SHARE
TWEET

Untitled

a guest Jan 24th, 2011 419 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
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top