开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2268|回复: 3
收起左侧

[图文教程] 调call和偷功能时,VC中内联汇编容易产生的错误

[复制链接]
发表于 2019-6-19 15:50:39 | 显示全部楼层 |阅读模式   吉林省通化市
本帖最后由 超级大神 于 2019-6-19 16:12 编辑

最近,有不少刚学习内联汇编的网友和同学跟我聊,他写的内联汇编代码总是出现一些莫名其妙的错误,看上去明明是对的,却怎么也执行不成功。

        甚至有的是,代码注入器都可以测试成功的汇编代码,复制到VC里不行了!感到很困惑。
那么,今天我们就一起来探讨一下这个问题,帮助刚学习内联汇编的同学和刚逆向入门的同学少走些弯路,少遇一些坑。

1.png

我们先来看下什么是内联汇编?
内联汇编,指在C语言中插入汇编语言。


       内联汇编可以帮我们做什么?
1.可以帮我们在C语言中插入汇编代码。
2.可以帮我们调用目标程序的子程序(CALL)。
3.可以协助我们偷功能。

2和3  是可以做一些羞羞的事的,功能很强大

2.png


3.png


下面的反汇编窗口是一个小游戏的吃药函数

push的第一个参数是 push 0
push的第二个参数是 push edx   
edx 是表示的药品位置(当然正常情况 我们不会选择这样参数的函数调用,位置参数一定是没有ID 参数调用方便的,这里只是随便举一个简单例子)

call004FACD0  只是为了取一个返回值eax
然后把返回值赋值给  参数ECX
即mov  ecx,eax

最后调用函数  call 00491C50



4.png

函数我们分析清楚了,就可以写代码了
首先先在代码注入器中编写代码
代码注入器中测试成功的代码(药品我们选择第一个位置的 ,edx 为0)
我们看到除了变化的参数我们需要给其赋值以外,其他的代码就照抄的
5.png



然后我们到VC中进行内联汇编的编写

6.png


这里需要注意的只有两点
第一点,从反汇编窗口复制出来的数值都是16进制的,到VC里要加上个0x
例如  004F1CD0  写成  0x004F1CD0
第二点,call  立即数  语法是不合法的   需要用寄存器转一下
call0x00491C50   写成  mov  eax,0x00491C50   call eax
上面的例子可以看出内联汇编写法很容易

__asm{},把自己想插入的汇编代码直接按照汇编的语法编写即可。

7.png

感觉完了?不,才开始=。=

以上只是最简单的情况,在我们编写的过程中可能存在很多错误,主要表现为三种错误。

第一种错误,编译错误

这种错误编译器会提示我们,这种错误没什么难度,如下

8.png

不能直接call 立即数


9.png

标点符号要英文的
10.png

立即数不能作为左值
根据提示修改即可。
第二种,运行错误,当然编译器是不会管我们的,所以我们就要额外小心的使用内联汇编。
我们拿个例子看下
例如代码注入器测试成功的代码

11.png


我们按照规则修改成内联汇编代码如下
也编译通过了


12.png


但是这段内联汇编代码测试了好多次
调用一定是会崩溃程序的(代码注入器的完全没有问题)
为什么?

13.png

那我们可以选择逆向我们自己的代码来看看情况,由于我写的是MFC dll
需要注入到游戏中运行的,所以我们附加上这个小游戏 ,然后去看我们的代码
首先我们在自己的内联汇编中加一些特征  ,方便我们直接定位跳转过去。

14.png

这样的特征,正常代码 是打死也不会有的。


点开E

15.png

找到我们的模块 我们的DLL.dll

16.png

入口地址 37542D16
CTRL+G 跳过去

17.png


18.png

回车来到模块领空

19.png

CTRL + S 搜索我们的特征码

20.png

找到了我们的内联汇编代码


21.png


我们来对比一下代码


22.png


23.png

是不是发现 我们代码 mov  ecx,[0x00D0DF1C]  的括号没有了
有的人会说,  这是你没有加  dword ptr

那么我们加一下试试

24.png

发现代码依然是这样的


25.png



那么怎么办?
我们怎么写才能不出错误

代码写成这样就可以了


这是根本看不出来的可能的错误,一个是靠我们已经有的经验解决
另外一个就是,我们出现问题 ,用上面的方法到游戏里定位问题,解决问题,永远是最好的方法。

第三种,可以预知的运行错误

看上去没有什么错误,但是实际上这样运行是百分百会崩溃的。
原因很简单,汇编代码不合法!
有的同学会说哪里不合法啊?
我们看int a[3]= {7,键码,1}; 一个数组,在逆向的本质里,其实就是3个局部变量而已
[ebp-4],[ebp-8],[ebp-C]
而 a是这个数组的首地址  即ebp-C
那么我们看  下面的内联汇编中
push a 是否合法
push  a  等价于  push  ebp - C
那么当然是不合法的!
因为不合法 ,编译器 不会编译出现不合法的代码的
他强制将代码编程成  push [ebp-c]  这样参数含义完全变化,程序执行过程自然出现错误,导致崩溃也是必然的了。
想要解决
所以我们要改成以下代码
正确的方法一
我们 lea ebx,a[0]
相当于  lea ebx,[ebp-C]
然后再 push ebx
这样就合法了

如下图

正确的方法二

把指针转换成  用局部变量存放 然后再PUSH
总之,使用内联汇编,一定要对其机制比较了解
否则稍不小心,会在上面浪费很多调试时间
处于好奇心,我也百度了一下,看看是不是也有很多人出现过类似的问题,果然找到了几个,我已经对其进行了一一解答。简单截图2个具有代表性的问题 我们一起看一眼
上面的例子,就是我们第二种错误的情况
代码需要写成
push 0
moveax,0x1E22DD8
moveax,[eax]
push eax
push 0
这样就可以了
上面的例子,就是我们第三种错误的情况
编译器认为代码不合法,强行编译的错误
并不是内联汇编不把字符串名当指针看待,而是你的汇编代码不合法,
编译器为了能够编译,编译结果自然和你想的不是一样的了。
a 是字符串名,看上去 mov  ebx,a   就可以了。
但是  真要是编程出来了,你还认识这样的汇编代码吗? mov  ebx, ebp-xx ????
他真要编译出来是不是你认都不敢认,没见过这样的代码啊!
所以他只能编译成合法的代码吧。 那就是mov  ebx,[ebp-xx], 也就是你所谓的,把指针硬当成变量看,编译器心里苦啊,是您逼迫我这样干的!
偷功能
偷功能其实和写call  没有什么本质的区别了,只是需要抄下来的代码更多一些

更确切的说是复制粘贴出来修改的代码更多一些。
复制出来的汇编代码需要进行初步处理才能写到内联汇编中
例如常数全部要加上0x
例如,call xxxxx  都要用寄存器转一下
例如 mov  eax,[0x12345678] 这种代码也要转一下
等等
还有一个最重要的,就是跳转要修改
例如 jnz  12345678 他是要跳转到目的代码地址执行的,我们偷出来的代码已经不是原来的地址了
所以要通过标签修改跳转的地址。
跳转的写法

我们随便截取一段代码,来说明跳转怎么修改

内联汇编中的写法
__asm
{
     mov esi,[eax]
     cmp  esi,eax
    Je Label1  //         不能再写  je 0x66C66F
Label2:   //                 跳转过来的标签
    mov edi,esi
    mov esi,[esi]
    push 0
    lea ecx, [edi+8]
    mov eax,0x0066CC60
   call  eax
   push 1
   push edi
   mov ecx,ebp
   mov eax,0x0066cc20
   call eax
   cmp esi,[ebp]
   Jnz  Label2     //         不能再写  je 0x66C652
Label1: //                 跳转过来的标签
   mov eax,[ebp]
}

我们查看自己的代码看是否正确
发现是正确的
当然偷功能的时候
我们尽量偷完整的函数代码,而不是中间一段
并且要传递正确的参数,才能执行成功。

绝对地址跳转
同样是不可以直接 jmp   xxxx


这样就可以了
如果是JMP 这样写就可以了
因为我们知道 jmp 的操作数可以是寄存器
而JNZEAX  是不合法的
jnz 等条件跳转怎么绝对地址跳转呢

发现无论你后面立即数写多少 都是没用的
他只是跳到下一条
因为   立即数  都被编译成了  00000000
目前已经知道解决方案有3个
一个是用标签
一个是自己判断数据,进行跳转

最后一个方法就是 自己计算跳转值  在代码里进行修改了,这种方式推荐裸函数,容易计算偏移
现在确实是不对的

那么我们  自己改写即可

0x371C5960 到 0x371C5984 是0x24字节  加上  0F84  的两字节
偏移是 0x26字节
也就是说 我们要修改的地址 是从函数头部+0x26的位置
我们修改成的值 是  跳转目标  -  本条代码地址  -5
既下面代码
DWORD temp =0x12345678 - ((DWORD)&aaa+0x24) -5 ;
然后把值写入  函数头部+0x26的位置
*(DWORD*)((DWORD)&aaa+0x26)= temp;
调用以后的效果

相当于串改了代码,不过是自己的代码
值得注意的是,如果函数有Jmp跳转需要再加入计算。
先讲到这里,欢迎补充和探讨!

评分

参与人数 1好评 +1 精币 +2 收起 理由
OK彩 + 1 + 2 小白学习太难了,感谢大佬

查看全部评分

结帖率:70% (44/63)
发表于 2021-10-7 19:26:52 | 显示全部楼层   广东省清远市
非常有用的~太感谢大佬了
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 15 天

发表于 2020-1-20 19:20:55 | 显示全部楼层   四川省成都市
大佬请教CALL的问题 有时间吗??
回复 支持 反对

使用道具 举报

结帖率:0% (0/2)
发表于 2020-1-16 09:36:50 | 显示全部楼层   山东省烟台市
易语言里有模块可以直接写汇编语言代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表