能力值:
( 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
被顾言庭编辑
,原因:
|
能力值:
( LV3,RANK:20 )
|
-
-
3 楼
顾言庭
```
' 00000000 PUSH EBX
' 00000001 PUSH ECX #保存寄存器中的值
' 00000002 MOV EAX,[EBP+8] #取参数(大概 ...
谢谢您,元宵快乐!
|
能力值:
( LV13,RANK:327 )
|
-
-
4 楼
举手之劳,何足挂齿。 元宵节快乐!
|
能力值:
( 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编辑
,原因:
|
能力值:
( LV3,RANK:20 )
|
-
-
6 楼
OxLucifer
//我觉得LZ可以去看一下E8指令是什么
//比如可以手动写个main函数,然后让其随便CALL一个函数,然后看一下CALL指令及周围的字节内容
//保存寄存器
00000000&n ...
谢谢大牛这么详细的讲解
最后于 2019-2-19 20:02
被小木鱼编辑
,原因:
|
能力值:
( LV3,RANK:20 )
|
-
-
7 楼
//下面这里通过对call指令硬编码方式求解出期望call的函数地址,结果保存在EBX寄存器中
00000010 LEA EBX,[EAX+ECX+5] 这里的eax指向的是call的地址,+5正好是call xxxxxxxx后的一行所占的内存地址,
而ecx=[eax+1],这个应该是指向什么具体意义的值呢?
对这句的硬编码计算不是很了解,希望能得到再次解答!
|
能力值:
( LV3,RANK:20 )
|
-
-
8 楼
顾言庭
举手之劳,何足挂齿。
元宵节快乐!
嗯嗯!
|
能力值:
( 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;
}
} 获取到的汇编图表如下: 我很新手,希望帮忙解答下,这样的情况,怎么汇编模式下分析代码呢?
|
能力值:
( 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编辑
,原因:
|
能力值:
( LV3,RANK:20 )
|
-
-
11 楼
OxLucifer
我这边手头比较方便的有Linux环境,所以我就先用Linux环境给你演示一下,其实原理是一样的。我自己写了一个HelloWorld程序,很简单只是调用了一下printf可以看到我在0x00005555 ...
谢谢!辛苦了!大部分懂了,谢谢这么耐心指导!
最后于 2019-2-19 23:48
被小木鱼编辑
,原因:
|
|
|