-
-
[原创]第七题 声名远扬WP
-
2021-12-2 11:09 12883
-
程序使用了兼容模式下32位代码与64位代码的混合执行的技术。
.text:00B2D88E 6A 00 push 0 .text:00B2D890 8B 5D 10 mov ebx, [ebp+arg_8] .text:00B2D893 53 push ebx .text:00B2D894 8B 4D 0C mov ecx, [ebp+arg_4] .text:00B2D897 51 push ecx .text:00B2D898 8B 4D 08 mov ecx, [ebp+arg_0] .text:00B2D89B 51 push ecx .text:00B2D89C 6A 00 push 0 .text:00B2D89E 8D 4D EC lea ecx, [ebp+var_14] .text:00B2D8A1 51 push ecx .text:00B2D8A2 FF 5D F4 call fword ptr [ebp+var_C] //进入IA-32e模式
当执行到.text:00B2D8A2 时,栈内存ebp+var_C如下:
Stack[000057AC]:012FEDB4 dd offset byte_B256F0 //远调用目标绝对地址 Stack[000057AC]:012FEDB8 dd 33h //远调用CS段选择子
当前CS段选择子为23h, 调用后的CS段选择子0x33(64位用户代码段).
0xB256F0所指的代码是64位代码,将其导出为二进制文件,使用IDA将其作为64位代码进行分析:
seg000:0000000000000000 sub_0 proc far seg000:0000000000000000 seg000:0000000000000000 arg_0 = qword ptr 10h seg000:0000000000000000 arg_8 = qword ptr 18h seg000:0000000000000000 arg_10 = qword ptr 20h seg000:0000000000000000 arg_18 = qword ptr 28h seg000:0000000000000000 arg_20 = qword ptr 30h seg000:0000000000000000 arg_28 = qword ptr 38h seg000:0000000000000000 seg000:0000000000000000 mov rdi, [rsp+arg_0] seg000:0000000000000005 mov rsi, [rsp+arg_8] seg000:000000000000000A mov r11, 1 seg000:0000000000000011 lea r10, [rsp+arg_10] seg000:0000000000000016 cmp rsi, 1 seg000:000000000000001A jb short loc_50 seg000:000000000000001C mov rcx, [rsp+arg_10] seg000:0000000000000021 cmp rsi, 2 seg000:0000000000000025 jb short loc_50 seg000:0000000000000027 mov rdx, [rsp+arg_18] seg000:000000000000002C cmp rsi, 3 seg000:0000000000000030 jb short loc_50 seg000:0000000000000032 mov r8, [rsp+arg_20] seg000:0000000000000037 cmp rsi, 4 seg000:000000000000003B jb short loc_50 seg000:000000000000003D mov r9, [rsp+arg_28] seg000:0000000000000042 mov rax, rsi seg000:0000000000000045 shl rax, 3 seg000:0000000000000049 add r10, rax seg000:000000000000004C sub r10, 8 seg000:0000000000000050 seg000:0000000000000050 loc_50: ; CODE XREF: sub_0+1A↑j seg000:0000000000000050 ; sub_0+25↑j ... seg000:0000000000000050 cmp rsi, r11 seg000:0000000000000053 jb short loc_62 seg000:0000000000000055 mov rax, [r10] seg000:0000000000000058 push rax seg000:0000000000000059 sub r10, 8 seg000:000000000000005D inc r11 seg000:0000000000000060 jmp short loc_50 seg000:0000000000000062 ; --------------------------------------------------------------------------- seg000:0000000000000062 seg000:0000000000000062 loc_62: ; CODE XREF: sub_0+53↑j seg000:0000000000000062 call rdi //实际验证函数 seg000:0000000000000064 shl rsi, 3 seg000:0000000000000068 add rsp, rsi seg000:000000000000006B mov rbx, [rsp+8] seg000:0000000000000070 mov [rbx], rax seg000:0000000000000073 retf //返回兼容模式
通过分析堆栈,可知验证函数为0xB255AC(同样为64位代码),导出分析:
__int64 __fastcall sub_B255AC(char *seri, __int64 ) { //... //初始化 v27 = 44; v4 = 0; *(__m128i *)v28 = _mm_load_si128((const __m128i *)0xB25408); *(__m128i *)&v28[32] = _mm_load_si128((const __m128i *)0xB253F8); *(__m128i *)&v28[16] = _mm_load_si128((const __m128i *)0xB25418); //序列号生成 do { v5 = v4 - 52; v6 = v4++; v28[v6] ^= v5; } while ( v4 < v27 ); v28[v27] = 0; //序列号输入检查 v7 = 0; chr = *seri; if ( *seri ) { v9 = seri; do { if ( chr != v9[v28 - seri] ) break; ++v9; ++v7; chr = *v9; } while ( *v9 ); } v10 = v7; i = 0; v24 = -48; if ( seri[v10] == v28[v10] ) { //验证成功 } else { //验证失败 } return 0i64; }
算法较简单,静态分析即可,若想进行动态调试,可配置bochs调试(注意依赖数据也须导入到数据库),配置如下:
序列号算法:
//.idc auto bytes = get_bytes(0xB25408, 0x10, 1); bytes = bytes + get_bytes(0xB25418, 0x10, 1); bytes = bytes + get_bytes(0xB253F8, 0x10, 1); auto i = 0; for(i = 0; i<44; i++){ auto v = ord(bytes[i]) ^ ((i - 52) & 0xff); msg("%02X ", (v & 0xff)); bytes[i] = v; } bytes[i] = '\x00'; msg("\n%s\n", bytes); //GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR!!
输入的序列号需要进行类似base64的编码,编码函数位于.text:00B2E530,因此需要做对应的解码操作:
//.idc auto seri = "GYldGg-iIoJlPX9hPXpjPqfdEY21B01TBTzeGqfKNR"; auto sseri = ""; auto chr = 0; auto bits = 0; auto result = 0; auto tree = ECX; //调试拿到tree地址 auto i = 0; auto j = 0; for(i = 0; i < strlen(seri); i++){ auto found = -1; for(j = 0; j <= 0x40; j++){ auto c = j; auto sc = bsearch(tree, &c); //APPCALL .text:00B2E970 ; void *__thiscall bsearch(void *bin_tree, char *chr) //msg("%02X ", byte(sc)); if(ord(seri[i]) == byte(sc)){ found = j; break; } } if(found == -1){ msg("\n###EXCEPTION %d %d %X\n", i, strlen(seri), ord(seri[i])); break; } else{ bits = bits + 6; chr = chr << 6; chr = chr | found; while(bits >= 8){ auto v = chr >> (bits - 8); chr = chr - (v << (bits - 8)); bits = bits -8; msg("%02X ", (v & 0xFF)); } } } msg("\nDONE bits = %d, chr = %02X\n", bits, chr); /* 66 6C 61 67 7B 32 30 32 31 2D 31 30 2D 30 34 2D 79 61 6E 67 79 61 6E 67 62 75 64 65 79 69 7D DONE bits = 4, chr = 00 */
解码得到序列号为:
flag{2021-10-04-yangyangbudeyi}
赞赏
他的文章
[原创]驱动保护-EAC内核调试检测分析
19343
[原创]第七题 声名远扬WP
12884
[原创]第二题 迷失丛林WP
10503
[原创]签到题 身在何处WP
1625
[原创]VMProtect分析(三)
20152