From ed8aefcec6235b5c70bf014699ccc3c4c6a43d80 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Tue, 27 Jan 2009 14:39:41 +0200 Subject: Wrote first version of corrupt. --- corrupt.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 corrupt.c (limited to 'corrupt.c') diff --git a/corrupt.c b/corrupt.c new file mode 100644 index 0000000..f8c5cd2 --- /dev/null +++ b/corrupt.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2009 Lars Wirzenius + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#define _LARGEFILE64_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Choose a random integer in [0..n-1]. */ +static long choose(long n) +{ + if (n == 0) + return 0; + + long buckets = (RAND_MAX + 1L) / n; + long max = buckets * n; + long r; + + do { + r = random(); + } while (r >= max); + return r / buckets; +} + + +static int corrupt(const char *filename) +{ + int fd; + struct stat st; + + fd = open(filename, O_RDWR | O_LARGEFILE); + if (fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", filename, strerror(errno)); + return -1; + } + + if (fstat(fd, &st) == -1) { + fprintf(stderr, "Can't find length of %s: %s", filename, + strerror(errno)); + return -1; + } + + long offset = choose(st.st_size); + long bit = choose(CHAR_BIT); + printf("%s: offset=%ld bit=%ld\n", filename, offset, bit); + + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { + fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); + return -1; + } + + unsigned char byte; + if (read(fd, &byte, 1) == -1) { + fprintf(stderr, "Can't read %s: %s", filename, strerror(errno)); + return -1; + } + + /* This is where we toggle the bit. */ + unsigned mask = 1 << bit; // All zeroes, except for the interesting bit. + unsigned interesting = byte & mask; // Only the interesting bit can be 1. + unsigned toggled = interesting ^ mask; // Interesting bit has been toggled. + unsigned others = byte & (~mask); // Interesting bit is 0. + byte = others | toggled; + + /* Now write it back. */ + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) { + fprintf(stderr, "Can't seek in %s: %s", filename, strerror(errno)); + return -1; + } + if (write(fd, &byte, 1) != 1) { + fprintf(stderr, "Can't write %s: %s", filename, strerror(errno)); + return -1; + } + + if (close(fd) == -1) { + fprintf(stderr, "Can't close %s: %s", filename, strerror(errno)); + return -1; + } + + return 0; +} + + +int main(int argc, char **argv) +{ + int exit_code; + + srandom(time(NULL) + getpid()); + exit_code = 0; + for (int i = 1; i < argc; ++i) + if (corrupt(argv[i]) == -1) + exit_code = 1; + return exit_code; +} -- cgit v1.2.1