第三关涉及到一个加密算法和注册机的编写,比较复杂,首先简单破解程序
使用命令 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'的实际长度
另外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是字符串指针,我们修改它。
修改后如下
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; }