内联汇编(小结笔记)

*该文章为本人学习51hook内联汇编一课后所总结的笔记以及经验,如有雷同纯属巧合。

 

本章知识点:_asm关键字,裸函数declspec(naked)声明,esp+4,esp+8存储的数据,ret内平栈,lea取地址中的值

 

 

1._asm关键字

 

在主函数中,如果想要编写汇编语言,例如 push eax, mov eax,ecx;是会报错的,因为在C语言中需要先声明一个变量或者参数的类型。

 

 所以需要加上_asm 来提示编译器,这是一行汇编代码

例如: _asm push eax; _asm eax,ecx;

 

 

 

这种称为行汇编

如果想执行多行汇编指令,重复的使用_asm指令会使代码看起来冗杂,所以下面就是比较简洁的块内联汇编

通过_asm{}将需要执行的汇编代码包括起来

 

 

2.通过call指令调用MessageBox

调用WINAPI 实现MessageBox弹窗

 

 

在汇编中,函数都是通过call指令调用,可以用过call指令调用MessageBox

 

 

这只是单纯的进行了一个简单的调用,对照注释掉的MessageBox函数,包含了4个参数,所以通过push传入四个参数

 

 

 

在汇编中是从右向左传参,所以我们要在第三个push处改为helloworld

我们尝试把第三处 push 0 改为 push helloworld

 

 

 

 发现这样改之后出现了报错,通过所学过的知识可以知道,我们要push helloworld对应的地址

因此尝试定义一个数组str 通过存放helloworld 再Push str

 

 

但是在运行后仍然会发生报错,在push处下断点跟入反汇编查看

 

 

 

看到在第三个Push处 push str 在汇编中变为了dword ptr[str],把str的地址当做地址,取了地址[地址]中的值压入了堆栈

最后打印的是地址的地址而不是地址的值

所以需要用lea 指令把str地址中的值放入eax再push eax即可

 

 

3.裸函数

 

 分析如上程序,在汇编中是如何执行的

首先看到定义了一个test函数,所以第一时间想到的就是通过call调用test函数,然后在堆栈中存入下一行代码的地址最后返回

然后call调用printf函数输出1234

但是test函数中没有任何代码,没有return 最后函数还能返回吗?

通过打断点进入反汇编查看

进入test函数内部发现即使函数内没有执行任何代码,系统也会为其开辟空间,同时在编译中也添加了ret指令

 

 

如果要写一个裸函数,需要添加声明_declspec(naked)

 

 

添加完后再下断点进入反汇编test函数内部查看

 

 

int 3就是全部用CC填充

可以看到添加了声明后,函数内部只是进行了初始化,并未进行其他任何操作

 

 

下面尝试在初始化的函数中使用内联汇编调用MessageBox,让test函数接收一个字符串数组test(char *str)

由于没有进行任何操作,所以提升堆栈开辟空间都要由自己操作

首先是所有函数通用的一个操作,把栈底指针压入堆栈 push ebp

然后让栈顶指针和栈底指针持平 mov ebp,esp

之后为函数内部分配空间 sub esp,0x30

然后开始为MessageBox传参,对应的是从右往左4个参数,之后用call调用MessageBox

调用之后要进行堆栈平衡,add esp,0x30

mov esp,ebp;

pop ebp;

函数结束后还要进行返回,这里采用内平栈,因为只压入了一个参数,所以返回4就可以

ret 0x4;

 

 

把初步的结构定义完之后,再考虑怎么传入messagebox的参数

在堆栈中,ebp+4存放的是返回地址,ebp+8存放的是第一个参数这个是固定的,所以我们直接拿ebp+8来传入MessageBox

这里的ebp+8中的值就是test接收的str字符串

 

 

然后定义字符串 char str[] = "HelloWorld";

可以通过内联汇编调用字符串str和函数test来完成操作

 

posted @ 2021-05-12 18:25  Y4n9  阅读(1944)  评论(0)    收藏  举报