Warning: Undefined array key 1 in /var/www/wptbox/wp-content/plugins/coblocks/src/blocks/gist/index.php on line 27
Warning: Undefined array key 1 in /var/www/wptbox/wp-content/plugins/coblocks/src/blocks/gist/index.php on line 27
Here is another very interesting challenge from Rootme. The title says ELF – no software breakpoints.
Let’s run the file command and see.
% file ch20.bin ch20.bin: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped
The executable seemed to be striped.
Next I examined the sections in file and the .text section starts at 0x08048080
This is the disassembly of the text section. I spent some time trying to understand the logic. Well let’s see what this is 🙂
ch20.bin: file format elf32-i386
Disassembly of section .text:
08048080 <.text>:
8048080: b8 04 00 00 00 mov eax,0x4
8048085: bb 01 00 00 00 mov ebx,0x1
804808a: b9 a1 91 04 08 mov ecx,0x80491a1
804808f: ba 26 00 00 00 mov edx,0x26
8048094: cd 80 int 0x80
8048096: b8 03 00 00 00 mov eax,0x3
804809b: 31 db xor ebx,ebx
804809d: b9 88 91 04 08 mov ecx,0x8049188
80480a2: ba 33 00 00 00 mov edx,0x33
80480a7: cd 80 int 0x80
80480a9: 31 c9 xor ecx,ecx
80480ab: b8 80 80 04 08 mov eax,0x8048080
80480b0: bb 23 81 04 08 mov ebx,0x8048123
80480b5: e8 5b 00 00 00 call 0x8048115
80480ba: 89 ca mov edx,ecx
80480bc: b9 19 00 00 00 mov ecx,0x19
80480c1: b8 55 91 04 08 mov eax,0x8049155
80480c6: bb 88 91 04 08 mov ebx,0x8049188
80480cb: d1 ca ror edx,1
80480cd: 8a 44 08 ff mov al,BYTE PTR [eax+ecx*1-0x1]
80480d1: 8a 5c 0b ff mov bl,BYTE PTR [ebx+ecx*1-0x1]
80480d5: 30 d8 xor al,bl
80480d7: 30 d0 xor al,dl
80480d9: 75 1b jne 0x80480f6
80480db: 49 dec ecx
80480dc: 75 e3 jne 0x80480c1
80480de: b8 04 00 00 00 mov eax,0x4
80480e3: bb 01 00 00 00 mov ebx,0x1
80480e8: b9 24 91 04 08 mov ecx,0x8049124
80480ed: ba 26 00 00 00 mov edx,0x26
80480f2: cd 80 int 0x80
80480f4: eb 16 jmp 0x804810c
80480f6: b8 04 00 00 00 mov eax,0x4
80480fb: bb 01 00 00 00 mov ebx,0x1
8048100: b9 4a 91 04 08 mov ecx,0x804914a
8048105: ba 0b 00 00 00 mov edx,0xb
804810a: cd 80 int 0x80
804810c: b8 01 00 00 00 mov eax,0x1
8048111: 31 db xor ebx,ebx
8048113: cd 80 int 0x80
8048115: 29 c3 sub ebx,eax
8048117: 31 c9 xor ecx,ecx
8048119: 02 08 add cl,BYTE PTR [eax]
804811b: c1 c1 03 rol ecx,0x3
804811e: 40 inc eax
804811f: 4b dec ebx
8048120: 75 f7 jne 0x8048119
8048122: c3 ret
Let’s open in gdb and start debugging.
0x8048080: mov eax,0x4 0x8048085: mov ebx,0x1 0x804808a: mov ecx,0x80491a1 0x804808f: mov edx,0x26 0x8048094: int 0x80
It will first print the text “Welcome to Root-Me Challenges\r\nPass: ” using the write system call.
0x8048096: mov eax,0x3 0x804809b: xor ebx,ebx 0x804809d: mov ecx,0x8049188 0x80480a2: mov edx,0x33 0x80480a7: int 0x80
Next it will store the input in 0x8049188 using the read system call and store in ecx.
0x80480a9: xor ecx,ecx 0x80480ab: mov eax,0x8048080 0x80480b0: mov ebx,0x8048123 0x80480b5: call 0x8048115
Next it will store 0x8048080 which means the starting address of the text section in eax and the ending section 0x8048123 of the text section in ebx. Next it calls 0x8048115
0x8048115: sub ebx,eax 0x8048117: xor ecx,ecx 0x8048119: add cl,BYTE PTR [eax] 0x804811b: rol ecx,0x3 0x804811e: inc eax 0x804811f: dec ebx 0x8048120: jne 0x8048119 0x8048122: ret
Next it subtracts ebx by eax which results in the size of the text section which is 163. Zero outs the ecx register. Add each opcode of the program’s text section into the cl register. Rotate left ecx by 3 bits and store in ecx. Next increment to the next opcode in eax and decrement the counter. If ebx not equal to zero keep looping. As you can clearly see this is a loop which will rotate left each opcode of the text section and sum in the cl register. This seems to be calculating a checksum for the serial routine.
This is known anti debugging technique in which can’t place any software breakpoints in the application itself. Because when we hit a breakpoint in a user mode applications a 0xCC (INT 3) will be placed in the code, hence the calculation will be wrong and will generate a wrong checksum. So, while debugging even we enter the correct password we won’t be validated because the checksum will be wrong.
The problem arises in calculating the checksum. What I did was I extracted the opcodes of the text section like we extract shellcode 😉 Then we can calculate the checksum like in the program.
extern printf
extern exit
global main
section .text
main:
lea esi, [shellcode] ; load offset of shellcode
mov ebx, shellcode_len ; mov the len of shellcode
xor ecx, ecx ; Zero out ecx
_loop:
add cl, [esi] ; add opcode to cl
rol ecx, 0x3 ; Rotate left ecx by 3
inc esi ; incremenet esi
dec ebx ; decrement ebx
jnz _loop ; if ebx != 0 loop
push ecx ; push the result to stack
push fmt_checksum ; push the format string
call printf ; print it
mov ebx, [esp+4] ; mov the result from stack to ebx
add esp, 0x8 ; Clear the stack
push 1
call exit
section .data
fmt: db "Checksum: %x",0xa,0
shellcode:
db 0xb8,0x04,0x00,0x00,0x00,0xbb,0x01,0x00,0x00,0x00
db 0xb9,0xa1,0x91,0x04,0x08,0xba,0x26,0x00,0x00,0x00
db 0xcd,0x80,0xb8,0x03,0x00,0x00,0x00,0x31,0xdb,0xb9
db 0x88,0x91,0x04,0x08,0xba,0x33,0x00,0x00,0x00,0xcd
db 0x80,0x31,0xc9,0xb8,0x80,0x80,0x04,0x08,0xbb,0x23
db 0x81,0x04,0x08,0xe8,0x5b,0x00,0x00,0x00,0x89,0xca
db 0xb9,0x19,0x00,0x00,0x00,0xb8,0x55,0x91,0x04,0x08
db 0xbb,0x88,0x91,0x04,0x08,0xd1,0xca,0x8a,0x44,0x08
db 0xff,0x8a,0x5c,0x0b,0xff,0x30,0xd8,0x30,0xd0,0x75
db 0x1b,0x49,0x75,0xe3,0xb8,0x04,0x00,0x00,0x00,0xbb
db 0x01,0x00,0x00,0x00,0xb9,0x24,0x91,0x04,0x08,0xba
db 0x26,0x00,0x00,0x00,0xcd,0x80,0xeb,0x16,0xb8,0x04
db 0x00,0x00,0x00,0xbb,0x01,0x00,0x00,0x00,0xb9,0x4a
db 0x91,0x04,0x08,0xba,0x0b,0x00,0x00,0x00,0xcd,0x80
db 0xb8,0x01,0x00,0x00,0x00,0x31,0xdb,0xcd,0x80,0x29
db 0xc3,0x31,0xc9,0x02,0x08,0xc1,0xc1,0x03,0x40,0x4b
db 0x75,0xf7,0xc3
shellcode_len equ $-shellcode
The checksum is “ac77e166”
Let’s proceed and see knowing we will get a wrong checksum while inside the debugger.
0x80480ba: mov edx,ecx 0x80480bc: mov ecx,0x19 0x80480c1: mov eax,0x8049155 0x80480c6: mov ebx,0x8049188 0x80480cb: ror edx,1 0x80480cd: mov al,BYTE PTR [eax+ecx*1-0x1] 0x80480d1: mov bl,BYTE PTR [ebx+ecx*1-0x1] 0x80480d5: xor al,bl 0x80480d7: xor al,dl 0x80480d9: jne 0x80480f6 0x80480db: dec ecx 0x80480dc: jne 0x80480c1 0x80480de: mov eax,0x4 0x80480e3: mov ebx,0x1 0x80480e8: mov ecx,0x8049124 0x80480ed: mov edx,0x26 0x80480f2: int 0x80
Next we have the serial routine which is a loop that. The checksum will be moved to edx and ecx will contain 25 which is the length of our password. We see that eax contains 0x8049155 which is 25 bytes of the key.
The user entered password will be stored in ebx. The checksum edx will be rotated to right by 1 and stored in edx. Mov al, [eax+ecx*1-0x1] means the starting address of the key bytes + 25 which will point to the 25th byte of the key 0xe0. Likewise this will place the each byte starting from the last byte in descending order basically and place in the al register.
Every last byte of our entered password will be store in the bl register like the above. Next the key byte will XORed by the entered password byte. Next the result will be XORed by the checksum byte. If the result is not equal to zero we will jump to bad boy which is 0x80480f6. If not we keep on looping. If loop went successfully it will print the message 0x8049124 “Well done man, use this pass to flag!\n”
The program basically check like this:
Password ^ Key byte ^ Checksum == 0
To get the password basically we just have to XOR the checksum with the key byte.
Checksum ^ Key byte = Password
After looking at the application logic since we calculated the checksum before it was easy to apply the serial routine and get the password like in the program, Simple XOR logic 😉
I wrote the keygen using NASM. It’s self-explanatory.
Well, here’s the high level version of the keygen written in C. I have written in a way that it would compile under both the GNU C compiler and the Microsoft’s Visual C compiler. This is due to the way both compilers handle inline assembly in two different formats.
I hope this challenge was fun and interesting 🙂
You are damn good at it :>
Thank You 🙂
Fun reading rce again 😀
Write up much appreciated! Learned a lot from it.