# Reverse I (2)Points: 200Description (*Forgot to copy, all based on my memory*):```The file is corrupted, try to fix it. The decryptor will decrypt the file to JPEG image file. The image is not just a normal image, look carefully.```
We're given two file: 1. decryptor (ELF 64-bit executable)2. file (data)
Try run it:```bash./decryptor File is not valid```Try running ltrace:```ltrace ./decryptor fopen("file", "rb")                              = 0x5654b2cd32a0fseek(0x5654b2cd32a0, 0, 0, 13)                  = 0fread(0x7fff782f4340, 19000, 1, 0x5654b2cd32a0)  = 0ftello(0x5654b2cd32a0, 0x5654b2cd3490, 0x4777, 0xfbad24a8) = 0x4777memcmp(0x5654b0fec0f0, 0x7fff782f4290, 16, 0x5654b0fec0f0) = 140puts("File is not valid"File is not valid)                        = 18strlen("12345678")                               = 8MD5_Init(0x7fff782f4140, 0x7fff782f4280, 0x5654b0deb860, 32) = 1MD5_Update(0x7fff782f4140, 0x5654b0deb860, 8, 0x5654b0deb860) = 1MD5_Final(0x7fff782f41a0, 0x7fff782f4140, 0x7fff782f4140, 0x3837363534333231) = 1...strcmp("25d55ad283aa400af464c76d713c07ad"..., "\302<\032\367\255>812`\371&\344\004\310\341\350\325A;.\\7w\210\206>\376\tA\342:"...) = -144strlen("password")                               = 8MD5_Init(0x7fff782f4140, 0x7fff782f4280, 0x5654b0deb869, 9) = 1MD5_Update(0x7fff782f4140, 0x5654b0deb869, 8, 0x5654b0deb869) = 1MD5_Final(0x7fff782f41a0, 0x7fff782f4140, 0x7fff782f4140, 0x64726f7773736170) = 1...strcmp("5f4dcc3b5aa765d61d8327deb882cf99"..., "\302<\032\367\255>812`\371&\344\004\310\341\350\325A;.\\7w\210\206>\376\tA\342:"...) = -141strlen("qwertyuiop")                             = 10MD5_Init(0x7fff782f4140, 0x7fff782f4280, 0x5654b0deb872, 18) = 1MD5_Update(0x7fff782f4140, 0x5654b0deb872, 10, 0x5654b0deb872) = 1MD5_Final(0x7fff782f41a0, 0x7fff782f4140, 0x7fff782f4140, 0x706f697579747265) = 1...strcmp("6eea9b7ef19179a06954edd0f6c05ceb"..., "\302<\032\367\255>812`\371&\344\004\310\341\350\325A;.\\7w\210\206>\376\tA\342:"...) = -140strlen("passwrd123")                             = 10MD5_Init(0x7fff782f4140, 0x7fff782f4280, 0x5654b0deb87d, 29) = 1MD5_Update(0x7fff782f4140, 0x5654b0deb87d, 10, 0x5654b0deb87d) = 1MD5_Final(0x7fff782f41a0, 0x7fff782f4140, 0x7fff782f4140, 0x3332316472777373) = 1...strcmp("bd3304f768220a27d1ae92d9c332dbf8"..., "\302<\032\367\255>812`\371&\344\004\310\341\350\325A;.\\7w\210\206>\376\tA\342:"...) = -96strlen("123456789")                              = 9MD5_Init(0x7fff782f4140, 0x7fff782f4280, 0x5654b0deb888, 8) = 1MD5_Update(0x7fff782f4140, 0x5654b0deb888, 9, 0x5654b0deb888) = 1MD5_Final(0x7fff782f41a0, 0x7fff782f4140, 0x7fff782f4140, 0x3938373635343332) = 1...strcmp("25f9e794323b453885f5181f1b624d0b"..., "\302<\032\367\255>812`\371&\344\004\310\341\350\325A;.\\7w\210\206>\376\tA\342:"...) = -144puts("\n"
)                                       = 2fclose(0x5654b2cd32a0)                           = 0+++ exited (status 1) +++```Notice it calculate some MD5 hashes and strcmp it with something...
It's decompile it with Ghidra to understand more!
## DecompilingBecause it is stripped, so we look for the `entry` function:```cvoid entry(undefined8 uParm1,undefined8 uParm2,undefined8 uParm3)
{  undefined8 in_stack_00000000;  undefined auStack8 [8];   __libc_start_main(FUN_00100f80,in_stack_00000000,&stack0x00000008,FUN_001017b0,FUN_00101820,uParm3                    ,auStack8);  do {                    /* WARNING: Do nothing block with infinite loop */  } while( true );}```And the `main` function should be at `FUN_00100f80`
The main function quite long, I'll explain the main part only
*Note: I modified some code to make it more readable*### Analyze main function```cundefined8 FUN_00100f80(void){  int iVar1;  int iVar2;  FILE *__stream;  ulong current_position;  void *__s1;  long lVar5;  long in_FS_OFFSET;  int local_dffc;  int local_dff8;  int local_dff4;  int local_dff0;  uint local_dfec;  int local_dfe8;  int local_dfe4;  int local_dfe0;  char local_df98 [16];  ...  char local_df08 [32];  char buffer [19008];  char input [19008];  ...  long local_20;  // Open the file given put into stream  __stream = fopen("file","rb");  if (__stream != (FILE *)0x0) {    fseek(__stream,0,0);    // It reads 19K bytes but file contain only 18295 bytes    fread(buffer,19000,1,__stream);    // so the position should at the last character of file    current_position = ftello(__stream);    iVar1 = (int)current_position;
    // XOR the data with 1 and store in local_df88    xor("7dd`8c6dg08068`1",0x10,1,&local_df88);    // Copy first 16 bytes in buffer and store in s1    __s1 = copyFirst16Bytes(buffer);    // If s1 and local_df88 are the same     if (memcmp(__s1,&local_df88,0x10) == 0) {      // XOR the data with 1 and store in output      xor("7845dee1g7b14bdc",0x10,1,&output);      // Copy previous 16 bytes from current position      __s1 = copyPrevious16Bytes(buffer,current_position);      // If s1 and output are the same       if (memcmp(__s1,&output,0x10) == 0) {      	// So we must get here for valid file        puts("* File is valid");      }      else {        puts("* File is not valid");      }    }    else {      puts("File is not valid");    }     char* last = copyPrevious16Bytes(buffer,current_position);  	char* first = copyFirst16Bytes(buffer);  	// Concatenate first and last string    char* key = concatenate(first,last);    char* data[5] = {"12345678", "password","qwertyuiop","password123","123456789"}
    while (local_dff8 < 5) {   	  // Calculate the hash at data then store at hash      md5sum(data[local_dff8],hash);      // If key and hash are equal      if (strcmp(key,hash) == 0) {        local_dfe8 = 0;        local_dfe4 = 0x10;        // Copy the content without the key we append        while (local_dfe4 < current_position -0x10) {          input[local_dfe8] = fileContent[local_dfe4];          local_dfe8++;          local_dfe4++;        }        printf("[+] Decrypted File has been generated. (FinalDecryption.jpeg)");        memset(&output,0,19000);        // Decrypt the input using the data as the key        RC4_decrypt(data[local_dff8],current_position -0x20,                     input,&output);        // Write the output to FinalDecryption.jpeg        writeToFile(&output,current_position -0x20);      }      local_dff8++;    }    puts("\n");    fclose(__stream);}```From the code above, the condition of the valid file are:- First 16 bytes must equal to ```7dd`8c6dg08068`1``` XOR 1- Last 16 bytes must equal to `7845dee1g7b14bdc` XOR 1
The challenge said that the file is corrupted, so we must correct the file for first 16 bytes and last 16 bytes
But we not sure we need to append those bytes or replace those bytes..
Lets test it out with python!
### Replace to file
```pyfrom Crypto.Util.strxor import strxor# Cut first 16 bytes and last 16 bytesori  = open("original",'r').read()[16:-16]first = strxor("7dd`8c6dg08068`1","\x01"*16)last = strxor("7845dee1g7b14bdc","\x01"*16)# Write to fileopen("file",'w').write(first+ori+last)```Run it:```bashpython solve.py 
./decryptor * File is valid[+] Decrypted File has been generated. (FinalDecryption.jpeg)
file Final_decryption.jpeg Final_decryption.jpeg: data
xxd Final_decryption.jpeg | head00000000: d4a0 b6c8 696c 9335 e8fd c21e 04ab ba08  ....il.5........00000010: 3fc2 1dee 5b20 9ab4 a3d9 4110 245c 7111  ?...[ ....A.$\q.00000020: 1906 bcb6 b81f 1530 7237 430a e924 7cd6  .......0r7C..$|.00000030: e2ff 3419 6732 a877 c68c af0d f8e9 7c96  ..4.g2.w......|.00000040: 9472 a275 2d2a cacb 4a96 9cbe 0e50 c34a  .r.u-*..J....P.J00000050: 8c7d 174f dd84 aa4a 0d17 b623 7edf 62b8  .}.O...J...#~.b.00000060: 0178 098f f205 2f2d df0c 25fb c7c7 0baa  .x..../-..%.....00000070: 5d1d 8248 0de8 be94 ac6c 7dbe 39ae e574  ]..H.....l}.9..t00000080: 7c32 d5df 2a03 1c93 8f86 49cf 9ff6 f299  |2..*.....I.....00000090: 4eda f6e9 99ff 5bb4 5d15 06ad f73c 9d4c  N.....[.]....<.L```Not a JPEG file, next try append:
## Append to file```pyfrom Crypto.Util.strxor import strxorori  = open("original",'r').read()first = strxor("7dd`8c6dg08068`1","\x01"*16)last = strxor("7845dee1g7b14bdc","\x01"*16)
open("file",'w').write(first+ori+last)```Run it:```bashpython solve.py 
./decryptor * File is valid[+] Decrypted File has been generated. (FinalDecryption.jpeg)
file Final_decryption.jpeg Final_decryption.jpeg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=6, xresolution=86, yresolution=94, resolutionunit=2, datetime=2020:07:12 01:05:18], comment: "shellcode: \x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x6", baseline, precision 8, 700x366, components 3
```Can see it decrypted a JPEG file!!
The image just a door with some binary code:
![image1](test/Final_decryption.jpeg)
Notice there is a comment looks interesting:```comment: "shellcode: \x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x6"```Run `strings` on it to get the full code:```\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x19\x00\x00\x00\x65\x63\x68\x6f\x20\x2d\x6e\x65\x20\x54\x4d\x43\x54\x46\x7b\x67\x30\x30\x64\x77\x30\x72\x6b\x7d\x00\x56\x57\x48\x89\xe6\x0f\x05```Shellcode is also [machine code](https://en.wikipedia.org/wiki/Machine_code) only computer can understand (because 0 and 1)
Use Pwntools can convert to assembly code:```pycontext.arch = "amd64"print disasm("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x19\x00\x00\x00\x65\x63\x68\x6f\x20\x2d\x6e\x65\x20\x54\x4d\x43\x54\x46\x7b\x67\x30\x30\x64\x77\x30\x72\x6b\x7d\x00\x56\x57\x48\x89\xe6\x0f\x05")
```Result:```asm   0:   6a 3b                   push   0x3b   2:   58                      pop    rax   3:   99                      cdq       4:   48 bb 2f 62 69 6e 2f    movabs rbx,0x68732f6e69622f   b:   73 68 00    e:   53                      push   rbx   f:   48 89 e7                mov    rdi,rsp  12:   68 2d 63 00 00          push   0x632d  17:   48 89 e6                mov    rsi,rsp  1a:   52                      push   rdx  1b:   e8 19 00 00 00          call   0x39  20:   65 63 68 6f             movsxd ebp,DWORD PTR gs:[rax+0x6f]  24:   20 2d 6e 65 20 54       and    BYTE PTR [rip+0x5420656e],ch        # 0x54206598  2a:   4d                      rex.WRB  2b:   43 54                   rex.XB push r12  2d:   46 7b 67                rex.RX jnp 0x97  30:   30 30                   xor    BYTE PTR [rax],dh  32:   64 77 30                fs ja  0x65  35:   72 6b                   jb     0xa2  37:   7d 00                   jge    0x39  39:   56                      push   rsi  3a:   57                      push   rdi  3b:   48 89 e6                mov    rsi,rsp  3e:   0f 05                   syscall```Also can run it:```pyfrom pwn import *context.arch = "amd64"p = run_shellcode("\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x68\x2d\x63\x00\x00\x48\x89\xe6\x52\xe8\x19\x00\x00\x00\x65\x63\x68\x6f\x20\x2d\x6e\x65\x20\x54\x4d\x43\x54\x46\x7b\x67\x30\x30\x64\x77\x30\x72\x6b\x7d\x00\x56\x57\x48\x89\xe6\x0f\x05")print p.recv()	```And we get the flag!!!```[x] Starting local process '/tmp/pwn-asm-Eb7ELF/step3-elf'[+] Starting local process '/tmp/pwn-asm-Eb7ELF/step3-elf': pid 239648[*] Process '/tmp/pwn-asm-Eb7ELF/step3-elf' stopped with exit code 0 (pid 239648)-ne TMCTF{g00dw0rk}```
Just printing the shellcode also reveal the flag:```'j;X\x99H\xbb/bin/sh\x00SH\x89\xe7h-c\x00\x00H\x89\xe6R\xe8\x19\x00\x00\x00echo -ne TMCTF{g00dw0rk}\x00VWH\x89\xe6\x0f\x05'```Believe it is running syscall `execve` (rax=0x3b can checking in the [syscall table](https://filippo.io/linux-syscall-table/))
The command should be `/bin/sh -c "echo -ne TMCTF{g00dw0rk}"`
## Alternative solutionWe also can solve it without using the `decryptor` program
We know the key is the hash we appended to the file
The hash is `6eea9b7ef19179a06954edd0f6c05ceb`
That is MD5 hash of `qwertyuiop`! (One of the string in data)
Therefore, we can just decrypt the file with this key using python:```pyfrom arc4 import ARC4file = open("original",'rb').read()arc4 = ARC4('qwertyuiop')open("flag.jpeg",'wb').write(arc4.decrypt(file))```Flag.jpeg:
![image2](test/flag.jpeg)
[Python script](test/solve.py)
[Python script 2](test/solve2.py)
## Flag```TMCTF{g00dw0rk}```