CM分析-腾讯面试
一、反调试
1、分析
程序启动时会对Zw函数进行拷贝到自身内存中,并将内存加密。实现过掉常规API检测。
然后对BeginDebug和ForceFlags标志位进行检测,如果根据是否进行调试来设置自定义值。
执行到MFC入口后会首先判断Wow64Transition是否被hook。
然后对PEB->ProcessHeap->Flags、PEB->ProcessHeap->ForceFlag、PEB->BeginDebug、PEB->NtGlobalFlag多个标志位进行检查是否存在调试。
除此之外,程序会通过解密自拷贝的Zw函数来进行反调试。
- 通过设置ThreadInformation为
ThreadHideFromDebugger,将调试器分离实现反调试。
- 通过查询调试对象来判断是否进行调试。
- 调试时默认会有一个调试对象,程序尝试创建一个调试对象后获取,如果获取不到则表明处于调试状态。
- 通过传递非法指针地址引发0xC0000005 异常,如果执行后返回的异常码不正确则表明调试器接管了异常处理,即存在调试。
- 常规API检测反调试。
- 查询系统信息
- 引发异常检测调试
其中,反调试检测大多在窗口消息中。
包括文字的渲染。
2、反反调试
2.1、Patch
通过nop 反调试函数方式或者修改返回值的方式的patch实现过掉反调试。
2.2、Hook Zw
2.2.1 EAT
在程序启动初期,快速将ntdll.dll的导出函数进行替换后自写分发过滤。
2.2.2 替换wow64transition
通过ce查看32位下的syscall。
可以将mov edx,xxxxxx的硬编码20 8f 87 77 修改为自己的函数地址,然后通过eax的值判断函数后进行自定义处理。
由于CM会检测wow64transition头部是否为0xE9(默认 FF 25 xxxxxxx)
因此自定义函数的头字节不能为0xe9。但在实现后测试的环节中发现部分Zw函数调用时崩溃,原因也暂未查找,因此该方法只作为一个额外的思路。
二、注册机
1、算法分析
Win32获取EditBox函数大多是GetWindowText,但是在ida中交叉引用发现并没有什么有价值的东西。但是在导入表看到OutputDebugStringA,然后尝试打开了DbgView看看能不能捕获到内容。
发现当用户名和注册码输入长度较长时,点击注册有输出,但该输出并非正确的注册码。猜测上层有对注册逻辑处理,交叉引用后发现上层代码无法进行伪代码生成。
简单分析后发现该段代码存在异常处理和花指令。
在异常地址0x401B86和异常函数0x0415890下断点后Shift+F9跳转到自定义异常跟踪分析后,发现该处最终的跳转结果为0x401BA1。
对代码进行修复后且nop无效代码后,ida已经可以进行伪代码生成。
注册算法为从地址为0x401BA9处循环执行0x960次,每次以四字节大小读取地址数据后与初始值的Key(0x19820714),进行异或运算得到最后一个校验值。然后生成三个固定常量表。
紧接着获取用户名和注册码对应EditBox的内容。
其中会判断用户名长度是否为8,注册码长度是否为24。
最后将用户名和上边生成的三个表、Key进行计算注册码。
计算完毕后会执行函数OutputDebugStringA将计算出来的注册码输出,但输出的方式为将计算出的注册码的头和尾字符各上升一个字符,及”0”->”1”。
2、注册机实现
1 | |
DbgView捕获到的内容
将头尾各降一个字符得到的内容与注册机一致。
Uk4Xm30PtWj6Vl13LtRk2Xp1 -> Tk4Xm30PtWj6Vl13LtRk2Xp0