-
-
[原创]CTF2016第一组凉飕飕的CrackMe破解分析作业
-
发表于: 2016-11-3 00:57 3725
-
标题:CTF2016第一组凉飕飕的CrackMe破解分析作业
工具:OD+IDA
CrackMe下载:点这里
比赛在工作日,刚坐下屁股就被老板叫去干活,实在没时间参加攻击组,还好我也参加了防御组。
代码为今天晚上分析时将关键几处算法摘录,可能注释得不是很完整,但思路是有的,将就看吧。
先把结论写在开头:
注册码第1位为“1”,第2位为“2”,第3位为“1”,第4位为“5”,第5位为“p”,第6位为“b”,第7位为“8”
连接在一起为:1215pb8,测试成功,但是测试第2次时又提示错误,难道是暗桩?
这与比赛规格“对于正确的注册码必须在何时都能提示成功信息,否则设计不合理”相违背,作者会不会被取消参赛资格或扣除一半分数?
其BUG代码位于00401790处,不应取测试次数关联到取字符串起始位置和长度,导致每次注册码都会改变,甚至后续几次测试无答案。
作品算法方面没有新意,将简单的注册码校验过程拆解成很多片段,绕得人头晕。
摘录分析过程:
//反调试,修改返回值为0 (还有其他反调试、花指令,直接无视)
CALL 004048DE
//要求注册码包含字母“b”
CALL 00401C00
//要求注册码包含字母“p”
CALL 00402A50
//注册码位数为7位
00401DE6 . 83FE 07 CMP ESI,0x7
00401DE9 . 73 0B JNB XCrack_Me.00401DF6
00401DEB . 6A 00 PUSH 0x0
00401DED . 6A 00 PUSH 0x0
00401DEF . 68 0E040000 PUSH 0x40E
00401DF4 . EB 0B JMP XCrack_Me.00401E01
00401DF6 > 76 2C JBE XCrack_Me.00401E24
BOOL __fastcall sub_401A60(int a1, void *a2)
//调试到这里了
00401BA8 |> /83F8 02 /CMP EAX,0x2
00401BAB |. |73 07 |JNB XCrack_Me.00401BB4
//注册码第一位、第二位字符与0xf异或
00401BAD |. |66:833446 0F |XOR WORD PTR DS:[ESI+EAX*2],0xF
00401BB2 |. |EB 11 |JMP XCrack_Me.00401BC5
00401BB4 |> |83F8 04 |CMP EAX,0x4
00401BB7 |. |73 07 |JNB XCrack_Me.00401BC0
//注册码第三位、第四位字符与0x50异或
00401BB9 |. |66:833446 50 |XOR WORD PTR DS:[ESI+EAX*2],0x50
00401BBE |. |EB 05 |JMP XCrack_Me.00401BC5
//注册码第五位、第六位、第七位字符与0x42异或
00401BC0 |> |66:833446 42 |XOR WORD PTR DS:[ESI+EAX*2],0x42
00401BC5 |> |40 |INC EAX
00401BC6 |. |3BC1 |CMP EAX,ECX
00401BC8 |.^\72 DE \JB XCrack_Me.00401BA8
//填充0x30-0x39,对应ASCII“0-9”
0040189D . B8 30000000 MOV EAX,0x30
004018A2 > 66:8901 MOV WORD PTR DS:[ECX],AX
004018A5 . 8D49 02 LEA ECX,DWORD PTR DS:[ECX+0x2]
004018A8 . 40 INC EAX
004018A9 . 83F8 39 CMP EAX,0x39
004018AC .^ 7E F4 JLE XCrack_Me.004018A2
//填充0x61-0x7a,对应ASCII“a-z”
004018AE . B8 61000000 MOV EAX,0x61
004018B3 . 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004018B6 > 66:8901 MOV WORD PTR DS:[ECX],AX
004018B9 . 8D49 02 LEA ECX,DWORD PTR DS:[ECX+0x2]
004018BC . 40 INC EAX
004018BD . 83F8 7A CMP EAX,0x7A
004018C0 .^ 7E F4 JLE XCrack_Me.004018B6
//填充0x41-0x5a,对应ASCII“A-Z”
004018E0 0FB7444D B0 MOVZX EAX,WORD PTR SS:[EBP+ECX*2-0x50]
004018E5 83F8 61 CMP EAX,0x61
004018E8 72 0D JB XCrack_Me.004018F7
004018EA 83F8 7A CMP EAX,0x7A
004018ED 77 08 JA XCrack_Me.004018F7
004018EF 83C0 E0 ADD EAX,-0x20
004018F2 66:89444D B0 MOV WORD PTR SS:[EBP+ECX*2-0x50],AX
004018F7 41 INC ECX
004018F8 3BCA CMP ECX,EDX
004018FA ^ 72 E4 JB XCrack_Me.004018E0
//注册码校验,详细见下文分析
CALL 00401870
//内存数据
001673D8 007F006D
001673DC 00640063
001673E0 00740077
001673E4 00000075
00401920 83F8 02 CMP EAX,0x2
00401923 73 07 JNB XCrack_Me.0040192C
//变形后注册码第一位、第二位字符与0xf异或
00401925 66:833447 0F XOR WORD PTR DS:[EDI+EAX*2],0xF
0040192A EB 11 JMP XCrack_Me.0040193D
0040192C 83F8 04 CMP EAX,0x4
0040192F 73 07 JNB XCrack_Me.00401938
//变形后注册码第三位、第四位字符与0x50异或
00401931 66:833447 50 XOR WORD PTR DS:[EDI+EAX*2],0x50
00401936 EB 05 JMP XCrack_Me.0040193D
//变形后注册码第五位、第六位、第七位字符与0x42异或
00401938 66:833447 42 XOR WORD PTR DS:[EDI+EAX*2],0x42
0040193D 40 INC EAX
0040193E 3BC1 CMP EAX,ECX
00401940 ^ 72 DE JB XCrack_Me.00401920
异或完之后的注册码又变回明文
//内存数据
001673D8 00700062
001673DC 00340033
001673E0 00360035
001673E4 00000037
//注册码小写转为大写
00401960 0FB7044F MOVZX EAX,WORD PTR DS:[EDI+ECX*2]
00401964 83F8 61 CMP EAX,0x61
00401967 72 0C JB XCrack_Me.00401975
00401969 83F8 7A CMP EAX,0x7A
0040196C 77 07 JA XCrack_Me.00401975
0040196E 83C0 E0 ADD EAX,-0x20
00401971 66:89044F MOV WORD PTR DS:[EDI+ECX*2],AX
00401975 41 INC ECX
00401976 3BCA CMP ECX,EDX
00401978 ^ 72 E6 JB XCrack_Me.00401960
//内存数据
001673D8 00500042
001673DC 00340033
001673E0 00360035
001673E4 00000037
//检查注册码每一位,大写字母只能有2个
0040199B 0FB710 MOVZX EDX,WORD PTR DS:[EAX] ; 取注册码每一位
0040199E 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004019A1 33C0 XOR EAX,EAX
004019A3 66:3B11 CMP DX,WORD PTR DS:[ECX]
004019A6 74 10 JE XCrack_Me.004019B8 ; 比较注册码每一位是否为在A-Z之中
004019A8 40 INC EAX
004019A9 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004019AC 66:833C41 00 CMP WORD PTR DS:[ECX+EAX*2],0x0
004019B1 8D0C41 LEA ECX,DWORD PTR DS:[ECX+EAX*2]
004019B4 ^ 75 ED JNZ XCrack_Me.004019A3
004019B6 EB 0B JMP XCrack_Me.004019C3
004019B8 66:8B4445 B0 MOV AX,WORD PTR SS:[EBP+EAX*2-0x50]
004019BD 66:8903 MOV WORD PTR DS:[EBX],AX
004019C0 83C3 02 ADD EBX,0x2
004019C3 66:8B4D B0 MOV CX,WORD PTR SS:[EBP-0x50]
004019C7 46 INC ESI
004019C8 66:833C77 00 CMP WORD PTR DS:[EDI+ESI*2],0x0
004019CD 8D0477 LEA EAX,DWORD PTR DS:[EDI+ESI*2]
004019D0 ^ 75 C4 JNZ XCrack_Me.00401996
004019D2 8B5D AC MOV EBX,DWORD PTR SS:[EBP-0x54]
004019D5 33C9 XOR ECX,ECX
004019D7 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-0x10]
004019DA 66:394D F0 CMP WORD PTR SS:[EBP-0x10],CX
004019DE 74 59 JE XCrack_Me.00401A39
004019E0 8D40 02 LEA EAX,DWORD PTR DS:[EAX+0x2]
004019E3 41 INC ECX
004019E4 66:8338 00 CMP WORD PTR DS:[EAX],0x0
004019E8 ^ 75 F6 JNZ XCrack_Me.004019E0
004019EA 83F9 02 CMP ECX,0x2
004019ED 75 4A JNZ XCrack_Me.00401A39
//校验码
004019F1 C745 F0 31003500 MOV DWORD PTR SS:[EBP-0x10],0x350031 ; 校验 0x31 0x35 0x50 0x42
004019F8 C745 F4 50004200 MOV DWORD PTR SS:[EBP-0xC],Crack_Me.00420050
//内存数据
00E3FC2C 00350031
00E3FC30 00420050 Crack_Me.00420050
//校验注册码与校验码是否相同,要求:1、5、P、B
00401A10 66:8B444D F0 MOV AX,WORD PTR SS:[EBP+ECX*2-0x10]
00401A15 66:3B06 CMP AX,WORD PTR DS:[ESI] ; 注册码第三位必须为“1”,第四位为“5”
00401A18 75 1F JNZ XCrack_Me.00401A39 ; 第五位为“P”,第六位为“B”(转换为大写后)
00401A1A 41 INC ECX
00401A1B 83C6 02 ADD ESI,0x2
00401A1E 83F9 04 CMP ECX,0x4
00401A21 ^ 72 ED JB XCrack_Me.00401A10 ; 4次循环
注册码格式推测:??15pb?,先假设假的注册码:1215pb7
跟踪如下校验子程序:
00401A27 E8 14FDFFFF CALL Crack_Me.00401740
//查看内存
00E4FB8C 0016C668 UNICODE "123456789215PB7"
00E4FB90 0016C738 UNICODE "1215PB7"
//关键代码摘录
0040178C 8B02 MOV EAX,DWORD PTR DS:[EDX] ; 读取测试次数
0040178E 33F6 XOR ESI,ESI
00401790 8D0C43 LEA ECX,DWORD PTR DS:[EBX+EAX*2] ; BUG代码,不应该随测试次数改变ECX值,作者可能会被取消参赛资格或者扣除一半分数
004017AF E8 1C110000 CALL Crack_Me.004028D0 ; 生成“123456789”跟注册码第2-7位连接
004017B4 8D76 FF LEA ESI,DWORD PTR DS:[ESI-0x1]
004017B7 8BF8 MOV EDI,EAX
004017B9 8D0473 LEA EAX,DWORD PTR DS:[EBX+ESI*2]
004017BC 897D B8 MOV DWORD PTR SS:[EBP-0x48],EDI
004017BF 33F6 XOR ESI,ESI
004017C1 8945 B0 MOV DWORD PTR SS:[EBP-0x50],EAX
004017C4 66:3975 DC CMP WORD PTR SS:[EBP-0x24],SI
004017C8 74 31 JE XCrack_Me.004017FB
004017CA 0FB738 MOVZX EDI,WORD PTR DS:[EAX] ; 取注册码最后一位
004017CD 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017D0 83E7 01 AND EDI,0x1 ; EDI=1
004017D3 66:8B01 MOV AX,WORD PTR DS:[ECX] ; 取123456789的每一位
004017D6 66:C1E8 02 SHR AX,0x2 ; 密码表ASCII\4 忽略余数
004017DA 66:03C7 ADD AX,DI ; AX=C+1=D
004017DD 66:83F8 32 CMP AX,0x32 ; 如果AX=0x32
004017E1 74 78 JE XCrack_Me.0040185B
004017E3 66:83F8 64 CMP AX,0x64 ; 如果AX=0x32
004017E7 74 0F JE XCrack_Me.004017F8
004017E9 46 INC ESI
004017EA 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017ED 8D1436 LEA EDX,DWORD PTR DS:[ESI+ESI]
004017F0 03CA ADD ECX,EDX
004017F2 66:8339 00 CMP WORD PTR DS:[ECX],0x0 ; 比较下一位是否结尾
004017F6 ^ 75 DB JNZ XCrack_Me.004017D3
004017F8 8B7D B8 MOV EDI,DWORD PTR SS:[EBP-0x48]
004017FB 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017FE 8BF3 MOV ESI,EBX
00401800 8BC1 MOV EAX,ECX
00401802 BA 31000000 MOV EDX,0x31 ; EDX=0x31
00401807 2BF0 SUB ESI,EAX
00401809 0F1F ??? ; 未知命令
0040180B 8000 00 ADD BYTE PTR DS:[EAX],0x0
0040180E 0000 ADD BYTE PTR DS:[EAX],AL
00401810 66:8B01 MOV AX,WORD PTR DS:[ECX]
00401813 66:3B040E CMP AX,WORD PTR DS:[ESI+ECX] ; 注册码第一位必须为“1”,第二位必须为“2”
00401817 75 42 JNZ XCrack_Me.0040185B
00401819 83C2 06 ADD EDX,0x6 ; EDX=37
0040181C 83C1 02 ADD ECX,0x2
0040181F 83FA 39 CMP EDX,0x39 ; 此处只比较注册码前两位
00401822 ^ 7E EC JLE XCrack_Me.00401810
00401824 0FB74F 12 MOVZX ECX,WORD PTR DS:[EDI+0x12]
00401828 0FB703 MOVZX EAX,WORD PTR DS:[EBX]
0040182B 03C8 ADD ECX,EAX
0040182D 83F9 63 CMP ECX,0x63
00401830 75 29 JNZ XCrack_Me.0040185B
00401832 8B45 B4 MOV EAX,DWORD PTR SS:[EBP-0x4C]
00401835 0FB74F 0C MOVZX ECX,WORD PTR DS:[EDI+0xC] ; 把密码表0x37取出
00401839 0308 ADD ECX,DWORD PTR DS:[EAX] ; 密码表0x37与第0x1次相加=0x38
0040183B 8B45 B0 MOV EAX,DWORD PTR SS:[EBP-0x50]
0040183E 0FB700 MOVZX EAX,WORD PTR DS:[EAX] ; 读取注册码第7位,与0x38比较,说明第7位必须为“8”
00401841 3BC1 CMP EAX,ECX
00401843 75 16 JNZ XCrack_Me.0040185B
//IDA关键代码(摘录片段)
// 此处有BUG,不应取测试次数关联到取字符串起始位置和长度。
// 造成比赛规则无法满足,作者可能会被取消资格或扣除分数。
v8 = sub_4028D0((int)&v20, v2 + 2 * *(_DWORD *)v3);
LABEL_12:
v14 = &v20;
v15 = 0x31;
while ( *(_WORD *)v14 == *(_WORD *)((char *)v14 + v2 - (_DWORD)&v20) )
{
v15 += 6;
v14 = (__int128 *)((char *)v14 + 2);
if ( v15 > 0x39 )
{
if ( *(_WORD *)v2 + *((_WORD *)v8 + 9) == 0x63 && *(_WORD *)v17 == *(_DWORD *)v18 + *((_WORD *)v8 + 6) )
return 1;
return 0;
}
}
//IDA关键代码(摘录片段)
BOOL __fastcall sub_401870(int a1, int a2)
{
v2 = a1;
v3 = a2;
v32 = a1;
sub_4039D0(v33, 0, 54);
v4 = &v34;
v5 = 48;
do
{
*(_WORD *)v4 = v5;
v4 += 2;
++v5;
}
while ( v5 <= 57 );
v6 = 97;
v7 = (int)v33;
do
{
*(_WORD *)v7 = v6;
v7 += 2;
++v6;
}
while ( v6 <= 122 );
v8 = 0;
v9 = (int)v33;
if ( v33[0] )
{
do
{
v9 += 2;
++v8;
}
while ( *(_WORD *)v9 );
}
v10 = 0;
if ( v8 )
{
do
{
v11 = (unsigned __int16)v33[v10];
if ( v11 >= 0x61 && v11 <= 0x7A )
v33[v10] = v11 - 32;
++v10;
}
while ( v10 < v8 );
}
v12 = 0;
v13 = v3;
if ( v3 )
{
if ( *(_WORD *)v3 )
{
do
{
v13 += 2;
++v12;
}
while ( *(_WORD *)v13 );
}
v14 = 0;
if ( v12 )
{
do
{
if ( v14 >= 2 )
{
if ( v14 >= 4 )
*(_WORD *)(v3 + 2 * v14) ^= 0x42u;
else
*(_WORD *)(v3 + 2 * v14) ^= 0x50u;
}
else
{
*(_WORD *)(v3 + 2 * v14) ^= 0xFu;
}
++v14;
}
while ( v14 < v12 );
}
v15 = 0;
for ( i = v3; *(_WORD *)i; ++v15 )
i += 2;
v17 = 0;
if ( v15 )
{
do
{
v18 = *(_WORD *)(v3 + 2 * v17);
if ( v18 >= 0x61 && v18 <= 0x7A )
*(_WORD *)(v3 + 2 * v17) = v18 - 0x20;
++v17;
}
while ( v17 < v15 );
}
}
v19 = 0;
_mm_storel_epi64((__m128i *)&v35, 0i64);
v36 = 0;
if ( *(_WORD *)v3 )
{
v20 = v33[0];
v21 = &v35;
v22 = v3;
do
{
if ( v20 )
{
v23 = *(_WORD *)v22;
v24 = v33;
v25 = 0;
while ( v23 != *v24 )
{
++v25;
v24 = &v33[v25];
if ( !v33[v25] )
goto LABEL_37;
}
*(_WORD *)v21 = v33[v25];
v21 = (__int64 *)((char *)v21 + 2);
LABEL_37:
v20 = v33[0];
}
++v19;
v22 = v3 + 2 * v19;
}
while ( *(_WORD *)(v3 + 2 * v19) );
v2 = v32;
}
v26 = 0;
v27 = &v35;
if ( (_WORD)v35 )
{
do
{
v27 = (__int64 *)((char *)v27 + 2);
++v26;
}
while ( *(_WORD *)v27 );
if ( v26 == 2 )
{
LODWORD(v35) = 0x350031;
HIDWORD(v35) = &unk_420050;
v28 = v3 + 4;
v36 = 0;
v29 = 0;
while ( *((_WORD *)&v35 + v29) == *(_WORD *)v28 )
{
++v29;
v28 += 2;
if ( v29 >= 4 )
{
if ( !sub_401740(v2, v3) )
break;
v31 = 0x40B; //消息传递0x40B对应注册成功代码
return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0);
}
}
}
}
v31 = 0x40A;
return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0);
}
工具:OD+IDA
CrackMe下载:点这里
比赛在工作日,刚坐下屁股就被老板叫去干活,实在没时间参加攻击组,还好我也参加了防御组。
代码为今天晚上分析时将关键几处算法摘录,可能注释得不是很完整,但思路是有的,将就看吧。
先把结论写在开头:
注册码第1位为“1”,第2位为“2”,第3位为“1”,第4位为“5”,第5位为“p”,第6位为“b”,第7位为“8”
连接在一起为:1215pb8,测试成功,但是测试第2次时又提示错误,难道是暗桩?
这与比赛规格“对于正确的注册码必须在何时都能提示成功信息,否则设计不合理”相违背,作者会不会被取消参赛资格或扣除一半分数?
其BUG代码位于00401790处,不应取测试次数关联到取字符串起始位置和长度,导致每次注册码都会改变,甚至后续几次测试无答案。
作品算法方面没有新意,将简单的注册码校验过程拆解成很多片段,绕得人头晕。
摘录分析过程:
//反调试,修改返回值为0 (还有其他反调试、花指令,直接无视)
CALL 004048DE
//要求注册码包含字母“b”
CALL 00401C00
//要求注册码包含字母“p”
CALL 00402A50
//注册码位数为7位
00401DE6 . 83FE 07 CMP ESI,0x7
00401DE9 . 73 0B JNB XCrack_Me.00401DF6
00401DEB . 6A 00 PUSH 0x0
00401DED . 6A 00 PUSH 0x0
00401DEF . 68 0E040000 PUSH 0x40E
00401DF4 . EB 0B JMP XCrack_Me.00401E01
00401DF6 > 76 2C JBE XCrack_Me.00401E24
BOOL __fastcall sub_401A60(int a1, void *a2)
//调试到这里了
00401BA8 |> /83F8 02 /CMP EAX,0x2
00401BAB |. |73 07 |JNB XCrack_Me.00401BB4
//注册码第一位、第二位字符与0xf异或
00401BAD |. |66:833446 0F |XOR WORD PTR DS:[ESI+EAX*2],0xF
00401BB2 |. |EB 11 |JMP XCrack_Me.00401BC5
00401BB4 |> |83F8 04 |CMP EAX,0x4
00401BB7 |. |73 07 |JNB XCrack_Me.00401BC0
//注册码第三位、第四位字符与0x50异或
00401BB9 |. |66:833446 50 |XOR WORD PTR DS:[ESI+EAX*2],0x50
00401BBE |. |EB 05 |JMP XCrack_Me.00401BC5
//注册码第五位、第六位、第七位字符与0x42异或
00401BC0 |> |66:833446 42 |XOR WORD PTR DS:[ESI+EAX*2],0x42
00401BC5 |> |40 |INC EAX
00401BC6 |. |3BC1 |CMP EAX,ECX
00401BC8 |.^\72 DE \JB XCrack_Me.00401BA8
//填充0x30-0x39,对应ASCII“0-9”
0040189D . B8 30000000 MOV EAX,0x30
004018A2 > 66:8901 MOV WORD PTR DS:[ECX],AX
004018A5 . 8D49 02 LEA ECX,DWORD PTR DS:[ECX+0x2]
004018A8 . 40 INC EAX
004018A9 . 83F8 39 CMP EAX,0x39
004018AC .^ 7E F4 JLE XCrack_Me.004018A2
//填充0x61-0x7a,对应ASCII“a-z”
004018AE . B8 61000000 MOV EAX,0x61
004018B3 . 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004018B6 > 66:8901 MOV WORD PTR DS:[ECX],AX
004018B9 . 8D49 02 LEA ECX,DWORD PTR DS:[ECX+0x2]
004018BC . 40 INC EAX
004018BD . 83F8 7A CMP EAX,0x7A
004018C0 .^ 7E F4 JLE XCrack_Me.004018B6
//填充0x41-0x5a,对应ASCII“A-Z”
004018E0 0FB7444D B0 MOVZX EAX,WORD PTR SS:[EBP+ECX*2-0x50]
004018E5 83F8 61 CMP EAX,0x61
004018E8 72 0D JB XCrack_Me.004018F7
004018EA 83F8 7A CMP EAX,0x7A
004018ED 77 08 JA XCrack_Me.004018F7
004018EF 83C0 E0 ADD EAX,-0x20
004018F2 66:89444D B0 MOV WORD PTR SS:[EBP+ECX*2-0x50],AX
004018F7 41 INC ECX
004018F8 3BCA CMP ECX,EDX
004018FA ^ 72 E4 JB XCrack_Me.004018E0
//注册码校验,详细见下文分析
CALL 00401870
//内存数据
001673D8 007F006D
001673DC 00640063
001673E0 00740077
001673E4 00000075
00401920 83F8 02 CMP EAX,0x2
00401923 73 07 JNB XCrack_Me.0040192C
//变形后注册码第一位、第二位字符与0xf异或
00401925 66:833447 0F XOR WORD PTR DS:[EDI+EAX*2],0xF
0040192A EB 11 JMP XCrack_Me.0040193D
0040192C 83F8 04 CMP EAX,0x4
0040192F 73 07 JNB XCrack_Me.00401938
//变形后注册码第三位、第四位字符与0x50异或
00401931 66:833447 50 XOR WORD PTR DS:[EDI+EAX*2],0x50
00401936 EB 05 JMP XCrack_Me.0040193D
//变形后注册码第五位、第六位、第七位字符与0x42异或
00401938 66:833447 42 XOR WORD PTR DS:[EDI+EAX*2],0x42
0040193D 40 INC EAX
0040193E 3BC1 CMP EAX,ECX
00401940 ^ 72 DE JB XCrack_Me.00401920
异或完之后的注册码又变回明文
//内存数据
001673D8 00700062
001673DC 00340033
001673E0 00360035
001673E4 00000037
//注册码小写转为大写
00401960 0FB7044F MOVZX EAX,WORD PTR DS:[EDI+ECX*2]
00401964 83F8 61 CMP EAX,0x61
00401967 72 0C JB XCrack_Me.00401975
00401969 83F8 7A CMP EAX,0x7A
0040196C 77 07 JA XCrack_Me.00401975
0040196E 83C0 E0 ADD EAX,-0x20
00401971 66:89044F MOV WORD PTR DS:[EDI+ECX*2],AX
00401975 41 INC ECX
00401976 3BCA CMP ECX,EDX
00401978 ^ 72 E6 JB XCrack_Me.00401960
//内存数据
001673D8 00500042
001673DC 00340033
001673E0 00360035
001673E4 00000037
//检查注册码每一位,大写字母只能有2个
0040199B 0FB710 MOVZX EDX,WORD PTR DS:[EAX] ; 取注册码每一位
0040199E 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004019A1 33C0 XOR EAX,EAX
004019A3 66:3B11 CMP DX,WORD PTR DS:[ECX]
004019A6 74 10 JE XCrack_Me.004019B8 ; 比较注册码每一位是否为在A-Z之中
004019A8 40 INC EAX
004019A9 8D4D B0 LEA ECX,DWORD PTR SS:[EBP-0x50]
004019AC 66:833C41 00 CMP WORD PTR DS:[ECX+EAX*2],0x0
004019B1 8D0C41 LEA ECX,DWORD PTR DS:[ECX+EAX*2]
004019B4 ^ 75 ED JNZ XCrack_Me.004019A3
004019B6 EB 0B JMP XCrack_Me.004019C3
004019B8 66:8B4445 B0 MOV AX,WORD PTR SS:[EBP+EAX*2-0x50]
004019BD 66:8903 MOV WORD PTR DS:[EBX],AX
004019C0 83C3 02 ADD EBX,0x2
004019C3 66:8B4D B0 MOV CX,WORD PTR SS:[EBP-0x50]
004019C7 46 INC ESI
004019C8 66:833C77 00 CMP WORD PTR DS:[EDI+ESI*2],0x0
004019CD 8D0477 LEA EAX,DWORD PTR DS:[EDI+ESI*2]
004019D0 ^ 75 C4 JNZ XCrack_Me.00401996
004019D2 8B5D AC MOV EBX,DWORD PTR SS:[EBP-0x54]
004019D5 33C9 XOR ECX,ECX
004019D7 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-0x10]
004019DA 66:394D F0 CMP WORD PTR SS:[EBP-0x10],CX
004019DE 74 59 JE XCrack_Me.00401A39
004019E0 8D40 02 LEA EAX,DWORD PTR DS:[EAX+0x2]
004019E3 41 INC ECX
004019E4 66:8338 00 CMP WORD PTR DS:[EAX],0x0
004019E8 ^ 75 F6 JNZ XCrack_Me.004019E0
004019EA 83F9 02 CMP ECX,0x2
004019ED 75 4A JNZ XCrack_Me.00401A39
//校验码
004019F1 C745 F0 31003500 MOV DWORD PTR SS:[EBP-0x10],0x350031 ; 校验 0x31 0x35 0x50 0x42
004019F8 C745 F4 50004200 MOV DWORD PTR SS:[EBP-0xC],Crack_Me.00420050
//内存数据
00E3FC2C 00350031
00E3FC30 00420050 Crack_Me.00420050
//校验注册码与校验码是否相同,要求:1、5、P、B
00401A10 66:8B444D F0 MOV AX,WORD PTR SS:[EBP+ECX*2-0x10]
00401A15 66:3B06 CMP AX,WORD PTR DS:[ESI] ; 注册码第三位必须为“1”,第四位为“5”
00401A18 75 1F JNZ XCrack_Me.00401A39 ; 第五位为“P”,第六位为“B”(转换为大写后)
00401A1A 41 INC ECX
00401A1B 83C6 02 ADD ESI,0x2
00401A1E 83F9 04 CMP ECX,0x4
00401A21 ^ 72 ED JB XCrack_Me.00401A10 ; 4次循环
注册码格式推测:??15pb?,先假设假的注册码:1215pb7
跟踪如下校验子程序:
00401A27 E8 14FDFFFF CALL Crack_Me.00401740
//查看内存
00E4FB8C 0016C668 UNICODE "123456789215PB7"
00E4FB90 0016C738 UNICODE "1215PB7"
//关键代码摘录
0040178C 8B02 MOV EAX,DWORD PTR DS:[EDX] ; 读取测试次数
0040178E 33F6 XOR ESI,ESI
00401790 8D0C43 LEA ECX,DWORD PTR DS:[EBX+EAX*2] ; BUG代码,不应该随测试次数改变ECX值,作者可能会被取消参赛资格或者扣除一半分数
004017AF E8 1C110000 CALL Crack_Me.004028D0 ; 生成“123456789”跟注册码第2-7位连接
004017B4 8D76 FF LEA ESI,DWORD PTR DS:[ESI-0x1]
004017B7 8BF8 MOV EDI,EAX
004017B9 8D0473 LEA EAX,DWORD PTR DS:[EBX+ESI*2]
004017BC 897D B8 MOV DWORD PTR SS:[EBP-0x48],EDI
004017BF 33F6 XOR ESI,ESI
004017C1 8945 B0 MOV DWORD PTR SS:[EBP-0x50],EAX
004017C4 66:3975 DC CMP WORD PTR SS:[EBP-0x24],SI
004017C8 74 31 JE XCrack_Me.004017FB
004017CA 0FB738 MOVZX EDI,WORD PTR DS:[EAX] ; 取注册码最后一位
004017CD 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017D0 83E7 01 AND EDI,0x1 ; EDI=1
004017D3 66:8B01 MOV AX,WORD PTR DS:[ECX] ; 取123456789的每一位
004017D6 66:C1E8 02 SHR AX,0x2 ; 密码表ASCII\4 忽略余数
004017DA 66:03C7 ADD AX,DI ; AX=C+1=D
004017DD 66:83F8 32 CMP AX,0x32 ; 如果AX=0x32
004017E1 74 78 JE XCrack_Me.0040185B
004017E3 66:83F8 64 CMP AX,0x64 ; 如果AX=0x32
004017E7 74 0F JE XCrack_Me.004017F8
004017E9 46 INC ESI
004017EA 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017ED 8D1436 LEA EDX,DWORD PTR DS:[ESI+ESI]
004017F0 03CA ADD ECX,EDX
004017F2 66:8339 00 CMP WORD PTR DS:[ECX],0x0 ; 比较下一位是否结尾
004017F6 ^ 75 DB JNZ XCrack_Me.004017D3
004017F8 8B7D B8 MOV EDI,DWORD PTR SS:[EBP-0x48]
004017FB 8D4D DC LEA ECX,DWORD PTR SS:[EBP-0x24]
004017FE 8BF3 MOV ESI,EBX
00401800 8BC1 MOV EAX,ECX
00401802 BA 31000000 MOV EDX,0x31 ; EDX=0x31
00401807 2BF0 SUB ESI,EAX
00401809 0F1F ??? ; 未知命令
0040180B 8000 00 ADD BYTE PTR DS:[EAX],0x0
0040180E 0000 ADD BYTE PTR DS:[EAX],AL
00401810 66:8B01 MOV AX,WORD PTR DS:[ECX]
00401813 66:3B040E CMP AX,WORD PTR DS:[ESI+ECX] ; 注册码第一位必须为“1”,第二位必须为“2”
00401817 75 42 JNZ XCrack_Me.0040185B
00401819 83C2 06 ADD EDX,0x6 ; EDX=37
0040181C 83C1 02 ADD ECX,0x2
0040181F 83FA 39 CMP EDX,0x39 ; 此处只比较注册码前两位
00401822 ^ 7E EC JLE XCrack_Me.00401810
00401824 0FB74F 12 MOVZX ECX,WORD PTR DS:[EDI+0x12]
00401828 0FB703 MOVZX EAX,WORD PTR DS:[EBX]
0040182B 03C8 ADD ECX,EAX
0040182D 83F9 63 CMP ECX,0x63
00401830 75 29 JNZ XCrack_Me.0040185B
00401832 8B45 B4 MOV EAX,DWORD PTR SS:[EBP-0x4C]
00401835 0FB74F 0C MOVZX ECX,WORD PTR DS:[EDI+0xC] ; 把密码表0x37取出
00401839 0308 ADD ECX,DWORD PTR DS:[EAX] ; 密码表0x37与第0x1次相加=0x38
0040183B 8B45 B0 MOV EAX,DWORD PTR SS:[EBP-0x50]
0040183E 0FB700 MOVZX EAX,WORD PTR DS:[EAX] ; 读取注册码第7位,与0x38比较,说明第7位必须为“8”
00401841 3BC1 CMP EAX,ECX
00401843 75 16 JNZ XCrack_Me.0040185B
//IDA关键代码(摘录片段)
// 此处有BUG,不应取测试次数关联到取字符串起始位置和长度。
// 造成比赛规则无法满足,作者可能会被取消资格或扣除分数。
v8 = sub_4028D0((int)&v20, v2 + 2 * *(_DWORD *)v3);
LABEL_12:
v14 = &v20;
v15 = 0x31;
while ( *(_WORD *)v14 == *(_WORD *)((char *)v14 + v2 - (_DWORD)&v20) )
{
v15 += 6;
v14 = (__int128 *)((char *)v14 + 2);
if ( v15 > 0x39 )
{
if ( *(_WORD *)v2 + *((_WORD *)v8 + 9) == 0x63 && *(_WORD *)v17 == *(_DWORD *)v18 + *((_WORD *)v8 + 6) )
return 1;
return 0;
}
}
//IDA关键代码(摘录片段)
BOOL __fastcall sub_401870(int a1, int a2)
{
v2 = a1;
v3 = a2;
v32 = a1;
sub_4039D0(v33, 0, 54);
v4 = &v34;
v5 = 48;
do
{
*(_WORD *)v4 = v5;
v4 += 2;
++v5;
}
while ( v5 <= 57 );
v6 = 97;
v7 = (int)v33;
do
{
*(_WORD *)v7 = v6;
v7 += 2;
++v6;
}
while ( v6 <= 122 );
v8 = 0;
v9 = (int)v33;
if ( v33[0] )
{
do
{
v9 += 2;
++v8;
}
while ( *(_WORD *)v9 );
}
v10 = 0;
if ( v8 )
{
do
{
v11 = (unsigned __int16)v33[v10];
if ( v11 >= 0x61 && v11 <= 0x7A )
v33[v10] = v11 - 32;
++v10;
}
while ( v10 < v8 );
}
v12 = 0;
v13 = v3;
if ( v3 )
{
if ( *(_WORD *)v3 )
{
do
{
v13 += 2;
++v12;
}
while ( *(_WORD *)v13 );
}
v14 = 0;
if ( v12 )
{
do
{
if ( v14 >= 2 )
{
if ( v14 >= 4 )
*(_WORD *)(v3 + 2 * v14) ^= 0x42u;
else
*(_WORD *)(v3 + 2 * v14) ^= 0x50u;
}
else
{
*(_WORD *)(v3 + 2 * v14) ^= 0xFu;
}
++v14;
}
while ( v14 < v12 );
}
v15 = 0;
for ( i = v3; *(_WORD *)i; ++v15 )
i += 2;
v17 = 0;
if ( v15 )
{
do
{
v18 = *(_WORD *)(v3 + 2 * v17);
if ( v18 >= 0x61 && v18 <= 0x7A )
*(_WORD *)(v3 + 2 * v17) = v18 - 0x20;
++v17;
}
while ( v17 < v15 );
}
}
v19 = 0;
_mm_storel_epi64((__m128i *)&v35, 0i64);
v36 = 0;
if ( *(_WORD *)v3 )
{
v20 = v33[0];
v21 = &v35;
v22 = v3;
do
{
if ( v20 )
{
v23 = *(_WORD *)v22;
v24 = v33;
v25 = 0;
while ( v23 != *v24 )
{
++v25;
v24 = &v33[v25];
if ( !v33[v25] )
goto LABEL_37;
}
*(_WORD *)v21 = v33[v25];
v21 = (__int64 *)((char *)v21 + 2);
LABEL_37:
v20 = v33[0];
}
++v19;
v22 = v3 + 2 * v19;
}
while ( *(_WORD *)(v3 + 2 * v19) );
v2 = v32;
}
v26 = 0;
v27 = &v35;
if ( (_WORD)v35 )
{
do
{
v27 = (__int64 *)((char *)v27 + 2);
++v26;
}
while ( *(_WORD *)v27 );
if ( v26 == 2 )
{
LODWORD(v35) = 0x350031;
HIDWORD(v35) = &unk_420050;
v28 = v3 + 4;
v36 = 0;
v29 = 0;
while ( *((_WORD *)&v35 + v29) == *(_WORD *)v28 )
{
++v29;
v28 += 2;
if ( v29 >= 4 )
{
if ( !sub_401740(v2, v3) )
break;
v31 = 0x40B; //消息传递0x40B对应注册成功代码
return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0);
}
}
}
}
v31 = 0x40A;
return PostMessageW(*(HWND *)(v2 + 4), 0x111u, v31, 0);
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
他的文章
谁下载
AloneWolf
keheng
风间仁
ooshanshui
qsy
netwind
爱琴海
久久小斌
库洛洛
findlakes
DiYhAcK
magicboy
bgptlmzyh
lacoucou
zhangbuib
woaixj
character
lizhenzhe
brichfire
Kisesy
cqccqc
burnett
daiwenyi
SilentGamb
MaMy
zhj张尼玛
orz1ruo
kaoyange
da一二三hai
悠悠wzq
KenLi
qdwj
OneLynn
伊邪那美
rhirufxmbcyj
要叫啥
mratlatsn
飘碎
半盲道人
LuanTanQin
柒小苦瓜
moonsuna
rtlcom
岁月。
渡。
IntThree
mmmmman
zzzpany
雪天出生的人
泪落晨曦
Andersz
Mirages
imstudy
小叶想谈恋爱
newbieyu
moods
ReeHY
evilG
wendax
村民九号
v字领
鼻塞
pandakim
HakuNAv
Limpidity
我真的好笨
看原图
赞赏
雪币:
留言: