| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> ARM PWN:Codegate2018_Melong详细讲解 -> 正文阅读 |
|
[嵌入式]ARM PWN:Codegate2018_Melong详细讲解 |
前言在上一篇文章中我们讲解了一道ARM32静态链接的题目,本篇文章讲解的是
文章目录Codegate2018_Melong检查一下首先检查一下程序属性: 可以看到这是一个32位动态链接的ARM架构ELF文件,并且题目中是给了lib.so的,所以一会使用qemu启动程序的时候就需要使用 接着检查一下程序的保护机制: 可以看到只开启了NX保护,没有什么特别的东西 静态分析扔到ida里面看一下,这个程序不怎么复杂,函数也比较少,所以就先看一下伪C代码: main()函数main()函数太长了,就分左右截图了。先看左面,左面主要是一些初始化及menu信息。需要注意的是a2变量的缓冲区大小,从图中可看到 接下来看一下右面,使用switch case判断输入数值,这里有几个点需要注意一下,首先check()函数中一参 check()函数简单的描述一下check()函数,在main()函数中v5的初始值为0,v5作为check()函数的参数。进入程序后可以看到将v5的值赋给了v6,并且经过判断之后v5的值加一,也就是说每次运行程序check()函数最多能被调用两次。这里需要注意的是v5变量是存放在bss段的全局变量,所以后续函数依然还会对v5进行判断操作 接着会打印一下一些友情提示,接着会有两次输入,第一次输入身高,第二次输入体重。接下来会调用calc()函数去计算一下bmi值,最后调用get_result()函数。check()函数前半部分都没有什么太多感兴趣的点,但是后面这个get_result()函数需要细点说明。可以看到v5变量是calc()函数计算之后的bmi值,会作为参数传入get_result()函数中。get_result()函数主要的功能就是通过bmi值去判断你的健康情况,每个判断分支中都会创建一个v2大小的堆块,并把其malloc指针赋给 exercise()函数没啥特别的,只是一堆计算,对于漏洞的利用没有什么特别大的影响,就不详细分析了 PT()函数PT()函数内部就比较简单了,首先需要输入一个数值作为size,并创建一个size大小的chunk,接下来释放该chunk并且返回size。这里需要注意的是size是一个有符号int,也就是说我们其实是可以写一个负数的,那么经过第一个分支后会返回一个负的十六进制数。这个点会在后面write_diary()函数中用到 write_diary()函数在进入write_diary()函数前是需要检查PT()函数返回值的,因为我们输入负数返回值不为空,所以可以进入到write_diary()函数中。并且返回的size作为write_diary()函数的一参传入,传入后的size将负值赋给无符号变量nbytes,那么nbytes就变成了一个以0xf开头4字节很大的一个数值。接下来会向bss段的a2变量写入nbytes个字节,这里就出现了栈溢出,因为a2变量在前面提到过,它能够存放的最大长度为0x54,所以nbtyes一定是大于0x54的 查看程序执行流程静态分析后,使用qemu启动一下程序,几个重要选项写出交互代码 主界面1选项:check()函数
3选项:PT()函数一次输入,在问号之后输入,交互代码如下: 4选项:write_diray()函数直接输入数据,交互代码如下: 6选项:退出为什么要加上一个6选项呢?这是因为在动态调试的时候发现,之后选择6选项之后才能执行栈中部署的内容,就很奇怪,ida里面也没看到有相关的说明。。。。。 交互代码如下: 思路分析通过前面静态分析阶段,我们得到如下几个可以利用的点:
那么现在溢出点找到了,接下来就需要通过栈溢出泄露泄露函数地址,进而找到libc基地址,在通过基地址找到system()函数地址及/bin/sh字符串地址。这部分过程就和x86下的ret2libc3一样了 计算缓冲区大小这里就演示一下动态调试查看缓冲区大小,其实静态的时候就已经可以看到a2字符串数组的长度了 首先使用qemu吧程序起起来,加入-g参数等待gdb链接: 然后gdb-multiarch启动,设置arm架构,链接本地1212端口 按c继续,在程序执行界面走到write_diray()函数,并输入cyclic创建的200个字符串 程序就会断在0x61616176处,再使用cyclic计算出长度: 最终计算出缓冲区大小为84,即0x54 泄露并找到libc基地址程序中是存在puts()函数的,所以可以直接使用pwntools查找puts.plt和puts.got,我们还需要准备main()函数地址,主要构造思路为puts.got
主要构造思路为将puts.got作为puts.plt,最后重新返回至main()函数进行接下来的操作。那么就意味着我们需要一个能够向R0寄存器赋值并返回的gadget: 可以看到只有一个满足条件的gadget:0x00011bbc 那么构造的payload如下:
这样一来我们就可以通过write_diray()函数发送,并调用logout()函数执行,这样就能输出puts()函数真实地址puts_real了,接下来计算libc基地址就可以了
第二次调用main函数getshell由于前面payload的构造使得程序返回main()函数,这就意味着可以再次执行程序流程,进入到write_diray()函数的过程和第一次是一样的,唯一需要修改的是payload 因为已经得到了libc基地址,所以可以找到system()函数和/bin/sh字符串。依然使用pop_r0这段gadget,将/bin/sh字符串地址作为system()函数的参数,执行就可以了
再次使用write_diray()函数发送,并且调用logout退出就可以拿shell了! EXP
|
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 18:49:35- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |