首页
社区
课程
招聘
[求助]请教这段汇编代码的逻辑思路是什么
发表于: 2019-2-19 10:27 3149

[求助]请教这段汇编代码的逻辑思路是什么

2019-2-19 10:27
3149
' 00000000    PUSH EBX
' 00000001    PUSH ECX
' 00000002    MOV EAX,[EBP+8]
' 00000005    INC EAX
' 00000006    MOV ECX,[EAX]
' 00000008    CMP CL,E8
' 0000000B    JNZ SHORT 00000005
' 0000000D    MOV ECX,[EAX+1]
' 00000010    LEA EBX,[EAX+ECX+5]
' 00000014    MOV ECX,[EBX]
' 00000016    SHL ECX,8
' 00000019    CMP ECX,EC8B5500
' 0000001F    LEA EAX,[EAX+4]
' 00000022    JNZ SHORT 00000005
' 00000024    MOV EAX,EBX
' 00000026    POP ECX
' 00000027    POP EBX
' 00000028    LEAVE
' 00000029    RETN 4

这是一段获取子程序真实地址的代码(不论多少参数),但是我只知道例如:
0x400204BA   E8 41B60500  call   0x4007BB00
0x400204BF    C9     leave
真实地址是4007BB00,算法是0x400204BA+5+0x0005B641=4007BB00

上面这段代码涉及到了位移,自加,平时只是简单的接触mov jnz jz lea指令,对这些高级指令的逻辑不是很清楚,所以问问大伙,这段代码意思如何,最好能详细到每一句,谢谢大家!

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 9910
活跃值: (2142)
能力值: ( LV13,RANK:327 )
在线值:
发帖
回帖
粉丝
2
' 00000000    PUSH EBX
' 00000001    PUSH ECX #保存寄存器中的值
' 00000002    MOV EAX,[EBP+8] #取参数(大概)
' 00000005    INC EAX #指向下一个数据
' 00000006    MOV ECX,[EAX]
' 00000008    CMP CL,E8 # [EAX]低位 == 0xE8,
' 0000000B    JNZ SHORT 00000005 #否则回到循环开始
--------------------------------------
' 0000000D    MOV ECX,[EAX+1] #指向下一个数据
' 00000010    LEA EBX,[EAX+ECX+5] #ebx=eax+ecx+5
' 00000014    MOV ECX,[EBX]
' 00000016    SHL ECX,8 #将操作ebx后的指向的地址的数据取出,再逻辑左移8位。
' 00000019    CMP ECX,EC8B5500 #如果等于特殊值-》
' 0000001F    LEA EAX,[EAX+4] #eax+4
' 00000022    JNZ SHORT 00000005 #-》不等则回到循环开始
--------------------------------------
' 00000024    MOV EAX,EBX #-》则返回。
' 00000026    POP ECX #还原寄存器中的值
' 00000027    POP EBX
' 00000028    LEAVE #返回
' 00000029    RETN 4

好像是看看参数中哪个值等于0xE8,发现之后累加数据至ebx,ebx中的值指向的地址的数据满足要求,则返回ebx的值。

最后于 2019-2-19 14:21 被顾言庭编辑 ,原因:
2019-2-19 14:16
0
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
顾言庭 ``` ' 00000000 PUSH EBX ' 00000001 PUSH ECX #保存寄存器中的值 ' 00000002 MOV EAX,[EBP+8] #取参数(大概 ...
谢谢您,元宵快乐!
2019-2-19 14:52
0
雪    币: 9910
活跃值: (2142)
能力值: ( LV13,RANK:327 )
在线值:
发帖
回帖
粉丝
4
举手之劳,何足挂齿。
元宵节快乐!
2019-2-19 15:10
0
雪    币: 22
活跃值: (977)
能力值: ( LV8,RANK:135 )
在线值:
发帖
回帖
粉丝
5
//我觉得LZ可以去看一下E8指令是什么
//比如可以手动写个main函数,然后让其随便CALL一个函数,然后看一下CALL指令及周围的字节内容

//保存寄存器
00000000    PUSH EBX
00000001    PUSH ECX

//这个函数应该只有一个参数,是一个指针,比如叫做fakeAddress
//然后以(fakeAddress+1)作为开始指针往后开始搜索(按字节为单位),直到出现0xE8字节
00000002    MOV EAX,[EBP+8]
00000005    INC EAX
00000006    MOV ECX,[EAX]
00000008    CMP CL,E8
0000000B    JNZ SHORT 00000005

//到此时EAX指向0xE8字符(注:0xE8在汇编中是 CALL 指令)
0000000D    MOV ECX,[EAX+1]

//下面这里通过对call指令硬编码方式求解出期望call的函数地址,结果保存在EBX寄存器中
00000010    LEA EBX,[EAX+ECX+5]

//从期望被CALL的函数头取出四个字节,保存在ECX中
00000014    MOV ECX,[EBX]

//将这四个字节作为32位值左移8位(相当于一个魔术值)
00000016    SHL ECX,8

//左移八位后这个值应该等于0xEC8B5500才对
00000019    CMP ECX,EC8B5500

//EAX==EAX+4
0000001F    LEA EAX,[EAX+4]

//如果上面计算完ECX不等于0xEC8B5500,那么就再跳回到 0x00000005 找下一个0xE8字节
00000022    JNZ SHORT 00000005
00000024    MOV EAX,EBX

//恢复寄存器及函数返回
00000026    POP ECX
00000027    POP EBX
00000028    LEAVE
00000029    RETN 4

最后于 2019-2-19 15:57 被OxLucifer编辑 ,原因:
2019-2-19 15:43
2
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
OxLucifer //我觉得LZ可以去看一下E8指令是什么 //比如可以手动写个main函数,然后让其随便CALL一个函数,然后看一下CALL指令及周围的字节内容 //保存寄存器 00000000&n ...
谢谢大牛这么详细的讲解 
最后于 2019-2-19 20:02 被小木鱼编辑 ,原因:
2019-2-19 19:42
0
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
//下面这里通过对call指令硬编码方式求解出期望call的函数地址,结果保存在EBX寄存器中
00000010    LEA EBX,[EAX+ECX+5]
这里的eax指向的是call的地址,+5正好是call xxxxxxxx后的一行所占的内存地址,

而ecx=[eax+1],这个应该是指向什么具体意义的值呢?

对这句的硬编码计算不是很了解,希望能得到再次解答!


2019-2-19 19:54
0
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
顾言庭 举手之劳,何足挂齿。 元宵节快乐!
嗯嗯!
2019-2-19 20:03
0
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
OxLucifer //我觉得LZ可以去看一下E8指令是什么 //比如可以手动写个main函数,然后让其随便CALL一个函数,然后看一下CALL指令及周围的字节内容 //保存寄存器 00000000&n ...
还要麻烦你一下,我尝试VC6下写一个CALL,调用任意一个函数A,代码如下:
#include "iostream"
using namespace std;

void A(int)
{
	cout<<"ok"<<endl;
}

void main()
{
	_asm
	{
		call A;
	}
}
获取到的汇编图表如下:

我很新手,希望帮忙解答下,这样的情况,怎么汇编模式下分析代码呢?
2019-2-19 20:23
0
雪    币: 22
活跃值: (977)
能力值: ( LV8,RANK:135 )
在线值:
发帖
回帖
粉丝
10

我这边手头比较方便的有Linux环境,所以我就先用Linux环境给你演示一下,其实原理是一样的。
我自己写了一个HelloWorld程序,很简单只是调用了一下printf
可以看到我在0x000055555555465a这个地址处准备执行一个call 0x555555554520 <printf@plt>的指令
然后我对0x000055555555465a这个地址的内容打印8个字节,可以看到打印的结果中第一个字节就是0xE8
0xE8代表CALL指令,0xE8后面的四个连续字节逆序拼起来就是CALL指令与被CALL函数地址的差
然后后面的四个字节依次为0xc1、0xfe、0xff、0xff,倒叙组合就是0xFFFFFEC1,这个值指的是当前CALL指令与期望call的函数(此处为printf@plt)的地址差。
所以用call指令所在的地址+地址差就等于:0x000055555555465a+0xFFFFFEC1==0x55565555451B
然后因为一条CALL指令这里占5个字节,所以再在0x55565555451B的基础上+5,就等于了0x55565555451B+5==0x555655554520
0x555655554520就是上图上方那个红框里printf@plt的地址。所以这就是对call指令的一次“翻译”
这就是你发的那个汇编代码中第00000010行的内容

最后于 2019-2-19 20:45 被OxLucifer编辑 ,原因:
2019-2-19 20:45
0
雪    币: 173
活跃值: (807)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
OxLucifer 我这边手头比较方便的有Linux环境,所以我就先用Linux环境给你演示一下,其实原理是一样的。我自己写了一个HelloWorld程序,很简单只是调用了一下printf可以看到我在0x00005555 ...
谢谢!辛苦了!大部分懂了,谢谢这么耐心指导!
最后于 2019-2-19 23:48 被小木鱼编辑 ,原因:
2019-2-19 23:38
0
游客
登录 | 注册 方可回帖
返回
//