1.写在前面的一段话
从开始接触逆向到现在已经有一年的时间了,最开始激情满满,把王爽的汇编看了,硬着头皮把逆向工程看了一半,但是从来没有接触过实际的题目,都是一些纸上谈兵的东西,导致后面的学习越发的困难。而且找不到方向,停滞了半年,如今重新拾起逆向,从做题开始学习。这里也告诫即将进入逆向世界大门的同学,学习还是以项目/问题驱动为好,遇到什么问题,再去查询、学习,这样才不至于失去兴趣和感到迷茫。学习逆向是一个漫长的过程,要有耐心,不要想着一下就吃饱,这样一个简单的逆向,我也是一点点看下来,一点点的分析,前前后后加起来总共花了二十四个小时(纯粹分析和记录程序流程,没有干别的事情)。很多道理道理大家都懂,但是就是不愿意去相信,我深有体会,但是这些东西就是你需要去经历的,需要你花时间上去的。
2.分析
在看这些过程之前,你需要对逆向有一些基础的了解。比如汇编,熟悉DBG、OD、IDA 等等,这些都可以从别人的文章中学到,我写这篇文章主要是为了给自己记录一下,顺带唠叨唠叨。
先打开程序看看这个程序大概是个什么流程,需要做些什么。
输入错误会有弹出框提示。
然后再看看有没有壳。
直接拿到dbg里面去跑,或者先拿到 IDA里面静态分析一波。
DBG中搜索字符串,看看有没有啥好东西。
跳转到关键字符串处
向上找找有没有啥函数是熟悉的
很幸运,这里的函数都非常的明显一个是字符串组合,一个是字符串的移动、还有一个是字符串的比较。直接下断点,进入函数里面去看,然后就一点点分析,我比较粗暴,就直接用寄存器啥的直接干了。要注意 if 的判断。
vbastrcmp( 用户名(encrypted) *x)
{
vabstrcom(密码 S, S, Z)
{
esi = 0;
if (S != 0)
{
eax = &s;
esi = *(s - 4) = Sn;
} //检验S是否等于零,若等于零,则不将个数传入
edi = 0;
if (*x != 0)
{
ecx = &x;
edi = *(x - 4) = Xn;
} //检验X是否等于零,若等于零,则不将个数传入
ebx = edi = Xn;
if (Xn >= Sn) //检验X的个数是否大于等于S的个数
{
mov ebx, esi;
}
if (Z == 0) //多余步骤,传入的参数本来就是0
{
if (ebx != 0) //再次检验S的个数或者X的个数是否为0
{
eax = ebx;
eax = eax / 2; //若个数相符,则执行将S的个数除以二,算数右移
msvbvm50_F00D9EA(eax, *x, S)
{
edi = *x;
esi = S;
ecx = Sn / 2;
eax = 0;
if (S == (*x)) //若不等,则设置CF标志位为1
{
返回上一函数;
} // sbb eax,eax = = eax-eax-CF(1/0)
sbb eax, eax; //若标志位CF 为1 则eax = FFFFFFFF
sbb eax, FFFFFFFF; // eax = FFFFFFFF
返回上一函数; /* */
if (eax == 0)
{
if (bL == 1) // bL有八位,范围很大。故检验的就是S或X的个数
{
if (edi > esi) //再次检验个数是否相符
{
ax = 1;
}
else
{
sbb eax, eax
}
退出strcomp;
} } } } }
movsx eax,ax;
退出strcmp;
分析代码肯定是一个漫长的过程,不过等你一点点的记录,分析完之后,你会觉得有成就感。
这里有几个汇编指令需要学习
sbb eax,eax 。 意思是 eax= eax-eax-CF标志位(0 or 1)
movsx eax,ax。 符号拓展,将ax拓展后 移动到eax中去(正数不变)。
这里掌握了一个比较字符串是否正确的流程。对于破解它没啥意义。但是,如果跟着它一直按F8运行下去,你会看到上上张图中的一个 je 0x004025E5。很明显的一个判断,而它的下面就是输出正确的字符串。
其实分析到这里,也能发现堆栈里面会重复出现一个字符串(前提是你一直输入的是同一个数据),以及你输入的用户密码。可以猜测那个就是加密后的东西。
再对 StrCat 进行分析
这里个函数只需要三个,但是后面运行的话,你可以看到其实它只是将AKA- 与 780297 组合了一下(2222222)是我输入的密码。
所以再向上走,找啊找啊找(我找的时候没啥方法,就是拿着这个程序慢慢跑,到处下断点一点点的看)。直到在
发现了它,F7进入,分析这个函数整体。可以看到一个循环的地方,而且前面有一个在内存中清空的操作。
把edi指向的地址连续清零。这个表示要进行操作了。
这个表示进行加密了
vbstrI4(地址 0019F2AC) //将用户名加密
{
msvb50.F00B349( 0019F1D0/*(存储着0019F2AC)*/ , 0 )
{
getuserDefaultLCID();
VarBstrFromI4( 804 /*上个函数返回的值*/ ,Enc)
{
.......
oleaut32.74CC9E40() //执行加密操作
{
while(Enc!=0)
temp = Enc;
edx = 0;
Enc = temp / 0xA;
temp = temp % 0xA + 30;
[edi] = temp;
edi += 2;
}
}}}
分析Enc 从哪里来的,找到Enc 就找到了
多运行几次可以发现,edi 就是Enc,被当作值传入了 StrI4,且你可以发现 edi 是一个数字,结合LenBstr ,就可以猜到是输入用户名字符串的个数。于是
edi = eax; //eax 为vbaLenBstr() 的返回值,其值为用户名字符串长度
edi = edi * 17CFB;
rtcANsiValueBstr();
Enc = 用户名第一位(ascii)值 + edi;
传入 StrI4 函数。
因此这个程序就是对个数进行加密。只需要关注你输入的第一个数字的值,后面的值不影响。
分析花了很多时间。
还有很多没分析。路还长,慢慢走