Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Automosher - Bruteforce by datamoshing
- * Author : Ely
- *
- * Compile with : -lturbojpeg (sudo apt-get install libjpeg-turbo8-dev)
- * run : ./automosh <muselk_orig_imgur.jpg> <sombra_reaper.jpg>
- *
- * In case you don't have it : https://s9.postimg.io/fkgu9v8bx/muselk_orig_imgur.jpg
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdint.h>
- #include <turbojpeg.h>
- // First byte in muselk's imgur jpeg that could modify the first block
- #define FIRST_TRY 62010
- // Offset in the decoded RGB of the first 8x8 block modified by sombra
- #define FIRST_BLOCK 785544
- // Raw RGB pic size for 1920x1100. Too lazy to check what jpeg turbo tells me.
- #define PIC_SIZE 6336000
- // Any block with a difference under this threshold will be considered good and not evaluated
- #define THRESHOLD_GOOD 300
- // Maximum allowed difference when trying to solve a block with '!'
- #define THRESHOLD_OK_SOLUTION 240
- long getFileSize(FILE* f) {
- fseek(f, 0, SEEK_END);
- long fsize = ftell(f);
- fseek(f, 0, SEEK_SET);
- return fsize;
- }
- unsigned char* readFile(char* filename, long* fsize) {
- FILE* f = fopen(filename, "rb");
- *fsize = getFileSize(f);
- unsigned char *content = malloc(*fsize + 1);
- fread(content, *fsize, 1, f);
- fclose(f);
- printf("Read %ld bytes from %s \n", *fsize, filename);
- return content;
- }
- void writeFile(char* filename, const unsigned char* data, long length) {
- FILE* f = fopen(filename, "w+");
- fwrite(data, 1, length, f);
- fclose(f);
- }
- // Quick & Dirty jpeg decode
- void decodeJpeg(const unsigned char *origJpeg, long sizeOrig, unsigned char* decodedOrig, long sizeDecoded) {
- int jpegSubsamp, width, height;
- tjhandle _jpegDecompressor = tjInitDecompress();
- tjDecompressHeader2(_jpegDecompressor, origJpeg, sizeOrig, &width, &height, &jpegSubsamp);
- tjDecompress2(_jpegDecompressor, origJpeg, sizeOrig, decodedOrig, width, 0/*pitch*/, height, TJPF_RGB, TJFLAG_ACCURATEDCT);
- tjDestroy(_jpegDecompressor);
- }
- // Returns the sum of the squared differences between pixels in two 8x8 blocks that share the same offset
- int get8x8Diff(const unsigned char* prev, const unsigned char* next, int offset) {
- int diff = 0;
- for (int i = 0; i < 8; ++i) {
- int start = offset+i*1920*3;
- for (int j = 0; j < 24; ++j) {
- int index = start+j;
- diff += (prev[index] - next[index])*(prev[index] - next[index]);
- }
- }
- return diff;
- }
- // Tells us whether or not a block was modified by one of our attempt to add a '!' somewhere
- int wasModded(const unsigned char* prev, const unsigned char* next, unsigned int offset) {
- int diff = 0;
- for (int i = 0; i < 8; ++i) {
- int start = offset+i*1920*3;
- for (int j = 0; j < 24; ++j) {
- int index = start+j;
- if (prev[index] != next[index])
- return 1;
- }
- }
- return 0;
- }
- int main (int argc, char* argv[]) {
- long jpegLength;
- long decodedLength;
- if (argc != 3) {
- printf("USAGE : %s <muselk_orig_imgur.jpg> <sombra-datamosh.jpg>\n", argv[0]);
- return EXIT_FAILURE;
- }
- unsigned char* origJpeg = readFile(argv[1], &jpegLength);
- const unsigned char* sombraJpeg = readFile(argv[2], &decodedLength);
- const unsigned char* decodedMosh = malloc(PIC_SIZE);
- decodeJpeg(sombraJpeg, decodedLength, decodedMosh, PIC_SIZE);
- unsigned char* decodedPrev = malloc(PIC_SIZE);
- unsigned char* decodedNext = malloc(PIC_SIZE);
- char filename[32] = {0};
- unsigned int firstTry = FIRST_TRY;
- // Note : this will scan the whole image, although you won't find anything after the start.
- for (unsigned int block = FIRST_BLOCK; block < PIC_SIZE ; block += 24) {
- // If the condition is true, we have passed a new line. Need to add 7 lines
- // to the current offset to match the next 8x8 block
- if ((block / 5760) % 8) {
- printf("New line !\n");
- block += 40320;
- }
- decodeJpeg(origJpeg, jpegLength, decodedPrev, PIC_SIZE);
- int bestDiff = get8x8Diff(decodedPrev, decodedMosh, block);
- if (bestDiff <= THRESHOLD_GOOD)
- continue;
- printf("Trying out block offset %u ; diff = %d\n", block, bestDiff);
- int bestValue = -1;
- int bestOffset = 0;
- for (unsigned int i = firstTry; i < firstTry+2000; ++i) {
- unsigned char before = origJpeg[i];
- if (before == '!')
- continue;
- origJpeg[i] = '!';
- decodeJpeg(origJpeg, jpegLength, decodedNext, PIC_SIZE);
- if (!wasModded(decodedNext, decodedPrev, block)) {
- origJpeg[i] = before;
- continue;
- }
- int newDiff = get8x8Diff(decodedNext, decodedMosh, block);
- if (newDiff <= THRESHOLD_OK_SOLUTION && newDiff < bestDiff) {
- bestValue = i;
- bestDiff = newDiff;
- }
- origJpeg[i] = before;
- }
- if (bestValue != -1) {
- printf("Best diff at %d : %d\n", bestValue, bestDiff);
- printf("Commiting '!' replacement at %08X, previous : %c (0x%02X)\n", (unsigned int)bestValue, origJpeg[bestValue], origJpeg[bestValue]);
- origJpeg[bestValue] = '!';
- decodeJpeg(origJpeg, jpegLength, decodedPrev, PIC_SIZE);
- sprintf(filename, "out-%06X.jpg", bestValue);
- writeFile(filename, origJpeg, jpegLength);
- memcpy(decodedPrev, decodedNext, PIC_SIZE);
- firstTry = bestValue + 1;
- }
- }
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement