Guest User

Untitled

a guest
Jan 24th, 2011
559
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /**
  2.  *
  3.  *  ___         _____
  4.  * |   |  ____ /
  5.  * |---  |____ |____,  ____
  6.  * |   \ |____      |  ---- PIRE!
  7.  * |    \      _____/
  8.  *
  9.  * res-pire : open source re-implementation of stupid x-pire.net
  10.  *
  11.  * this file handles the whole decryption. it is such an incredible
  12.  * mess, i immediately feel sick by just looking at it. however,
  13.  * written in <1h and it works like a charm.
  14.  *
  15.  * to compile, don't forget to link:
  16.  * -ljpeg   : libjpeg for parsing input (encrypted) image
  17.  * -lcurl   : libcurl for querying the keyserver
  18.  * -lcrypto : openssl for decryption
  19.  *
  20.  * Also, you won't notice, but this is actually C++ code. but i
  21.  * felt like hacking so....anyways, you should compile using a
  22.  * c++ compiler, nevertheless :P
  23.  *
  24.  * THIS IS A "PROTOTYPE"
  25.  * consider this as a prototype to use as a base for further
  26.  * development (in case there was a use for further developent...)
  27.  *
  28.  * Still ToDo (naa, rather not)
  29.  * = Handle CAPTCHAs
  30.  * = Locally store (cache) keys
  31.  * = I think for facebook/stuff there is an additional step
  32.  *   of reed-solomon FEC required. Whatever.
  33.  *
  34.  *
  35.  **/
  36. #include <cstdio>
  37. #include <cstdlib>
  38. #include <cstring>
  39. #include <jpeglib.h>
  40. #include <openssl/evp.h>
  41. #include <openssl/sha.h>
  42. #include <curl/curl.h>
  43.  
  44. /* -------------- JPEG STUFF -------------------- */
  45. const static JOCTET EOI_BUFFER[1] = { JPEG_EOI };
  46. struct my_source_mgr {
  47.     struct jpeg_source_mgr  pub;
  48.     const JOCTET            *data;
  49.     size_t                  len;
  50. };
  51.  
  52. static void my_init_source(j_decompress_ptr cinfo) {}
  53.  
  54. static boolean my_fill_input_buffer(j_decompress_ptr cinfo) {
  55.     my_source_mgr* src = (my_source_mgr*)cinfo->src;
  56.     src->pub.next_input_byte = EOI_BUFFER;
  57.     src->pub.bytes_in_buffer = 1;
  58.     return TRUE;
  59. }
  60. static void my_skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
  61.     my_source_mgr* src = (my_source_mgr*)cinfo->src;
  62.     if (src->pub.bytes_in_buffer < (unsigned long)num_bytes) {
  63.         src->pub.next_input_byte = EOI_BUFFER;
  64.         src->pub.bytes_in_buffer = 1;
  65.     } else {
  66.         src->pub.next_input_byte += num_bytes;
  67.         src->pub.bytes_in_buffer -= num_bytes;
  68.     }
  69. }
  70. static void my_term_source(j_decompress_ptr cinfo) {}
  71.  
  72. static void my_set_source_mgr(j_decompress_ptr cinfo, const char* data, size_t len) {
  73.     my_source_mgr* src;
  74.     if (cinfo->src == 0) { // if this is first time;  allocate memory
  75.         cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small)
  76.             ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr));
  77.     }
  78.     src = (my_source_mgr*) cinfo->src;
  79.     src->pub.init_source = my_init_source;
  80.     src->pub.fill_input_buffer = my_fill_input_buffer;
  81.     src->pub.skip_input_data = my_skip_input_data;
  82.     src->pub.resync_to_restart = jpeg_resync_to_restart; // default
  83.     src->pub.term_source = my_term_source;
  84.     // fill the buffers
  85.     src->data = (const JOCTET *)data;
  86.     src->len = len;
  87.     src->pub.bytes_in_buffer = len;
  88.     src->pub.next_input_byte = src->data;
  89. }
  90.  
  91.  
  92. /* -------------- CURL STUFF -------------------- */
  93. struct curlreq_mem {
  94.     char *memory;
  95.     size_t size;
  96. };
  97. static size_t curlreq_mem_cb(void *ptr, size_t size, size_t nmemb, void *data) {
  98.     size_t realsize = size*nmemb;
  99.     struct curlreq_mem *mem = (struct curlreq_mem*)data;
  100.     if(NULL==mem->memory) {
  101.         mem->memory = (char*)malloc(realsize+1);
  102.         mem->size = 0;
  103.     } else {
  104.         mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
  105.     }
  106.     if(NULL==mem->memory) {
  107.         fprintf(stderr, "ARGH MEMORY ISSUE WITH CURL!\n");
  108.         exit(-1);
  109.     }
  110.     memcpy( &(mem->memory[mem->size]), ptr, realsize );
  111.     mem->size += realsize;
  112.     mem->memory[mem->size] = 0;
  113.     return realsize;
  114. }
  115.  
  116. /* -------------- Main Code -------------------- */
  117.  
  118. int main(int argc, char* argv[]) {
  119.     if(argc<2) {
  120.         fprintf(stderr,"%s <filename>\n", argv[0]);
  121.         return 1;
  122.     }
  123.  
  124.  
  125.     FILE *fd = fopen(argv[1], "r");
  126.     if(!fd) {
  127.         return 1;
  128.     }
  129.  
  130.     /* completely read file to memory */
  131.     fseek(fd, 0L, SEEK_END);
  132.     long total_size = ftell(fd);
  133.     fseek(fd, 0L, SEEK_SET);
  134.  
  135.     char *buffer = new char[total_size];
  136.     long left = total_size;
  137.     char *p = buffer;
  138.     while(left) {
  139.         size_t done = fread(p, 1, left, fd);
  140.         if(0==done) {
  141.             break;
  142.         }
  143.         p += done;
  144.         left -= done;
  145.     }
  146.     fclose(fd);
  147.     if(left) {
  148.  
  149.         delete [] buffer;
  150.         return 1;
  151.     }
  152.  
  153.     unsigned image_id = 0;
  154.     char *server_address;
  155.     char *encrypted_data = NULL;
  156.     unsigned encrypted_data_length = 0;
  157.     char *decrypted_image = NULL;
  158.     unsigned decrypted_len = 0;
  159.  
  160.     char *key_in;
  161.  
  162.     unsigned char md[SHA256_DIGEST_LENGTH];
  163.     unsigned char md_string[2*SHA256_DIGEST_LENGTH];
  164.  
  165.     /** let libjpeg parse **/
  166.     {
  167.         struct jpeg_decompress_struct cinfo;
  168.         struct jpeg_error_mgr jerr;
  169.         cinfo.err = jpeg_std_error(&jerr);
  170.         jpeg_create_decompress(&cinfo);
  171.         my_set_source_mgr(&cinfo, buffer, total_size);
  172.  
  173.         jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
  174.  
  175.         jpeg_read_header(&cinfo, TRUE);
  176.         /* process markers */
  177.         int count = 0;
  178.         {
  179.             jpeg_saved_marker_ptr marker;
  180.             for(marker=cinfo.marker_list; marker!=NULL; marker=marker->next) {
  181.                 if(marker->marker == JPEG_COM) {
  182.                     switch(count++) {
  183.                         case 0: // ID
  184.                             image_id = atoi((const char*)marker->data);
  185.                             break;
  186.                         case 1: // Server-Address
  187.                             server_address = (char*)malloc(marker->data_length+1);
  188.                             memcpy(server_address, marker->data, marker->data_length);
  189.                             server_address[marker->data_length]=0;
  190.                             break;
  191.                         case 2: // unknown
  192.                             break;
  193.                         case 3: // encrypted image
  194.                             encrypted_data = (char*)malloc(marker->data_length);
  195.                             memcpy(encrypted_data, marker->data, marker->data_length);
  196.                             encrypted_data_length = marker->data_length;
  197.                             break;
  198.                     }
  199.                 }
  200.             }
  201.         }
  202.     }
  203.     printf(">> marker_id = %d\n", image_id);
  204.     printf(">> server = %s\n", server_address);
  205.  
  206.     /** compute hash of encrypted data **/
  207.     {
  208.         SHA256_CTX ctx;
  209.         //unsigned char md[SHA256_DIGEST_LENGTH];
  210.         SHA256_Init(&ctx);
  211.         SHA256_Update(&ctx, encrypted_data, encrypted_data_length);
  212.         SHA256_Final(md, &ctx);
  213.         for(int i=0; i<SHA256_DIGEST_LENGTH; ++i) {
  214.             printf("%02X",md[i]);
  215.             sprintf((char*)&md_string[2*i], "%02x", md[i]);
  216.         }
  217.         printf("\n");
  218.     }
  219.  
  220.     /** request key from server **/
  221.     {
  222.         struct curlreq_mem mtmp;
  223.         //mtmp.memory = (char*)malloc(1);
  224.         mtmp.memory = NULL;
  225.  
  226.         CURL *curl;
  227.         curl_global_init(CURL_GLOBAL_ALL);
  228.         curl = curl_easy_init();
  229.  
  230.         char url[512];
  231.         sprintf(url, "%s/api/get_key.json?key_id=%d&image_hash=%s", server_address, image_id, md_string);
  232.         printf(">> url->%s\n", url);
  233.  
  234.         curl_easy_setopt(curl, CURLOPT_URL, url);
  235.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
  236.         curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
  237.        
  238.         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlreq_mem_cb);
  239.         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&mtmp);
  240.  
  241.         curl_easy_perform(curl);
  242.  
  243.         //printf("DONE!\n%s\n", mtmp.memory);
  244.  
  245.         /* extract key */
  246.         /* ("parse" json) */
  247.         char *ptr = mtmp.memory;
  248.         while(ptr<mtmp.memory+mtmp.size && memcmp(ptr, "\"key\":", 6))
  249.             ptr++;
  250.         if(ptr<mtmp.memory+mtmp.size) {
  251.             ptr += 7;
  252.             char *ptr_start = ptr;
  253.             char *ptr_end = ptr+1;
  254.             while(ptr_end<mtmp.memory+mtmp.size && *ptr_end!='\"')
  255.                 ptr_end++;
  256.             if(ptr_end>=mtmp.memory+mtmp.size) {
  257.                 printf("error parsing key from json :(\n");
  258.                 exit(-1);
  259.             }
  260.             unsigned len = ptr_end - ptr_start;
  261.             key_in = (char*)malloc(len+1);
  262.             memcpy(key_in, ptr_start, len);
  263.             key_in[len]=0;
  264.  
  265.         } else {
  266.             printf("Could not get key from server! :(\n");
  267.             exit(-1);
  268.         }
  269.  
  270.         curl_easy_cleanup(curl);
  271.         curl_global_cleanup();
  272.     }
  273.  
  274.     printf(">> key=%s\n", key_in);
  275.  
  276.     unsigned char aes_key[16];
  277.     unsigned char aes_iv[16];
  278.  
  279.     /** derive AES key + decrypt **/
  280.     {
  281.         unsigned len = strlen(key_in);
  282.  
  283.         const EVP_CIPHER *type = EVP_aes_128_cbc();
  284.         EVP_BytesToKey(type, EVP_sha1(), NULL, (const unsigned char*)key_in, len, 5, aes_key, aes_iv);
  285.  
  286.         unsigned char *decrypted = (unsigned char*)malloc(encrypted_data_length);
  287.         int p_len = encrypted_data_length;
  288.         int f_len;
  289.  
  290.         EVP_CIPHER_CTX ctx;
  291.         EVP_CIPHER_CTX_init(&ctx);
  292.         EVP_DecryptInit_ex(&ctx, type, NULL, aes_key, aes_iv);
  293.         EVP_DecryptUpdate(&ctx, decrypted, &p_len, (const unsigned char*)encrypted_data, encrypted_data_length);
  294.         EVP_DecryptFinal(&ctx, decrypted+p_len, &f_len);
  295.  
  296.         /* sanity check if JPEG file */
  297.         unsigned SOI = *((unsigned*)decrypted);
  298.  
  299.         if(SOI==0xE0FFD8FF||SOI==0xFFD8FFE0) { // i'm cool so i care for the big endians around ;)
  300.             printf("valid JPEG decrypted, hurray\n");
  301.         } else {
  302.             printf("decryption failed :(\n");
  303.             exit(-1);
  304.         }
  305.  
  306.         decrypted_image = (char*)decrypted;
  307.         decrypted_len = p_len;
  308.     }
  309.  
  310.     /** write output **/
  311.     {
  312.         FILE *fd = fopen("output.jpg", "w");
  313.         char *ptrout = decrypted_image;
  314.         size_t left = decrypted_len;
  315.  
  316.         while(left) {
  317.             size_t w = fwrite(ptrout, 1, left, fd);
  318.             if(!w) break;
  319.             left -= w;
  320.             ptrout+= w;
  321.         }
  322.         fclose(fd);
  323.     }
  324.  
  325.     return 0;
  326. }
RAW Paste Data