第三关涉及到一个加密算法和注册机的编写,比较复杂,首先简单破解程序
使用命令 bp GetWindowTextA 下断点,找到获取字符串的关键代码
发现用户名和序列号分别被存在了,004053B0 和 004053A0,果断下内存断点,发现了判断长度的关键代码
这里其实是Strlen()这个函数翻译成汇编的执行过程,
参考:
重复前缀指令
任何一个串操作指令,都可以在前面加一个重复前缀,以实现串操作的重复执行,重复次数隐含在CX寄存器中
REP ;REP前缀用在MOVS、STOS、LODS指令前,每次执行一次指令,CX减1;直到CX=0,重复执行结束
REPZ ;也可以表把为REPE,用在CMPS、SCAS指令前,每执行一次串指令CX减1,并判断ZF标志是否为0
;只要CX=0或ZF=0,则重复执行结束
REPNZ ;也可以表达为REPNE,用在CMPS、SCAS指令前,每执行一次串操作指令CX减1,并判断ZF标志是否为1,只要CX=0或ZF=1,则重复执行结束。
串扫描指令SCAS
SCASB ;字节串扫描:AL-ES:[DI],DI←DI+/-1
SCASW ;字串扫描:AX-ES:[DI],DI←DI+/-2
串扫描指令SCAS将附加段中的字节或字内容与AL/AX寄存器内容进行比较,根据比较的结果设置标志,每次比较后修改DI寄存器的值,使之指向下一个元素。
解释:
假设esp+10指向字符串如:"xqiang",长度为6,以0结尾
ecx=FFFFFFFF
eax=0,则al=0
执行repne scas时候:
第一次:
al-'x',di=di-1,即byte ptr es:[edi]指向'q',并置相应的标志位
然后cx-1,则ecx=FFFFFFFE,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第二次:
al-'q',di=di-1,即byte ptr es:[edi]指向'i',并置相应的标志位
然后cx-1,则ecx=FFFFFFFD,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第三次:
al-'i',di=di-1,即byte ptr es:[edi]指向'a',并置相应的标志位
然后cx-1,则ecx=FFFFFFFC,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第三次:
al-'a',di=di-1,即byte ptr es:[edi]指向'n',并置相应的标志位
然后cx-1,则ecx=FFFFFFFB,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第四次:
al-'n',di=di-1,即byte ptr es:[edi]指向'g',并置相应的标志位
然后cx-1,则ecx=FFFFFFFA,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第五次:
al-'g',di=di-1,即byte ptr es:[edi]指向'0',并置相应的标志位
然后cx-1,则ecx=FFFFFFF9,判断是否cx=0或ZF=1,显然该处条件不成立,继续重复执行
第六次:
al-0,di=di-1,即byte ptr es:[edi]指向'未知字符',并置相应的标志位
然后cx-1,则ecx=FFFFFFF8,判断是否cx=0或ZF=1,此时ZF=1,停止串搜索
现在ecx从FFFFFFFF到FFFFFFF8记录了字符串'xqiang'和0的长度
然后not ecx得到ecx=00000007
dec ecx得到ecx=00000006 该长度就是字符串'xqiang'的实际长度
这里吧jb这个转跳给nop掉,就可以跳过长度的检测。
另外rep 还经常和 movs 和 stos 组合
具体看这里http://jpkc.zzu.edu.cn/hbyycai/courses/list.asp?id=131
根据程序运行的尿性,使用bp createWindowExa下断,找到关键代码
之前的转跳首先得nop掉,这里直接改成je,下面SetWindowTextA是设置窗口里面的文字的,首先把转跳干掉,再在内存中
写入“恭喜你,注册成功“之类的话,吧指针push进去就行了。
SetWindowTextA的定义如下
BOOL SetWindowText(HWND hwnd,LPCTSTR lpString)
第一个窗口句柄,第二个字符串指针。这么说,上图中eax是句柄,不要动它
ecx是字符串指针,我们修改它。
修改后如下
直接暴力的吧值赋给ecx,再把它push进去就可以了,其他语句用nop填就好,这些修改都改完了,程序的爆破就完成了。
最近试了一些IDA的F5插件感觉不错,把加密的代码直接转成了c,这样分析起来就会格外方便,不过在这里就不分析了,
最近想搞搞破解,先把antiy 的crack做完吧~
HWND __cdecl sub_401BD0(HWND hWnd)
{
HWND result; // eax@1
int v2; // edx@5
int v3; // ecx@5
unsigned int v4; // eax@6
signed int v5; // ecx@6
signed int v6; // ST2C_4@6
signed int v7; // eax@11
unsigned int v8; // eax@13
const CHAR *v9; // ecx@13
char *v10; // esi@13
int v11; // edx@15
int v12; // ecx@15
unsigned int v13; // eax@16
signed int v14; // ecx@16
signed int v15; // ST2C_4@16
signed int v16; // eax@21
int v17; // esi@4
int v18; // ecx@4
unsigned __int8 v19; // cf@7
const CHAR v20; // dl@14
unsigned __int8 v21; // cf@17
int v22; // [sp+8h] [bp-414h]@5
char v23; // [sp+Ch] [bp-410h]@5
int v24; // [sp+4h] [bp-418h]@10
const CHAR String; // [sp+408h] [bp-14h]@13
int v26; // [sp+409h] [bp-13h]@13
int v27; // [sp+40Dh] [bp-Fh]@13
int v28; // [sp+411h] [bp-Bh]@13
int v29; // [sp+415h] [bp-7h]@13
result = 0;
if ( strlen(String) - 1 >= 4 )
{
if ( strlen(dword_4053A0) - 1 >= 8 )
{
memset(byte_4047A0, 0, 0xC00u);
do
{
v17 = dword_4053A0[(_BYTE)result & 0xF];
v18 = String[(_BYTE)result++ & 0xF];
*(_BYTE *)((_DWORD)byte_40479F + (_DWORD)result) = *(&(*off_401174)[v17] + v18);
}
while ( (unsigned int)result < 0xC00 );
v22 = 0;
memset(&v23, 0, 0x3FCu);
v2 = -1;
v3 = 256;
do
{
v4 = v3 - 1;
v6 = v3;
v5 = 8;
do
{
v19 = __MKCSHR__(v4, 1);
v4 >>= 1;
if ( v19 )
v4 ^= 0xEDB88320u;
--v5;
}
while ( v5 );
*(&v24 + v6) = v4;
v3 = v6 - 1;
}
while ( v6 != 1 );
v7 = 0;
do
v2 = *(&v22 + ((_BYTE)v2 ^ byte_4047A0[v7++])) ^ ((unsigned int)v2 >> 8);
while ( v7 < 3072 );
String = 0;
v9 = &String;
v10 = (char *)&dword_4010DE + (unsigned __int8)~(_BYTE)v2 % 0x6Du;
v26 = 0;
v8 = 0;
v27 = 0;
v28 = 0;
v29 = 0;
do
{
v20 = v10[v8];
v8 += 2;
*v9++ = v20;
}
while ( v8 < 0x20 );
v22 = 0;
memset(&v23, 0, 0x3FCu);
v11 = -1;
v12 = 256;
do
{
v13 = v12 - 1;
v15 = v12;
v14 = 8;
do
{
v21 = __MKCSHR__(v13, 1);
v13 >>= 1;
if ( v21 )
v13 ^= 0xEDB88320u;
--v14;
}
while ( v14 );
*(&v24 + v15) = v13;
v12 = v15 - 1;
}
while ( v15 != 1 );
v16 = 0;
do
v11 = *(&v22 + ((_BYTE)v11 ^ *(&String + v16++))) ^ ((unsigned int)v11 >> 8);
while ( v16 < 16 );
if ( ~v11 == *((_DWORD *)v10 + 8) )
{
result = CreateWindowExA(0x20000u, "STATIC", "提示", 0x10CF0001u, 0, 0, 180, 90, hWnd, 0, 0, 0);
if ( result )
result = (HWND)SetWindowTextA(result, &String);
}
else
{
result = (HWND)MessageBoxA(hWnd, "注册失败", "错?, 0x10u);
}
}
}
return result;
}