From 7868b86e48d053a4ddec90c4562bf26022b8be16 Mon Sep 17 00:00:00 2001 From: snow flurry Date: Tue, 17 Nov 2020 13:45:15 -0800 Subject: [PATCH] corrupt: upload the corruption bits ... These were supposed to be uploaded a while ago --- src/corrupt.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/corrupt.h | 10 +++++ 2 files changed, 123 insertions(+) create mode 100644 src/corrupt.c create mode 100644 src/corrupt.h diff --git a/src/corrupt.c b/src/corrupt.c new file mode 100644 index 0000000..2be7b33 --- /dev/null +++ b/src/corrupt.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include + +#include "config.h" +#include "corrupt.h" +#include "debug.h" +#include "dosfs.h" + +static uint32_t xs_rand(uint32_t); +static uint32_t xs_randb(uint32_t *, uint32_t, uint32_t); + +/* + * Finds the rule (if any) that matches the given file. If no rule + * matches, the function returns NULL. + */ +config_t * +match_rule(config_t *conf, dosfile_t *file) +{ + config_t *cur; + int match; + + for (cur = conf; cur != NULL; cur = cur->next) { + match = 0; + match += ((cur->filename[0] == '*' && cur->filename[1] == 0) || + (!strncmp(cur->filename, file->fname, 8))); + + match += ((cur->ext[0] == '*' && cur->ext[1] == 0) || + (!strncmp(cur->ext, file->fext, 3))); + + if (match >= 2) + return cur; + } + + return NULL; +} + +/* + * Corrupts the given dosfile_t according to conf. + */ +int +corrupt_file(dosfs_t *fsd, dosfile_t *file, config_t *conf, uint32_t *state) +{ + uint32_t off; + int real_off; + unsigned char c; + struct conf_opts_t opts; + + opts = conf->opts; + for (off = conf->start; (off < conf->end) && (off < file->ent.size); + off += xs_randb(state, conf->skip_a, conf->skip_b)) { + real_off = get_byte_offset(fsd, file, off); + if (real_off < 0) { + DPRINTF(("get_byte_offset returned %s", strerror(real_off * -1))); + return 0; + } + + if (pread(fsd->ifd, &c, 1, real_off) == -1) { + perror("file read failed"); + return 1; + } + + /* + * The fun part! Originally the plan was to check for each + * function (i.e., "is it zero or not") before running the + * operations, but zero shift, add, and xor should be just as + * efficient as a bunch of if statements. Might be flawed + * logic, let me know if it is! + */ + c = c >> opts.shr; + c = c << opts.shl; + c += opts.add; + c ^= opts.bit_xor; + + if (pwrite(fsd->ifd, &c, 1, real_off) == -1) { + perror("file write failed"); + return 1; + } + } + + return 0; +} + +/* + * Generates a random number within two bounds. + */ +static uint32_t +xs_randb(uint32_t *state, uint32_t lower, uint32_t upper) +{ + *state = xs_rand(*state); + /* if we're already between, just roll with it */ + if (*state <= upper && *state >= lower) { + return *state; + } + return ((*state % (upper - lower)) + lower); +} + +/* + * Implement xorshift for randomness + */ +static uint32_t +xs_rand(uint32_t in) +{ + uint32_t out; + + out = in; + out ^= in << 13; + out ^= out >> 17; + out ^= out << 5; + return out; +} diff --git a/src/corrupt.h b/src/corrupt.h new file mode 100644 index 0000000..6bdebf8 --- /dev/null +++ b/src/corrupt.h @@ -0,0 +1,10 @@ +#ifndef _CORRUPT_H +#define _CORRUPT_H + +#include "config.h" +#include "dosfs.h" + +config_t *match_rule(config_t *, dosfile_t *); +int corrupt_file(dosfs_t *, dosfile_t *, config_t *, uint32_t *); + +#endif /* !_CORRUPT_H */