This program resides in /home/flag14/flag14 . It encrypts input and writes it to standard output. An encrypted token file is also in that home directory, decrypt it :)This time we will have to figure out how the encryption routine works to come up with a decryption routine in order to decrypt the token.
The encryption algorithm turns out to be so easy that you can figure it out by simply experimenting with the binary. But if we were to employ a systematic approach, we'd have to analyze the binary, which is exactly what we will do. This time we'll use objdump as our disassembler. Using objdump -D to disassemble, we find that the encryption routine lies in <main>:
level14@nebula:~$ objdump -dMintel ~flag14/flag14 /home/flag14/flag14: file format elf32-i386 ... 08048464 <main>: ... 8048482: c7 44 24 2c 00 00 00 mov DWORD PTR [esp+0x2c],0x0 ... 80484e1: 90 nop 80484e2: c7 44 24 08 40 00 00 mov DWORD PTR [esp+0x8],0x40 80484e9: 00 80484ea: 8d 44 24 3c lea eax,[esp+0x3c] 80484ee: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 80484f2: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 80484f9: e8 52 fe ff ff call 8048350 <read@plt> 80484fe: 89 44 24 34 mov DWORD PTR [esp+0x34],eax 8048502: 83 7c 24 34 00 cmp DWORD PTR [esp+0x34],0x0 8048507: 7f 0c jg 8048515 <main+0xb1> 8048509: c7 04 24 00 00 00 00 mov DWORD PTR [esp],0x0 8048510: e8 6b fe ff ff call 8048380 <exit@plt> 8048515: c7 44 24 30 00 00 00 mov DWORD PTR [esp+0x30],0x0 804851c: 00 804851d: eb 29 jmp 8048548 <main+0xe4> 804851f: 8d 44 24 3c lea eax,[esp+0x3c] 8048523: 03 44 24 30 add eax,DWORD PTR [esp+0x30] 8048527: 0f b6 00 movzx eax,BYTE PTR [eax] 804852a: 89 c2 mov edx,eax 804852c: 8b 44 24 2c mov eax,DWORD PTR [esp+0x2c] 8048530: 01 d0 add eax,edx 8048532: 89 c2 mov edx,eax 8048534: 8d 44 24 3c lea eax,[esp+0x3c] 8048538: 03 44 24 30 add eax,DWORD PTR [esp+0x30] 804853c: 88 10 mov BYTE PTR [eax],dl 804853e: 83 44 24 2c 01 add DWORD PTR [esp+0x2c],0x1 8048543: 83 44 24 30 01 add DWORD PTR [esp+0x30],0x1 8048548: 8b 44 24 30 mov eax,DWORD PTR [esp+0x30] 804854c: 3b 44 24 34 cmp eax,DWORD PTR [esp+0x34] 8048550: 7c cd jl 804851f <main+0xbb> 8048552: 8b 44 24 34 mov eax,DWORD PTR [esp+0x34] 8048556: 89 44 24 08 mov DWORD PTR [esp+0x8],eax 804855a: 8d 44 24 3c lea eax,[esp+0x3c] 804855e: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 8048562: c7 04 24 01 00 00 00 mov DWORD PTR [esp],0x1 8048569: e8 32 fe ff ff call 80483a0 <write@plt> 804856e: 89 44 24 38 mov DWORD PTR [esp+0x38],eax 8048572: 83 7c 24 38 00 cmp DWORD PTR [esp+0x38],0x0 8048577: 0f 8f 64 ff ff ff jg 80484e1 <main+0x7d> ...The above is the C equivalent of a for loop inside a do-while loop. The input is being read in 64 (0x40) byte chunks, then each byte is added the value of it's (global) offset. (by global offset I mean that the offset is preserved across different chunks.)
The C equivalent code would look like:
int c = 0; int i; int rd; unsigned char buffer[64]; do { rd = read(STDIN_FILENO, buffer, sizeof(buffer)); if(rd <= 0) exit(0); for(i = 0; i < rd; i++) buffer[i] += c++; } while(write(STDOUT_FILENO, buffer, rd) > 0);Like I said, we could deduce the above routine by using purely observational analysis:
level14@nebula:~$ ~flag14/flag14 -e AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno9Constructing the decryption routine consists of changing the += to -=
If you've noticed, we can reuse the flag14 binary to do the decryption for us by applying a simple patch here:
8048530: 01 d0 add eax,edx 8048532: 89 c2 mov edx,eaxWe could change the add to a sub, but then we'd have to negate the result (because we would essentially be computing c - buffer[i], while we need -(c - buffer[i]) = buffer[i] - c). But we can't fit the 'neg eax' (2 bytes) and still put the result in edx. We'll have to come up with a better patch.
What if we could simply patch in 'sub edx, eax' and nop out the 'mov edx, eax' that follows? 2 bytes for the sub and 2 bytes for the nops, seems good.
But we can still do better... We can nop out the 'add eax, edx' and put the 'sub edx, eax' instead of 'mov edx, eax'. That's still 4 bytes, but notice that we can reuse the ModR/M byte of the mov instruction for our sub. That's 3 bytes:
level14@nebula:~$ # nop = 0x90 level14@nebula:~$ # sub edx, eax = 0x29 0xc2 level14@nebula:~$ echo -ne '\x90\x90\x29' > patch level14@nebula:~$ cp ~flag14/flag14 flag14_decrypt level14@nebula:~$ dd if=patch of=flag14_decrypt bs=1 seek=1328 conv=notrunc 3+0 records in 3+0 records out 3 bytes (3 B) copied, 0.000137174 s, 21.9 kB/s level14@nebula:~$ ./flag14_decrypt -e < ~flag14/token 8457c118-887c-4e40-a5a6-33a25353165 ▒level14@nebula:~$ su flag14 -c getflag Password: You have successfully executed getflag on a target accountWe got another flag for just 3 bytes ;)
~ Dmitry
No comments:
Post a Comment