【pwnable.kr】unlink - unlink4字节写,劫持ecx到堆中获取main_retaddr

2024-03-31 18:08

本文主要是介绍【pwnable.kr】unlink - unlink4字节写,劫持ecx到堆中获取main_retaddr,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

image-20181122152930920

题目信息

image-20181122154147635

直接看源码:

image-20181122174832515

这题思路很清晰,程序模拟了最简单的unlink过程,unlink的本质就是把中间的chunk从前后解链,同时修改前面chunk的fd和后面chunk的bk。如果可以溢出了会被unlink的chunk,32bit下在FD->bk=BK时,拥有一次4bit写的机会,同时需要保证BK->fd可写(BK->fd=FD同理)。

拥有任意地址写的机会后,可以考虑修改程序返回地址为shelladdr就可以拿shell。程序是如何返回的?main函数中ret时取返回地址的操作如下(见下图):

   0x80485ff <main+208>:        mov    ecx,DWORD PTR [ebp-0x4]0x8048602 <main+211>:        leave0x8048603 <main+212>:        lea    esp,[ecx-0x4]0x8048606 <main+215>:        ret

从[ebp-0x4]中取ecx后,从[ecx-4]的地方取出main_retaddr。

image-20181123101240616

如果要写main_retaddr为shell,需要控制unlink时FD=&main_retaddr(0xffffd60c)-4,控制BK为&shell,那么FD->bk=BK执行时 ,两边同时替换,&main_retaddr -4 +4= &shell,即*(&main_retaddr)=&shell。但是由于BK->fd=FD,&shell+0在.text不可写,因此BK不能为&shell。

那么是否可以考虑让BK是一个类似jmp &shell的地址呢?gdb中find 0xf7fc5000没有找到任何输出。因此直接修改main_retaddr不可行了。但是由于main_retaddr获取时是通过ecx这个栈上的指针来获取的,因此,我们通过unlink修改栈中ecx的值指向堆中(&shell的堆地址+4),这时BK->fd(&shell的堆地址+4+0)肯定可写,由于堆溢出,堆中的数据我们是可以伪造的,因此就可以劫持程序main_retaddr了。

exp

A栈地址是ebp-14h,ecx的栈地址是ebp-0x4。假设泄漏的A栈地址为leakAstack,因此unlink时ecx为leakAstack+0x10。要写ecxaddr,因此fakefd为ecxaddr-0x4。 A的堆地址为leakAheap(上图中是0x804b408),溢出时先在leakAheap+0x8处布置&shell,fakebk修改为leakAheap+0x8+0x4。

image-20181123120010892

exploit:

image-20181123121053918

image-20181123121315002

总结

unlink的题已经做过好几遍了,时隔一年再做的时候还是得想一下。本质是unlink 4byte写,由于main ret时通过栈上的ecx指针来获取main_retaddr,因此堆中布置&shell,unlink写ecx=(&shell的堆地址+4),fakefd=ecx-4,从而修改main_retaddr。

这篇关于【pwnable.kr】unlink - unlink4字节写,劫持ecx到堆中获取main_retaddr的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/864971

相关文章

字节面试 | 如何测试RocketMQ、RocketMQ?

字节面试:RocketMQ是怎么测试的呢? 答: 首先保证消息的消费正确、设计逆向用例,在验证消息内容为空等情况时的消费正确性; 推送大批量MQ,通过Admin控制台查看MQ消费的情况,是否出现消费假死、TPS是否正常等等问题。(上述都是临场发挥,但是RocketMQ真正的测试点,还真的需要探讨) 01 先了解RocketMQ 作为测试也是要简单了解RocketMQ。简单来说,就是一个分

Android Environment 获取的路径问题

1. 以获取 /System 路径为例 /*** Return root of the "system" partition holding the core Android OS.* Always present and mounted read-only.*/public static @NonNull File getRootDirectory() {return DIR_ANDR

JS和jQuery获取节点的兄弟,父级,子级元素

原文转自http://blog.csdn.net/duanshuyong/article/details/7562423 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。 JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元素。 <div id="test"><div></div><div></div

vcpkg子包路径批量获取

获取vcpkg 子包的路径,并拼接为set(CMAKE_PREFIX_PATH “拼接路径” ) import osdef find_directories_with_subdirs(root_dir):# 构建根目录下的 "packages" 文件夹路径root_packages_dir = os.path.join(root_dir, "packages")# 如果 "packages"

Weex入门教程之4,获取当前全局环境变量和配置信息(屏幕高度、宽度等)

$getConfig() 获取当前全局环境变量和配置信息。 Returns: config (object): 配置对象;bundleUrl (string): bundle 的 url;debug (boolean): 是否是调试模式;env (object): 环境对象; weexVersion (string): Weex sdk 版本;appName (string): 应用名字;

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

android两种日志获取log4j

android   log4j 加载日志使用方法; 先上图: 有两种方式: 1:直接使用架包 加载(两个都要使用); 架包:android-logging-log4j-1.0.3.jar 、log4j-1.2.15.jar  (说明:也可以使用架包:log4j-1.2.17.jar)  2:对架包输入日志的二次封装使用; 1:直接使用 log4j 日志框架获取日志信息: A:配置 日志 文

17 通过ref代替DOM用来获取元素和组件的引用

重点 ref :官网给出的解释是: ref: 用于注册对元素或子组件的引用。引用将在父组件的$refs 对象下注册。如果在普通DOM元素上使用,则引用将是该元素;如果在子组件上使用,则引用将是组件实例: <!-- vm.$refs.p will be the DOM node --><p ref="p">hello</p><!-- vm.$refs.child will be the c

跟我一起玩《linux内核设计的艺术》第1章(四)——from setup.s to head.s,这回一定让main滚出来!(已解封)

看到书上1.3的大标题,以为马上就要见着main了,其实啊,还早着呢,光看setup.s和head.s的代码量就知道,跟bootsect.s没有可比性,真多……这确实需要包括我在内的大家多一些耐心,相信见着main后,大家的信心和干劲会上一个台阶,加油! 既然上篇已经玩转gdb,接下来的讲解肯定是边调试边分析书上的内容,纯理论讲解其实我并不在行。 setup.s: 目标:争取把setup.

react笔记 8-19 事件对象、获取dom元素、双向绑定

1、事件对象event 通过事件的event对象获取它的dom元素 run=(event)=>{event.target.style="background:yellowgreen" //event的父级为他本身event.target.getAttribute("aid") //这样便获取到了它的自定义属性aid}render() {return (<div><h2>{