当前位置: 首页 > article >正文

B站pwn教程笔记-4

ret2syscall题目

file查看elf文件 这是静态链接,里面有大量函数。

在使用ROPgadget的时候,grep命令可以用管道符链接在后面。用于查找。有的语句一下子就可以给很多寄存器给值,这样的gadget是我们最喜欢选择的,还省事一点,如下图最后一行。

pwntools自己有个ELF对象功能。可以创建一个ELF对象,并且有许许多多的方法用在这个对象上。

比如搜索指定的字符串功能,出来的结果是一个生成器,so:next(这一串代码)就可以直接出来地址了。出来的是十进制,可以用hex转为16进制。

疑难解答环节

系统内核函数不可以直接call调用,方式是有变化的。首先就是要int 0x80,这是一个中断号,系统有不止一个中断号,但是0x80代表开始进行系统调用了。然后,通过给寄存器传特定参数,告诉系统调用特定的系统函数,如sys_execve()就是0xb

看下图,需要注意不要犯迷糊的点在于,ret后实际上已经切换到另一个栈帧了(比如从被调函数转为了主调函数的栈帧),所以pop实际上不会发生冲突,因为pop是在自己的栈帧工作的。

动态链接过程 

下图还是稍微简化了,中间的过程更复杂。

有可能会出现ELF文件本身不包含int 0x80这种情况,就是gadget不好直接找。 

可以用上述代码实现PIE的关闭和静态链接。其中去掉--static就是动态链接 。下图就是动态链接的函数列表,比较少了。而静态的比较多,他会把很多库函数也包括来。

动态链接这里面粉色的都是一个标记相当于,运行的时候会解析,然后去动态链接库找对应的代码。

 动态链接的相关结构

只有动态链接的文件才会有

 .got是全局偏移量表,是变量地址,.got.plt是函数地址。

动态链接的过程

plt是程序中解析函数真实地址的一个节,在代码段吧。保存着程序调用的动态链接库函数,比如read、foo。plt最开始的指令看图。而.got.plt是保存的数据,存放的位置是数据段。

假设存在一个foo函数在动态链接库里面。由于程序自己不含有foo的代码,所以call foo实际上是在找foo函数在plt的地方,如下图所示。

在程序首次执行foo函数 的时候,.got.plt里面本身并没有foo函数实际的地址,所以第一次plt跳转到.got.plt的时候,.got.plt会立刻跳转回去,然后plt的任务就变成了找到foo的真实地址。

这时候已经跳转回来了。push index是一个参数。最终程序会push俩参数,jmp两次,也就是执行了4条汇编代码。

index:相当于函数在plt里面的索引。

push got+4 说明用的哪个动态链接库的函数。

接下来跳转到GOT+8开始解析库函数真实地址的任务。 这里是使用了.dl_resolve这个函数,具体实现不要学了,反正弄完之后把真实地址已经给了.got.plt。

如果是第二次调用,因为已经写入了真实地址,也不再进行上述操作了,直接锁定到真实地址就可以了。

(这里的真实地址说的是foo在动态链接库里面的位置)

IDA+gdb观察动态链接过程

gcc编译的时候 ,-m32表示编译为32位。因为64位传参方式之类会有区别,但是差别不大。为了便于学习,目前还是以32位为主。但是-m32需要电脑有相关库代码,这里还是编译为64位。。。

由于此程序只调用一个puts函数。所以plt只有一个。

查看plt表。需要注意的是,默认x不带/20只会显示的少一点。

init节就是代码初始化。

看看IDA里面的plt。蓝色字体说明了对应的函数了。16个字节一个。

更高地址分别是got、.plt.got。每个是8字节,因为64位一个地址是8字节。

 

看看got自己存的东西,默认存的其实是plt的地址哦(vmmap看虚拟内存地址)

 

此时刚调用puts。got表存储的就已经是puts真实地址,使用disass反汇编这个地址的机器码看看。

 

ret2libc 

几个动调知识

1.无法返回上一步的状态。想看上一步的状态只能在上一步打一个断点,run到断点处。

2.start:优先停在main函数第一行,然后是程序入口第一行。

backtrace:就像函数调用栈状态。main调用了-->my_puts()

return:执行到函数末尾了。

方法介绍 

也需要ROP创造执行shellcode的环境。但通常返回的是动态链接库里面。

 

难点:因为是动态链接,自带的gadget较少。 

注意,这里有个干扰函数,但是这里的system函数确实给plt表增加了一个表项(前提是动态连接的软件),相当于知道system地址了。我们就可以让她在libc执行一个system。

因为是32位,我们要在栈上控制一手参数,让system函数的参数变成有用的。

 

 

参数都是在父函数。最终栈帧构造如下(以后会详细讲解):
 

最后一个知识点:C语言传递字符串参数传递的是起始指针。字符串存在.rodata段的地方。所以system("/bin/sh")实际上是下面:

 


http://www.kler.cn/a/573298.html

相关文章:

  • Java Web-Filter
  • 面试基础---MySQL 事务隔离级别与 MVCC 深度解析
  • IP地址怎么加密https访问?
  • JAVA毕设项目-基于SSM框架的百色学院创新实践学分认定系统源码+设计文档
  • 毕业项目推荐:基于yolov8/yolov5/yolo11的田间杂草检测识别系统(python+卷积神经网络)
  • Stable Diffusion LoRA 技术详解
  • debian/control 文件中的${misc:Depends}
  • 如何在React中正确处理异步操作?
  • windows 利用nvm 管理node.js 2025最新版
  • 靶场之路-VulnHub-DC-6 nmap提权、kali爆破、shell反连
  • DAViMNet:基于状态空间模型的域自适应目标检测
  • 二、Java-封装playwright UI自动化(根据官网执行步骤,首先封装BrowserFactory枚举类及BrowserManager)
  • Python开发高效PDF批量转Word
  • 前端基础之内置指令与自定义指令
  • VsCode 快捷键备忘
  • CentOS 7 安装Nginx-1.26.3
  • 【3】VS Code 新建上位机项目---C#窗体与控件开发
  • 海康机器人搞工业机器人,我以为它忘记自己名字,作为技术,作为业务你跟不跟,机器视觉工程师搞视觉引导必须知道工业机器人四大坐标系
  • 前端开发10大框架深度解析
  • 【单片机】嵌入式系统设计流程