CrackMe160 学习笔记 之 067 如何从循环中快速分析算法
前言
这一篇文章起,我打算改变写作风格。
不再是枯燥的逆向分析,更注重方法论。
因为程序那么多,一个一个分析也没多大意义。
以后我会挑选一些值得去分析的程序,更加注重逆向本身的过程。
因为从程序中掌握规律和分析技巧才是真正需要做的。
汇编中的循环
应该都写过循环,就算没写过总应该看过吧。
那么汇编中构成循环需要满足什么条件呢?
得有一个寄存器用来保存循环的计数,还有一个循环的的终止条件(一般是 jnz 指令往回跳)。
没有终止条件那就是死循环了。
再来看一下这个程序,使用了edi作为循环的计数器。
计数器初始化
004013C1 |> \31FF xor edi, edi ; 计数器清零
循环出口
00401432 |> \47 |inc edi ; 计数器加1
00401433 |> \39F7 cmp edi, esi
00401435 |.^ 7C 8E \jl short 004013C5
这样就构成了一个循环,中间的计算过程先省略不提。
开始分析
重点在于快速二字。
通过观察可以发现,
004013C5 |> /89F0 /mov eax, esi
004013C7 |. |29F8 |sub eax, edi
出现了大量完全相同的指令,我们得搞清这个指令是做什么的。
004013C9 |. 0FB6543D AE |movzx edx, byte ptr [ebp+edi-52]
结合上下文,可以得出是用来计算在数组中的偏移值。
这样拆分汇编指令可以节约我们分析的时间。
整体分析
接下来把循环分成三个部分。
计算生成字符串的过程
004013C5 |> /89F0 /mov eax, esi
004013C7 |. |29F8 |sub eax, edi
004013C9 |. |0FB6543D AE |movzx edx, byte ptr [ebp+edi-52]
004013CE |. |31FA |xor edx, edi
004013D0 |. |89D9 |mov ecx, ebx
004013D2 |. |31F9 |xor ecx, edi
004013D4 |. |01CA |add edx, ecx
限制条件
004013E2 |. 3C 20 |cmp al, 20
004013E4 |. 73 0B |jnb short 004013F1
004013E6 |. 89F0 |mov eax, esi
004013E8 |. 29F8 |sub eax, edi
004013EA |. 8D4405 D6 |lea eax, dword ptr [ebp+eax-2A]
004013EE |. 8000 20 |add byte ptr [eax], 20
004013F1 |> 89F0 |mov eax, esi
004013F3 |. 29F8 |sub eax, edi
004013F5 |. 0FB64405 D6 |movzx eax, byte ptr [ebp+eax-2A]
004013FA |. 3D 80000000 |cmp eax, 80
004013FF |. 7C 09 |jl short 0040140A
00401401 |. 89F0 |mov eax, esi
00401403 |. 29F8 |sub eax, edi
00401405 |. C64405 D6 20 |mov byte ptr [ebp+eax-2A], 20
0040140A |> 89F0 |mov eax, esi
验证比较
0040140E |. 8A5405 84 |mov dl, byte ptr [ebp+eax-7C]
00401412 |. 3A5405 D6 |cmp dl, byte ptr [ebp+eax-2A]
00401416 |. 74 1A |je short 00401432
视频分析
具体的分析我会放到视频中去讲。
链接: https://pan.baidu.com/s/1qvL-AhUYj6tMlTpaFX_6LQ 密码: 681t
注册机代码
#include<stdio.h>
#include<string.h>
int main(int argc,char** argv)
{
if(argc!=2) end:return 0;
int len=strlen(argv[1]);
if(len<8) goto end;
for(int i=len-1;i>=0;i--)
{
int v=(argv[1][i]^i)+(len^i);
if(v<0x20) v+=0x20;
if(v>0x80) v=0x20;
printf("%c",v);
}
goto end;
}