Advertisement
Guest User

Untitled

a guest
Feb 20th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.49 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4.  
  5. #define IMAGE_WIDTH  2048 // Nothing above 61 seen in images.dat
  6. #define IMAGE_HEIGHT 2048
  7.  
  8. uint8_t image[IMAGE_WIDTH*IMAGE_HEIGHT];
  9.  
  10. #ifdef WIN32
  11. #include <windows.h>
  12. BOOL make_executable(void* data, uint32_t size) {
  13.     DWORD old;
  14.     return VirtualProtect(data, size, PAGE_EXECUTE_READWRITE, &old);
  15. }
  16. #endif
  17.  
  18. #ifdef _MSC_VER
  19. void call_code(void* code) {
  20.     __asm {
  21.         pushad                      // code seems to expect some register to be preserved?
  22.         mov     edi, offset image   // image pointer
  23.         mov     edx, IMAGE_WIDTH    // stride
  24.         call    [code]
  25.         popad
  26.     }
  27. }
  28. #endif
  29.  
  30. void* read_file(const char* filename, uint32_t* size) {
  31.     FILE* fp = fopen(filename, "rb");
  32.     if (!fp) {
  33.         perror(filename);
  34.         return NULL;
  35.     }
  36.  
  37.     fseek(fp, 0L, SEEK_END);
  38.     *size = (uint32_t)ftell(fp);
  39.     fseek(fp, 0L, SEEK_SET);
  40.  
  41.     void* data = malloc(*size);
  42.     if (!data) {
  43.         fclose(fp);
  44.         return NULL;
  45.     }
  46.  
  47.     fread(data, *size, 1, fp);
  48.  
  49.     if (ferror(fp)) {
  50.         free(data);
  51.         data = NULL;
  52.     }
  53.     fclose(fp);
  54.     return data;
  55. }
  56.  
  57. int write_image(const char* filename, int w, int h) {
  58.     FILE* fp = fopen(filename, "wb");
  59.     if (!fp) {
  60.         perror(filename);
  61.         return 0;
  62.     }
  63.     fprintf(fp, "P6\n%d %d 255\n", w, h);
  64.     for (int y = 0; y < h; ++y) {
  65.         for (int x = 0; x < w; ++x) {
  66.             const uint8_t c = image[x+y*IMAGE_WIDTH];
  67.             fputc(c, fp);
  68.             fputc(c, fp);
  69.             fputc(c, fp);
  70.         }
  71.     }
  72.     fclose(fp);
  73.     return 1;
  74. }
  75.  
  76. //
  77. // Returns one past next 'ret' (0xC3) instruction
  78. //
  79. // Recognizes only the subset of x86 actually used and takes
  80. // as many shortcuts as possible
  81. uint8_t* find_end(uint8_t* start, uint8_t* end) {
  82.     while (start < end) {
  83.         uint8_t inst = *start++;
  84.         const int op_size = inst == 0x66; // Operand size prefix
  85.         if (op_size) inst = *start++;
  86.  
  87.         if ((inst&0xf0) == 0x40) {
  88.             // inc/dec r16/r32
  89.         } else if ((inst&0xf8) == 0xb0) {
  90.             // MOV r8, imm8
  91.             start++; // imm8
  92.         } else if ((inst&0xf8) == 0xb8) {
  93.             // MOV  r16/r32, imm16/imm32
  94.             start += op_size ? 2 : 4;
  95.         } else if (inst == 0x03) {
  96.             // ADD  r16/32  r/m16/32
  97.             start++; // MODR/M
  98.         } else if (inst == 0x83) {
  99.             // ALUOP r32, imm8
  100.             start++; // MODR/M
  101.             start++; // imm8
  102.         } else if (inst == 0x8a || inst == 0x8b) {
  103.             // MOV  r16/32  r/m16/32
  104.             const uint8_t modrm = *start++; // MODR/M
  105.             if (modrm&0x40) start++;
  106.         } else if (inst == 0x69) {
  107.             // IMUL r16/32  r/m16/32 imm16/32
  108.             start++; // MODR/M
  109.             start += op_size ? 2 : 4;
  110.         } else if (inst == 0x6b) {
  111.             // IMUL r16/32 r/m16/32 imm8
  112.             start++; // MODR/M
  113.             start++; // imm8
  114.         } else if (inst == 0x86) {
  115.             // XCHG r8, r/m8
  116.             start++; // MODR/M
  117.         } else if (inst == 0xaa) {
  118.             // stosb
  119.         } else if (inst == 0xab) {
  120.             // stosw/stosd
  121.         } else if (inst == 0xc3) {
  122.             // ret!
  123.             break;
  124.         } else {
  125.             printf("Unhandled instruction %02X\n", inst);
  126.             abort();
  127.         }
  128.     }
  129.     return start;
  130. }
  131.  
  132. int main() {
  133.     uint32_t size;
  134.     uint8_t* data = read_file("images.dat", &size);
  135.     if (!data) {
  136.         return 1;
  137.     }
  138.     if (!make_executable(data, size)) {
  139.         free(data);
  140.         return 2;
  141.     }
  142.     int cnt = 0, maxw = 0, maxh = 0;
  143.     // 4 byte header?
  144.     for (uint8_t* code = data + 4; code < data + size; ++cnt) {
  145.         memset(image, 0, sizeof(image));
  146.         call_code(code);
  147.         int w=0,h=0;
  148.         for (int y = 0; y < IMAGE_HEIGHT; ++y) {
  149.             for (int x = 0; x < IMAGE_WIDTH; ++x) {
  150.                 if (image[x+y*IMAGE_WIDTH]) {
  151.                     if (x > w) w = x + 1;
  152.                     if (y > h) h = y + 1;
  153.                 }
  154.             }
  155.         }
  156.         printf("%08X: %dx%d\n", code-data-4, w, h);
  157.         if (w > maxw) maxw = w;
  158.         if (h > maxh) maxh = h;
  159.  
  160.         char filename[32];
  161.         snprintf(filename, sizeof(filename), "img%06X.ppm", code-data);
  162.         write_image(filename, w, h);
  163.  
  164.         code = find_end(code, data + size);
  165.     }
  166.     printf("Max size: %d x %d\n", maxw, maxh);
  167.     free(data);
  168.     return 0;
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement