od 打开crackme,查找所有参考字符串发现
004039E5 68 30484000 PUSH kanxue-c.00404830
004039EA BA 90A04300 MOV EDX,kanxue-c.0043A090 ; ASCII "correct!"
004039EF B9 38F04300 MOV ECX,kanxue-c.0043F038
004039F4 E8 27090000 CALL kanxue-c.00404320
这应该是表示注册成功提示,所以向上找跳转
0040399E A1 70014400 MOV EAX,DWORD PTR DS:[440170]
004039A3 0FBE48 01 MOVSX ECX,BYTE PTR DS:[EAX+1]
004039A7 83F9 01 CMP ECX,1
004039AA 0F85 95000000 JNZ kanxue-c.00403A45
004039B0 57 PUSH EDI
004039B1 FF7424 20 PUSH DWORD PTR SS:[ESP+20]
找到一个,将BYTE PTR DS:[EAX+1]修改为1,运行之后发现"correct!",表示这个位置没错。接下来分析DWORD PTR DS:[440170]这个地址
通过查找所有地址常量列出所有引用该地址的代码,其中关键的为
0040344F . 8D4D 90 LEA ECX,DWORD PTR SS:[EBP-70]
00403452 . E8 C9060000 CALL kanxue-c.00403B20 ; stringcmp
00403457 . 85C0 TEST EAX,EAX ; ==0 -> ok
00403459 . 75 0A JNZ SHORT kanxue-c.00403465
0040345B . 8B0D 70014400 MOV ECX,DWORD PTR DS:[440170]
00403461 . C641 01 01 MOV BYTE PTR DS:[ECX+1],1 ; <- 这里
00403465 > C785 38FFFFFF >MOV DWORD PTR SS:[EBP-C8],0
0040346F . 8D4D 90 LEA ECX,DWORD PTR SS:[EBP-70]
地址 0043E628 ; g_SN
为全局对比值SN,为
00626DD8 C8 E5 E2 C3 C4 39 FC 04 48 D8 0F 8B 5F 73 8C A9 儒饷??H?媉s尒
继续往上找
004032BF . E8 3CE7FFFF CALL kanxue-c.00401A00 ; strtol
004032C4 . 83C4 08 ADD ESP,8
004032C7 . C645 FC 03 MOV BYTE PTR SS:[EBP-4],3
004032CB . 8D4D D8 LEA ECX,DWORD PTR SS:[EBP-28]
004032CE . E8 6DE8FFFF CALL kanxue-c.00401B40
004032D3 . C645 FC 04 MOV BYTE PTR SS:[EBP-4],4
004032D7 . 8D45 D8 LEA EAX,DWORD PTR SS:[EBP-28]
004032DA . 50 PUSH EAX
004032DB . 8D4D A8 LEA ECX,DWORD PTR SS:[EBP-58]
004032DE . 51 PUSH ECX
004032DF . E8 1CE4FFFF CALL kanxue-c.00401700 ; RSA
004032E4 . 83C4 08 ADD ESP,8
发现作者使用了libtomcrypt密码学库
这里是将输入序列号转换到long类型,之后进行RSA解密操作,通过跟踪RSA过程发现公钥为
00439FA0 30 20 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 0 0..*咹嗺.
00439FB0 00 03 0F 00 30 0C 02 05 00 F5 74 FD 11 02 03 01 ..0..鮰?
00439FC0 00 01 .
通过DER解码为
0 30 32: SEQUENCE {
2 30 13: SEQUENCE {
4 06 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
15 05 0: NULL
: }
17 03 15: BIT STRING 0 unused bits
: 30 0C 02 05 00 F5 74 FD 11 02 03 01 00 01
: }
N = F574FD11
使用RSA tool分解N得到私钥
D = 2BBE7481
serial = 私钥D加密(M),M为公钥解密的明文,注意RSA解密结果只取2个字节
继续向下分析,来到
00403434 . 8D45 90 LEA EAX,DWORD PTR SS:[EBP-70]
00403437 . 50 PUSH EAX
00403438 . C645 FC 05 MOV BYTE PTR SS:[EBP-4],5
0040343C . E8 1FE4FFFF CALL kanxue-c.00401860 ; SN=AES_EN(X)
00403441 . 83C4 34 ADD ESP,34
00403444 . 8985 30FFFFFF MOV DWORD PTR SS:[EBP-D0],EAX
分析00401860函数可知为AES256加密,如下:
通过分析00401860 这个函数,得出SN=AES_EN(),返回值参与stringcmp比较,分析过程如下:
004018F3 . E8 D8910000 call 0040AAD0 ; aes_key_expansion
004018F8 . 83C4 10 add esp, 10
004018FB . 8D8D 38EBFFFF lea ecx, dword ptr [ebp-14C8]
00401901 . 51 push ecx
00401902 . 8D95 F0FBFFFF lea edx, dword ptr [ebp-410]
00401908 . 52 push edx
00401909 . 8D4D 0C lea ecx, dword ptr [ebp+C]
0040190C . E8 DF040000 call <stringptr>
00401911 . 50 push eax
00401912 . E8 F9970000 call 0040B110 ; aes_en(in, out, key)
00401917 . 83C4 0C add esp, 0C
0040191A . 8985 30EBFFFF mov dword ptr [ebp-14D0], eax
00401920 . 83BD 30EBFFFF 00 cmp dword ptr [ebp-14D0], 0
00401927 . 74 4B je short 00401974
中断到004018F3,从堆栈找到key为:
00626F20 0F 5F 7B CD C0 66 0D 58 7C 86 D7 26 B1 C6 AA D1 _{屠f.X|喿&逼
00626F30 03 B2 12 85 C1 03 A3 51 BB C5 73 3B 3A D4 36 35 ?吜慌s;:?5
aes_en(in, out, key)
输入为 RSA的输出,所以完整表达式为
SN = AES_ENC(RSA_DEC(X))
其中SN为已知:
00626DD8 C8 E5 E2 C3 C4 39 FC 04 48 D8 0F 8B 5F 73 8C A9 儒饷??H?媉s尒
AES_KEY已知:
00626F20 0F 5F 7B CD C0 66 0D 58 7C 86 D7 26 B1 C6 AA D1 _{屠f.X|喿&逼
00626F30 03 B2 12 85 C1 03 A3 51 BB C5 73 3B 3A D4 36 35 ?吜慌s;:?5
私钥D已知:
D = 2BBE7481
计算X的程序如下:
#include "zmath.h"
int aes256_test(void)
{
int i = 0;
unsigned char key256[32] = {
0x0F, 0x5F, 0x7B, 0xCD, 0xC0, 0x66, 0x0D, 0x58, 0x7C, 0x86, 0xD7, 0x26, 0xB1, 0xC6, 0xAA, 0xD1,
0x03, 0xB2, 0x12, 0x85, 0xC1, 0x03, 0xA3, 0x51, 0xBB, 0xC5, 0x73, 0x3B, 0x3A, 0xD4, 0x36, 0x35
};
unsigned char _in[32] = {
0xC8, 0xE5, 0xE2, 0xC3, 0xC4, 0x39, 0xFC, 0x04, 0x48, 0xD8, 0x0F, 0x8B, 0x5F, 0x73, 0x8C, 0xA9
};
unsigned char _out[256];
zstate akey;
zaes_init(&akey, key256, 256, 0);
zaes_decrypt(&akey, _in, _out, 16);
printf("AES256 解密结果:\n");
for (i = 0; i < 16; i++)
printf("%02X ", _out[i]);
printf("\n");
{
void *D, *N, *M, *C;
mp_init_multi(&D, &N, &M, &C, 0);
unsigned char dd[] = { 0x2B, 0xBE, 0x74, 0x81 };
mp_read_unsigned_bin(D, dd, 4);
unsigned char nn[] = { 0xF5, 0x74, 0xFD, 0x11 };
mp_read_unsigned_bin(N, nn, 4);
unsigned char cc[8] = { 0 };
for (int i = 0; i < 8; i++)
{
mp_read_unsigned_bin(M, _out+i*2, 2); // 注意 2个字节
mp_exptmod(M, D, N, C);
mp_to_unsigned_bin(C, cc);
for (int j = 0; j < 4; j++)
printf("%02X", cc[j]);
}
mp_clear_multi(D, N, M, C, 0);
}
return 0;
}
输出为:
AES256 解密结果:
0D 48 ED 5E F7 69 E2 AB D6 8B FD 6C 76 DD 79 5D
3C4F963B039A2C377E02291E3C157AE591BCC1CA0A8F528EB2700AC021FB958D
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!