-
-
[原创]KCTF 2019 Q2 Writeup
-
发表于: 2019-6-27 06:56 5941
-
1、通过MessageBox提示字符串可以定位到关键代码,需要注意的是真正的校验代码是通过 0x00401F8A 处的指令 rep movsd 拷贝到0x4010E0的
.text:00401EEB 8D 85 F0 FC FF FF lea eax, [ebp+String] .text:00401EF1 50 push eax ; lpString .text:00401EF2 68 E8 03 00 00 push 3E8h ; nIDDlgItem .text:00401EF7 8B CE mov ecx, esi ; this .text:00401EF9 E8 17 75 00 00 call ?GetDlgItemTextW@CWnd@@QBEHHPA_WH@Z ; CWnd::GetDlgItemTextW(int,wchar_t *,int) .text:00401EFE 8D 85 F0 FC FF FF lea eax, [ebp+String] .text:00401F04 8D 50 02 lea edx, [eax+2] .text:00401F07 .text:00401F07 loc_401F07: ; CODE XREF: onButtonCliked+70j .text:00401F07 66 8B 08 mov cx, [eax] .text:00401F0A 83 C0 02 add eax, 2 .text:00401F0D 66 85 C9 test cx, cx .text:00401F10 75 F5 jnz short loc_401F07 .text:00401F12 2B C2 sub eax, edx .text:00401F14 D1 F8 sar eax, 1 .text:00401F16 83 F8 10 cmp eax, 10h .text:00401F19 0F 85 BB 00 00 00 jnz loc_401FDA ; 长度要等于0x10 .text:00401F1F 33 C0 xor eax, eax .text:00401F21 .text:00401F21 loc_401F21: ; CODE XREF: onButtonCliked+A6j .text:00401F21 B9 00 FF 00 00 mov ecx, 0FF00h .text:00401F26 66 85 8C 45 F0 FC FF FF test [ebp+eax*2+String], cx .text:00401F2E 0F 85 A6 00 00 00 jnz loc_401FDA .text:00401F34 8A 94 45 F0 FC FF FF mov dl, byte ptr [ebp+eax*2+String] .text:00401F3B 88 94 05 F0 FE FF FF mov [ebp+eax+var_110], dl .text:00401F42 40 inc eax .text:00401F43 83 F8 10 cmp eax, 10h .text:00401F46 7C D9 jl short loc_401F21 .text:00401F48 8B 1D 10 D2 51 00 mov ebx, ds:VirtualProtect .text:00401F4E 8D 45 FC lea eax, [ebp+flOldProtect] .text:00401F51 50 push eax ; lpflOldProtect .text:00401F52 6A 40 push 40h ; flNewProtect .text:00401F54 68 17 0D 00 00 push 0D17h ; dwSize .text:00401F59 68 E0 10 40 00 push offset sub_4010E0 ; lpAddress .text:00401F5E C7 45 F0 40 00 00 00 mov [ebp+var_10], 40h .text:00401F65 C7 45 FC 00 00 00 00 mov [ebp+flOldProtect], 0 .text:00401F6C FF D3 call ebx ; VirtualProtect .text:00401F6E FF 15 08 D4 51 00 call ds:GetLastError .text:00401F74 85 C0 test eax, eax .text:00401F76 75 62 jnz short loc_401FDA .text:00401F78 8B 55 FC mov edx, [ebp+flOldProtect] .text:00401F7B B9 CC 00 00 00 mov ecx, 0CCh .text:00401F80 BE B8 47 56 00 mov esi, offset byte_5647B8 .text:00401F85 BF E0 10 40 00 mov edi, offset sub_4010E0 .text:00401F8A F3 A5 rep movsd 拷贝真正的校验代码到0x4010E0 .text:00401F8C 8D 4D F0 lea ecx, [ebp+var_10] .text:00401F8F 51 push ecx ; lpflOldProtect .text:00401F90 52 push edx ; flNewProtect .text:00401F91 68 17 0D 00 00 push 0D17h ; dwSize .text:00401F96 68 E0 10 40 00 push offset sub_4010E0 ; lpAddress .text:00401F9B FF D3 call ebx ; VirtualProtect .text:00401F9D FF 15 08 D4 51 00 call ds:GetLastError .text:00401FA3 85 C0 test eax, eax .text:00401FA5 75 30 jnz short loc_401FD7 .text:00401FA7 89 45 F8 mov [ebp+var_8], eax .text:00401FAA 8D 85 F0 FE FF FF lea eax, [ebp+var_110] .text:00401FB0 50 push eax .text:00401FB1 E8 2A F1 FF FF call sub_4010E0 进入校验 .text:00401FB6 89 45 F8 mov [ebp+var_8], eax .text:00401FB9 83 7D F8 01 cmp [ebp+var_8], 1 .text:00401FBD 75 18 jnz short loc_401FD7 .text:00401FBF 8B 4D F4 mov ecx, [ebp+var_C] ; this .text:00401FC2 6A 00 push 0 ; unsigned int .text:00401FC4 6A 00 push 0 ; lpCaption .text:00401FC6 68 10 57 54 00 push offset Text ; "Congratulations! You are right!" .text:00401FCB E8 55 92 00 00 call ?MessageBoxW@CWnd@@QAEHPB_W0I@Z ; CWnd::MessageBoxW(wchar_t const *,wchar_t const *,uint) .text:00401FD0 5F pop edi
.text:00401EEB 8D 85 F0 FC FF FF lea eax, [ebp+String] .text:00401EF1 50 push eax ; lpString .text:00401EF2 68 E8 03 00 00 push 3E8h ; nIDDlgItem .text:00401EF7 8B CE mov ecx, esi ; this .text:00401EF9 E8 17 75 00 00 call ?GetDlgItemTextW@CWnd@@QBEHHPA_WH@Z ; CWnd::GetDlgItemTextW(int,wchar_t *,int) .text:00401EFE 8D 85 F0 FC FF FF lea eax, [ebp+String] .text:00401F04 8D 50 02 lea edx, [eax+2] .text:00401F07 .text:00401F07 loc_401F07: ; CODE XREF: onButtonCliked+70j .text:00401F07 66 8B 08 mov cx, [eax] .text:00401F0A 83 C0 02 add eax, 2 .text:00401F0D 66 85 C9 test cx, cx .text:00401F10 75 F5 jnz short loc_401F07 .text:00401F12 2B C2 sub eax, edx .text:00401F14 D1 F8 sar eax, 1 .text:00401F16 83 F8 10 cmp eax, 10h .text:00401F19 0F 85 BB 00 00 00 jnz loc_401FDA ; 长度要等于0x10 .text:00401F1F 33 C0 xor eax, eax .text:00401F21 .text:00401F21 loc_401F21: ; CODE XREF: onButtonCliked+A6j .text:00401F21 B9 00 FF 00 00 mov ecx, 0FF00h .text:00401F26 66 85 8C 45 F0 FC FF FF test [ebp+eax*2+String], cx .text:00401F2E 0F 85 A6 00 00 00 jnz loc_401FDA .text:00401F34 8A 94 45 F0 FC FF FF mov dl, byte ptr [ebp+eax*2+String] .text:00401F3B 88 94 05 F0 FE FF FF mov [ebp+eax+var_110], dl .text:00401F42 40 inc eax .text:00401F43 83 F8 10 cmp eax, 10h .text:00401F46 7C D9 jl short loc_401F21 .text:00401F48 8B 1D 10 D2 51 00 mov ebx, ds:VirtualProtect .text:00401F4E 8D 45 FC lea eax, [ebp+flOldProtect] .text:00401F51 50 push eax ; lpflOldProtect .text:00401F52 6A 40 push 40h ; flNewProtect .text:00401F54 68 17 0D 00 00 push 0D17h ; dwSize .text:00401F59 68 E0 10 40 00 push offset sub_4010E0 ; lpAddress .text:00401F5E C7 45 F0 40 00 00 00 mov [ebp+var_10], 40h .text:00401F65 C7 45 FC 00 00 00 00 mov [ebp+flOldProtect], 0 .text:00401F6C FF D3 call ebx ; VirtualProtect .text:00401F6E FF 15 08 D4 51 00 call ds:GetLastError .text:00401F74 85 C0 test eax, eax .text:00401F76 75 62 jnz short loc_401FDA .text:00401F78 8B 55 FC mov edx, [ebp+flOldProtect] .text:00401F7B B9 CC 00 00 00 mov ecx, 0CCh .text:00401F80 BE B8 47 56 00 mov esi, offset byte_5647B8 .text:00401F85 BF E0 10 40 00 mov edi, offset sub_4010E0 .text:00401F8A F3 A5 rep movsd 拷贝真正的校验代码到0x4010E0 .text:00401F8C 8D 4D F0 lea ecx, [ebp+var_10] .text:00401F8F 51 push ecx ; lpflOldProtect .text:00401F90 52 push edx ; flNewProtect .text:00401F91 68 17 0D 00 00 push 0D17h ; dwSize .text:00401F96 68 E0 10 40 00 push offset sub_4010E0 ; lpAddress .text:00401F9B FF D3 call ebx ; VirtualProtect .text:00401F9D FF 15 08 D4 51 00 call ds:GetLastError .text:00401FA3 85 C0 test eax, eax .text:00401FA5 75 30 jnz short loc_401FD7 .text:00401FA7 89 45 F8 mov [ebp+var_8], eax .text:00401FAA 8D 85 F0 FE FF FF lea eax, [ebp+var_110] .text:00401FB0 50 push eax .text:00401FB1 E8 2A F1 FF FF call sub_4010E0 进入校验 .text:00401FB6 89 45 F8 mov [ebp+var_8], eax .text:00401FB9 83 7D F8 01 cmp [ebp+var_8], 1 .text:00401FBD 75 18 jnz short loc_401FD7 .text:00401FBF 8B 4D F4 mov ecx, [ebp+var_C] ; this .text:00401FC2 6A 00 push 0 ; unsigned int .text:00401FC4 6A 00 push 0 ; lpCaption .text:00401FC6 68 10 57 54 00 push offset Text ; "Congratulations! You are right!" .text:00401FCB E8 55 92 00 00 call ?MessageBoxW@CWnd@@QAEHPB_W0I@Z ; CWnd::MessageBoxW(wchar_t const *,wchar_t const *,uint) .text:00401FD0 5F pop edi
2、校验代码还原
1)、对16字节的序列号进行异或运算
char key[16] = { 0x16,0x96,0x8C,0xE3,0x81,0x98,0x6E,0x64,0x84,0x08,0xDC,0x81,0xBE,0x4D,0x48,0x4F }; char* xorSerial(char serial[16]) { char *resultSerial = new char[16]; for (int i = 0; i < 8; i++) { resultSerial[i] = key[i] ^ serial[i]; resultSerial[i + 8] = key[i + 8] ^ serial[i + 8]; } return resultSerial; }
2)、对异或后的结果进行检查:第7和第15字节不能为0,且第7字节的高4位必须为0
bool check(char *serial) { if (serial[7] == 0 || serial[15] == 0) { return false; } if (serial[7] & 0xF0) { return false; } return true; }
3)、把序列号拆成两段,前8个字节为第一段设为x,后8个字节为第二段设为y;最后可得方程:x^2 - 7y^2 = 8
不过最后不会解这个方程
char key[16] = { 0x16,0x96,0x8C,0xE3,0x81,0x98,0x6E,0x64,0x84,0x08,0xDC,0x81,0xBE,0x4D,0x48,0x4F }; char* xorSerial(char serial[16]) { char *resultSerial = new char[16]; for (int i = 0; i < 8; i++) { resultSerial[i] = key[i] ^ serial[i]; resultSerial[i + 8] = key[i + 8] ^ serial[i + 8]; } return resultSerial; }
2)、对异或后的结果进行检查:第7和第15字节不能为0,且第7字节的高4位必须为0
bool check(char *serial) { if (serial[7] == 0 || serial[15] == 0) { return false; } if (serial[7] & 0xF0) { return false; } return true; }
bool check(char *serial) { if (serial[7] == 0 || serial[15] == 0) { return false; } if (serial[7] & 0xF0) { return false; } return true; }
3)、把序列号拆成两段,前8个字节为第一段设为x,后8个字节为第二段设为y;最后可得方程:x^2 - 7y^2 = 8
不过最后不会解这个方程
1、随便输入一个字符串提示:“Please Try Again”,通过字符串搜索找到关键代码
.text:00401622 ; int __cdecl main(int argc, char **argv) .text:00401622 public _main .text:00401622 _main proc near ; CODE XREF: ___mingw_CRTStartup+F8p .text:00401622 .text:00401622 argc = dword ptr 8 .text:00401622 argv = dword ptr 0Ch .text:00401622 .text:00401622 push ebp .text:00401623 mov ebp, esp .text:00401625 and esp, 0FFFFFFF0h .text:00401628 sub esp, 50h .text:0040162B call ___main .text:00401630 mov dword ptr [esp], offset aPleaseEnterSer ; "please enter Serial:" .text:00401637 call _printf .text:0040163C lea eax, [esp+11h] .text:00401640 mov [esp+4], eax .text:00401644 mov dword ptr [esp], offset aS ; " %s" .text:0040164B call _scanf 读取输入的字符串 .text:00401650 lea eax, [esp+11h] .text:00401654 mov [esp], eax ; char * .text:00401657 call _strlen .text:0040165C cmp eax, 31h .text:0040165F jbe short loc_40166D .text:00401661 mov dword ptr [esp], offset aError ; "error" 字符串长度大于0x31,则错误 .text:00401668 call _puts .text:0040166D .text:0040166D loc_40166D: ; CODE XREF: _main+3Dj .text:0040166D mov dword ptr [esp+4], 400h ; size_t .text:00401675 mov dword ptr [esp], 1 ; size_t .text:0040167C call _calloc .text:00401681 mov [esp+4Ch], eax .text:00401685 lea eax, [esp+11h] .text:00401689 mov [esp], eax ; char * .text:0040168C call _strlen .text:00401691 mov [esp+8], eax ; binlength .text:00401695 mov eax, [esp+4Ch] .text:00401699 mov [esp+4], eax ; base64 .text:0040169D lea eax, [esp+11h] .text:004016A1 mov [esp], eax ; bindata .text:004016A4 call _base64_encode 字符串进行base64编码 .text:004016A9 mov dword ptr [esp+48h], offset aNgvH1f4s32pHkq ; "!NGV%,$h1f4S3%2P(hkQ94==" .text:004016B1 mov eax, [esp+4Ch] .text:004016B5 mov [esp+4], eax ; char * .text:004016B9 mov eax, [esp+48h] .text:004016BD mov [esp], eax ; char * .text:004016C0 call _strcmp 编码后的base字符串与!NGV%,$h1f4S3%2P(hkQ94==比较,相等则成功 .text:004016C5 test eax, eax .text:004016C7 jnz short loc_4016D7 .text:004016C9 mov dword ptr [esp], offset aSuccess ; "Success" .text:004016D0 call _puts .text:004016D5 jmp short loc_4016E3 .text:004016D7 ; --------------------------------------------------------------------------- .text:004016D7 .text:004016D7 loc_4016D7: ; CODE XREF: _main+A5j .text:004016D7 mov dword ptr [esp], offset aPleaseTryAgain ; "Please Try Again" .text:004016DE call _puts .text:004016E3 .text:004016E3 loc_4016E3: ; CODE XREF: _main+B3j .text:004016E3 mov eax, [esp+4Ch] .text:004016E7 mov [esp], eax ; void * .text:004016EA call _free .text:004016EF mov dword ptr [esp], offset aPause ; "pause" .text:004016F6 call _system .text:004016FB mov eax, 0 .text:00401700 leave .text:00401701 retn
2、还原base64编码代码,编码方法
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-6-28 11:25
被kanxue编辑
,原因:
赞赏
他的文章
看原图
赞赏
雪币:
留言: