2021-04-06 函数的参数是如何入栈出栈的

函数的参数是如何入栈出栈的

制作逆向靶 建议用debug版而不是release版,因为release版会自作聪明把很多东西省略掉

在调试器中 寄存器EIP 表示当前程序走到哪一步了

ctrl+G 光标定位到某一地址

在单步调试中 右侧哪个寄存器变红了 就是哪个寄存器发生了变化

call 的第一个作用就是 将EIP的值改为函数所在的地址

由硬编码知识 可以计算出返回地址的值,举例

E8 84 FF FF FF (call stack.00401005) 这行硬编码是5个字节 所以 call完的返回地址就是 当前地址+5

call 的第二个作用就是 把返回地址压栈

 

按F7单步步入(ollydbg环境)

进入函数后发生了什么?(进函数之前push 4 push 3)

 

push ebp             栈的本质是一段内存,将栈底的地址压入栈, 为划分新的栈区做备忘录 记住旧的栈底位置。 此时栈底和栈顶的位置并没有发生巨大改变(因为入栈了一次,栈顶上移了一格)

mov ebp esp        使栈底=栈顶 抛弃了旧的栈区

sub esp, 44          每一个内存格是4个字节 0~FF FF FF FF ,esp上移0x44 就是上移0x11个格,就是上移17个格子. 至此 新的栈底和栈顶形成了新的栈区

这个新的栈区 就叫做缓冲区

push ebx

push esi

push edi

lea edi,dword ptr SS:[ebp-44]           所谓ebp-44就是新栈顶初次的位置

mov ecx,11                      计数0x11次即17个格子 准备填充缓冲区

mov eax,CC CC CC CC     填充物准备,不是硅胶,是一堆C  (int3)

rep stos dword ptr es:[edi]         (此时的D flag位是0 也就是向下填充) 

回顾一下被调用函数

int my_add(int x,int y)

{

           int z=2;

           return x+y+z;

}

int main()

{

         my_add(3,4);

         return 0;

}

mov dword ptr ss:[EBP-4],2           填充区底部倒数第二个格子里 装上2       这个2就是局部变量int z=2

                                                       此时可得学习经验 一般情况,EBP - 的 都是局部变量, EBP + 的 都是参数 

                                                       继续分析 EBP-4 是栈底倒数第二格  EBP是旧栈顶 EBP+4 是旧栈底  因此 大量逆向攻击都是攻击EBP+4

                                                       EBP+8 参数3 ,EBP+C 参数4

                                                       至此 被调用函数的参数和局部变量准备完毕 准备运行

mov eax, dword ptr SS:[EBP+8]        =3         eax不清0吗??? 哦 mov 不用清0

add eax, dword ptr SS:[EBP+C]         +4

add eax, dword ptr SS:[EBP-4]           +2        函数运行完毕 清理现场,恢复旧现场(之前有 push ebx        push esi          push edi  接下来pop的顺序要反过来)

pop edi

pop esi

pop ebx

mov esp,ebp                   把栈顶拉下来  此时新栈已无

pop ebp                           把栈底放下去

RETN

那么新栈区中的那些CCCCCCCC呢 那些局部变量呢? 没人管了 所以函数返回会留下一堆垃圾。 下次局部变量如果不赋初始值 就会捡到未知垃圾

RETN时发生的两件事  1 将返回地址弹进EIP

--------------------------------------

返回后发生的事

add esp,8                      将参数占用的栈空间返还回来  (这种栈平衡的方法叫 “外平衡”)

================================================================================================

攻击程序举例

#include "stdafx.h"

void attack()

{

               while(1){printf("哇哈哈你中招了\n");}              没人调用这个函数啊,怎么会中招?

}

int main(int argc,char* argv[])

{

                 int arr[5] = {0};

                 arr[6] = (int)attack;                  arr[5]是5个局部变量 arr[4]是0,arr[5] 已经是非法访问了 是栈底

                                                                arr[6]是栈底下的一格 [EBP+4] 这里存储着函数的返回位置!

}

=====================================================================================

《代码还是数据?》

知识点 函数指针

typedef int (*pFunction)(int x, int y);                            pFunction是一个函数的指针,此函数有两个整数参数 一个整数返回值

什么时候我们会用函数指针呢? 当我们要利用别人写的程序,只有个dll, 没有头文件,没有lib文件

我们到dll中找到要用的函数的指针,就可以用这个指针执行一段代码

对于逆向工作者 没有什么数据区 代码区,我让你是什么,你就是什么

举例

#include "stdafx.h"

unsigned char loc[] =                                  ( char的范围是-128~127 unsigned char范围是 0~255 )

{

            ox55,ox88,oxEC,ox83,oxEC ... ...      这些硬编码是逆向别人写的程序, 用处是加法计算

};

typedef int (*pFun)(int x, int y); 

int main(int argc,char* argv[])

{

          pFun f =(pFun) &loc;                      这是把人家的硬编码扒过来用啊!

          printf(  "%x",f(4,5)  );                       这个程序虽然小简单 但却是蕴含了架壳的思想

          getchar();

          return 0;

}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1讲:2015-01-12(进制01) 第2讲:2015-01-13(进制02) 第3讲:2015-01-14(数据宽度-逻辑运算03) 第4讲:2015-01-15(通用寄存器-内存读写04) 第5讲:2015-01-16(内存寻址-堆栈05) 第6讲:2015-01-19(EFLAGS寄存器06) 第7讲:2015-01-20(JCC) 第8讲:2015-01-21(堆栈图) 第8讲:2015-01-21(宝马问题) 第9讲:2015-01-22(堆栈图2) 第10讲:2015-01-23(C语言01_后半段) 第10讲:2015-01-23(C语言完整版) 第11讲:2015-01-26(C语言02_数据类型) 第12讲:2015-01-27(C语言03_数据类型_IF语句) 第13讲:2015-01-28(C语言04_IF语句逆向分析上) 第14讲:2015-01-28(C语言04_IF语句逆向分析下) 第15讲:2015-01-29(C语言04_正向基础) 第16讲:2015-01-30(C语言05_循环语句) 第17讲:2015-02-02(C语言06_参数_返回值_局部变量_数组反汇编) 第18讲:2015-02-02(2015-01-30课后练习) 第19讲:2015-02-03(C语言07_多维数组) 第20讲:2015-02-03(2015-02-02课后练习) 第21讲:2015-02-04(C语言08_结构体) 第22讲:2015-02-05(C语言09_字节对齐_结构体数组) 第23讲:2015-02-06(C语言10_Switch语句反汇编) 第24讲:2015-02-26(C语言11_指针1) 第25讲:2015-02-27(C语言11_指针2) 第26讲:2015-02-28(C语言11_指针3) 第27讲:2015-02-28(C语言11_指针4) 第28讲:2015-03-02(C语言11_指针5) 第29讲:2015-03-03(C语言11_指针6) 第30讲:2015-03-04(C语言11_指针7) 第31讲:2015-03-06(C语言11_指针8) 第32讲:2015-03-09(位运算) 第33讲:2015-03-10(内存分配_文件读写) 第34讲:2015-03-11(PE头解析_手动) 第35讲:2015-03-12(PE头字段说明) 第36讲:2015-03-13(PE节表) 第37讲:2015-03-16(FileBuffer转ImageBuffer) 第38讲:2015-03-17(代码节空白区添加代码) 第39讲:2015-03-18(任意节空白区添加代码) 第40讲:2015-03-19(新增节添加代码) 第41讲:2015-03-20(扩大节-合并节-数据目录) 第42讲:2015-03-23(静态连接库-动态链接库) 第43讲:2015-03-24(导出表) 第44讲:2015-03-25(重定位表) 第45讲:2015-03-26(移动导出表-重定位表) 第46讲:2015-03-27(IAT表) 第47讲:2015-03-27(导入表) 第48讲:2015-03-30(绑定导入表) 第49讲:2015-03-31(导入表注入) 第50讲:2015-04-01(C++ this指针 类 上) 第51讲:2015-04-01(C++ this指针 类 下) 第52讲:2015-04-02(C++ 构造-析构函数 继承) 第53讲:2015-04-03(C++ 权限控制) 第54讲:2015-04-07(C++ 虚函数表) 第55讲:2015-04-08(C++ 动态绑定-多态-上) 第56讲:2015-04-08(C++ 动态绑定-多态-下) 第57讲:2015-04-09(C++ 模版) 第58讲:2015-04-10(C++ 引用-友元-运算符重载) 第59讲:2015-04-13(C++ new-delete-Vector) 第60讲:2015-04-14(C++Vector实现) 第61讲:2015-04-15(C++链表) 第62讲:2015-04-16(C++链表实现) 第63讲:2015-04-16(C++二叉树) 第64讲:2015-04-17(C++二叉树实现) 第65讲:2015-04-20(Win32 宽字符) 第66讲:2015-04-21(Win32 事件-消息-消息处理函数) 第67讲:2015-04-22(Win32 ESP寻址-定位回调函数-条件断点) 第68讲:2015-04-23(Win32 子窗口-消息处理函数定位) 第69讲:2015-04-24(Win32 资源文件-消息断点) 第70讲:2015-04-27(Win32 提取图标-修改标题) 第71讲:2015-04-28(Win32 通用控件-VM_NOTIFY) 第72讲:2015-04-29(Win32 PE查看器-项目要求) 项目一:PE查看器 开发周期(5天) 需求文档 第73讲:2015-05-07(Win32 创建线程) 第74讲:2015-05-08(Win32 线程控制_CONTEXT) 第75讲:2015-05-11(Win32 临界区) 第76讲:2015-05-12(Win32 互斥体) 第77讲:2015-05-13(Win32 事件) 第78讲:2015-05-14(Win32 信号量) 第79讲:2015-05-15(Win32 线程同步与线程互斥) 第80讲:2015-05-18(Win32 进程创建_句柄表) 第81讲:2015-05-20(Win32 以挂起形式创建进程) 第82讲:2015-05-21(Win32 加密壳_项目说明) 项目二:加密壳 开发周期(5天) 需求文档 第83讲:2015-05-28(Win32 枚举窗口_鼠标键盘事件) 第84讲:2015-05-29(Win32 CE练习) 第85讲:2015-06-01(Win32 OD练习) 第86讲:2015-06-03(Win32 ShellCode_远程线程注入) 第87讲:2015-06-04(Win32 加载EXE_模块隐藏) 第88讲:2015-06-09(Win32 IAT_HOOK) 第89讲:2015-06-10(Win32 InlineHook) 第90讲:2015-06-11(Win32 进程通信) 第91讲:2015-06-11(Win32 进程监控_项目说明) 项目三:进程监控 开发周期(5天) 需求文档 第92讲:2015-06-15(硬编码_01) 第93讲:2015-06-16(硬编码_02) 第94讲:2015-06-17(硬编码_03) 第95讲:2015-06-18(硬编码_04) 第96讲:2015-06-19(硬编码_05)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值