看雪CTF2016CrackMe第一题分析
看雪CTF刷题系列,PEDIY-CTF2016-CM1。
前言
能力不足,基本上是对着前辈的Writeup逐步跟下来的,记录一些心得。
知识点
- OD、IDA基础知识
- Windows反调试
详细步骤
发现反调试
- OD加载程序,单步执行到 0x1C2BC9 call 0x1CC111; call _initterm 挂掉了,跟进 _initerm 函数执行到 0x1CC151 call dword ptr [ebp-8]; call 0x1C1000 第二次挂掉,继续跟进在 0x1C000 跳转到 0x1C1340 处,在 sub_1C1340 中执行到 0x1C1530 会有一个判断直接退出程序,这里我们直接NOP掉,之后来到0x1C2C44 call 0x1C1560进入WinMain函数。进入WinMain之前的函数栈 start->scrt_common_main_seh->WinMain,在 scrt_common_main_seh 中调用 _initterm 。
进入WinMain之后,界面程序起来之前,会遇到超时检测。通过交叉引用查看clock函数,能发现三处超时检测,如图:
我们直接NOP掉跳转指令,这样就能让CM在OD中跑起来了。
给出程序调试过程中的反调试patch:
分析注册过程
进入WinMain函数以后,这里有一个技巧对GetWindowTextW函数下断,执行到返回 0x1C232B ,落在 sub_1C2120 函数中,ida分析 sub_1C2120 是窗口处理消息的程序,只有当消息值为 0x40B 时才注册成功。继续运行之后, 程序会创建新线程进入 sub_1C20E0 ,继而进入 sub_1C1CB0 ,可以看出 sub_1C1CB0 就是注册码检测逻辑的主函数。
第一次进入 sub_1C1CB0 ,调用了 sub_1C1C00 和 sub_1C2A50 ,分别要求注册码含有 ‘b’ 和 ‘p’ ,否则返回消息0x40F注册失败。
当满足上面条件后,会第二次进入 sub_1C1CB0 函数,在函数中会判断字符长度是否是7,不满足条件会发送消息0x40E或0x40D导致注册失败,所以 注册码长度是7 。
当满足条件后,会进入 sub_1C1A60 ,对注册码进行异或加密,之后会进入 sub_1C1870 函数,在 sub_1C1870 对加密的注册码进行了异或解密,将注册码小写转化成大写之后,进行了字符集检测。
并且要求从第三位开始,解密出来的注册码序列是 15PB ,所以注册码的格式是 ??15PB? 。
当解密的注册码满足 ??15PB? 格式后进入 sub_1C1740 ,sub_1C1740要求前两位之和是0x63,所以前两位肯定是 ‘1’ 和 ‘2’,第七位必须是 ‘8’ 。综上,满足条件的注册码有 1215pb8 。
分析过程中关键断点:
总结
- 第一步是过掉反调试,让CM能跑起来。
- 只有一条道路是通往CM成功的,不断的逆向尝试。