闭关学pwn第四天——掌握pwn中需要了解的汇编指令(对第一天栈做相应补充)
Posted mid2dog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭关学pwn第四天——掌握pwn中需要了解的汇编指令(对第一天栈做相应补充)相关的知识,希望对你有一定的参考价值。
补充
这篇最后编辑时间是19年12月。。我居然鸽子了这么久没发!!!
看了下自己大致讲的很详细了,文章后面应该想着自己手绘图然后再多来几个函数调试,不过既然鸽子了就炖汤吧,这篇就不补上了。
准备在闭关学pwn第五天把第三天和第四天两篇文章的内容结合起来,搞一道题来练手什么的[滑稽]
前言
pwn现在卡死在ret2libc,知道是返回,却不懂怎么返回,也不知道怎么搞到shellcode,估计是没有相应基础,所以这回补一波pwn中需要掌握的汇编指令。
———————————————————————————————————
一 、开天辟地
没错我就是来开天辟地的。
首先……
move push add 这些基础指令肯定要看看的吖
不过pwn里好像需要用到的是这些指令:
子程序
算术指令
通用数据传送指令
比较指令
栈的结构在闭关学pwn第一天了解过
pwn里最常见的ebp和esp肯定要了解
当时只是学到了栈由高地址向低地址生长,却从没想过为什么要这样
这篇文章里有讲到
https://www.jianshu.com/p/899f34722d57
———————————————————————————————————
二 、女娲补天
开天辟地完了就该女娲补天了
刚才都是理论,这里实际操作一下
gcc编译配合gdb调试还不大熟练
所以就花点功夫找了个在线查看汇编代码的网站
先简单练练手来验证之前的汇编指令
写一段最最最最最简单的代码吧
int main()
int a,b,c;
a=1;b=2;c=3;
然后放进汇编
它很灵性的输入一行就汇编一行出来
边看汇编边学习吧
首先是push rbp
————————————————————————
0x10 push
而push是压栈操作,压栈是干什么用的呢?
在调用一个函数时CPU会将当前的环境保存起来我们称之为压栈(Push)
计算机在运算的时候大部分情况会把数据放到寄存器里运算,而调用函数的时候,会有新的数值要使用这些寄存器,所以要把这些寄存器里的内容保存起来,就是保护现场。因为栈的先入后出非常适合这一操作,所以每次函数调用前都有入栈操作,函数返回是出栈还原现场
计算机程序用来放数据的地方有两种,一个是堆,一个是栈。
栈一般用来放一些函数的临时变量,还有中断和调用函数时的返回地址。
因为这些地址都是临时的,所以在栈的出栈和进栈的时候可以动态的进入和删除。
调用函数和中断的时候,临时变量和返回地址就暂存在栈中。
函数调用完了,临时变量和返回地址就从栈删除了。
所以栈一般来说是临时变量,调用函数会自动回收内存。
这就是PUSH 和 POP 的功能了。
相当于一个暂时保存数据的地方。
而堆的话一般用来动态分配内存,分配的内存一般不会自动释放。
也就是,如果对rbp不进行压栈操作,调用完函数以后cpu就找不到路了,不能返回调用函数前的位置继续往下运行了。毕竟电脑比人笨咯,我们要体谅cpu。
push压栈具体步骤如下,先用32位的来解释,毕竟要从32位开始
栈顶指针esp代表向下拓展了四个字节,就是说,esp往下4个字节,就可以把eax放进去封印起来,最后eax用完了再弄出来,栈先入后出的好处便在这里了。
写段代码当例子
void ha(int m, int n)
int a, b;
a = m;
b = n;
main()
int m,n;
ha(m, n);
汇编代码如下
发现出现了DWORD PTR []
搜索后发现是相当于*p的功能
dword 双字 就是四个字节
ptr pointer缩写 即指针
[ ]里的数据是一个地址值,这个地址指向一个双字型数据
如mov eax, dword ptr [11111111]
就是把内存地址11111111中的双字型(32位)数据赋给eax
然后看到在main中,先把这两个int变量从地址拿到寄存器edx和eax中,然后再从edx和eax中赋给esi和edi,也就是存到esi和edi中,这样edx和eax就又空出来可以参加中的运算而不用担心原本的值丢失了。
这时候发现又call指令
————————————————————————
0x20 call
把之前存到edi里和esi里的再拿出来赋给新的地址
这正说明了真正参与运算的是函数的形参,也跟之前学到的c语言知识相对应
原句是push rbp,push明白了,看rbp
rbp百度到是64位的相当于32位的ebp
也就是最上面一个栈帧的底部
对栈帧不大了解,以前都是粗略理解为上个函数底部,这回搞懂它。
这样看起来还是很迷糊,加入灵魂
精华:
首先应该明白,栈是从高地址向低地址延伸的。
每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息
寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)
注意:EBP指向当前位于系统栈最上边一个栈帧的底部,而不是系统栈的底部。
严格说来,“栈帧底部”和“栈底”是不同的概念;
ESP所指的栈帧顶部和系统栈的顶部是同一个位置。
大致自己画出图是这样的
栈帧n代表套娃n次
因为之前百度百科中也提到栈帧是对应着未完成的函数,比如我运行main函数里面调用了其他函数,那么就是栈帧1(也就是main)跳到栈帧2,如果这个函数里再嵌套进其它函数,那么就继续往下开栈帧。
而并列的函数比如main里有两个函数的话栈ebp是不会变的,只是把esp放出去再“收”回来罢了。
以上是关于闭关学pwn第四天——掌握pwn中需要了解的汇编指令(对第一天栈做相应补充)的主要内容,如果未能解决你的问题,请参考以下文章