0x0 初探先用PEID查看一下CM的信息从图中可以发现,程序使用Debug的编译方式编译且有一个TLS回调函数。因为程序有ASLR,不方便分析,因此我用FFI去掉后再继续分析。1x0 分析TLS回调函数OD载入,断在TLS入口处。一共有四个函数,其中前两个我们需要关注一下。因为这两个函数是反调试的函数。1x1 分析函数 0041141ACM先创建一个进程快照然后就开始枚举进程,取出进程名,如果进程名字符合如下进程名中的其中一个,就直接报错退出。
ollyice.exeollydbg.exepeid.exeida.exeidaq.exe
对应的检测代码如下:
1x2 分析函数 00411186这段函数其实就是IsDebuggerPresent。检测了PEB的BeingDebugged,若BeingDebugged为0则未被调试,否则被调试。函数代码如下:1x3 一次性全部拆解这两个检测函数都位于TLS回调函数内,因此删掉即可。这样系统就不会去执行TLS回调函数了,而是直接执行入口点处的代码了。2x0 分析第一个输入OD来到main函数00412E20处,单步调试一阵发现第一个算法函数 00411316因为这个函数的代码很长,所以使用IDA来分析。IDA来到00411316处,使用F5插件查看反编译好后的C代码。首先将注册码的顺序颠倒(123456789 -> 987654321)然后将循环次数作为密匙,加密颠倒后的Key最后和一串密文比较,若全部相等则通过第一个Key的验证。v8处的数据如下:计算注册码的办法很简单,写一个逆运算即可。代码如下:运行以后得到结果:M.KATSURAGI3x0 分析第二个输入第二个输入就有点复杂了,其中还夹杂着反调试(ntdll!NtQueryInformationProcess查询DebugPort)。x86用StrongOD插件,x64用xjun师傅的SharpOD插件都可以绕过(我是Windows7 x64)首先程序判断输入的Key是否是0x23个字节,如果不是则失败。构造一个key,使大小为0x23即可通过。我构造的是0123456789ABCDEFGHIJKLMNOPQRSTUVWXY继续分析,来到第一个计算的函数(一共有四个),我先将这个计算的函数和将要出现的计算的函数分别标记,到最后一起分析。第一个计算的函数我命名为First。加密以后,CM做了一些操作以后(包括调试器的检测)来到第二个计算的函数,我命名为Second。然后执行第三个计算的函数,我命名为Third然后执行第四个计算的函数,我命名为Fourth然后将First计算的数据的第八个字节开始用Second计算的七个字节替换,第十五个字节开始用Third计算的七个字节替换,第二十二个字节开始用Fourth的计算的七个字节替换。最后和内置好的一串数据比较,如果相等就成功。其中,内置好的正确数据如下:3x1 四个计算函数之First的分析First函数比较简单,将Key的每个字节和0x76异或。3x2 四个计算函数之Second的分析代码如下:3x3 四个计算函数之Third的分析这个和Second进行的运算差不多。代码如下:3x4 四个计算函数之Fourth的分析代码如下:3x5 计算第二个注册码这个注册码一共经历了四次变换(First Second Third Fourth)其中,First运算可逆,Second Third Fourth都不是可逆的函数。观察一下计算后的数据,容易发现注册码被分成了如下的五个部分:其中有高亮的(第二个到第四个)都是被替换后的,而没有高亮的(第一个和最后一个)都是不被替换的,因此没有高亮的部分可以直接用First运算来还原。而有高亮的部分我没有找到好的办法去还原,只有枚举了。总体的计算思路如下:1.先不考虑没有高亮的部分(第一个和最后一个),枚举第二个,用Second运算来枚举,尝试一个字节一个字节枚举,考虑到注册码都是可显示字符,scanf又有遇到空格截断的特性,因此从0x21开始枚举。若Second返回的的数据是正确的,则开始第二个字节的枚举。2.枚举第三个,用Third运算来枚举,尝试一个字节一个字节枚举,若Third返回的的数据是正确的,则开始第二个字节的枚举。3.枚举第四个,用Fourth运算来枚举,尝试一个字节一个字节枚举,若Fourth返回的的数据是正确的,则开始第二个字节的枚举。4.这步中的数据应该是正确的Key经过First运算后的数据了,因为First运算是xor运算,故将这部分的数据再用First运算一次即可得到Key。计算代码如下:
运行以后得到结果:hctf{>>D55_CH0CK3R_B0o0M!-037444eb}4x0 最后一个输入这个就很简单了,问你输入Y或者N,若输入Y则成功(不区分大小写),否则失败。4x1 完整的计算代码将上述代码写到一起,然后再加上输出最后一个注册码的代码即可。代码如下:
运行以后得到完整的Key:用原版CM注册,得到结果如下:全文完。
附件中的RuntimeLibrary.zip是CM的运行库,作者没有打包在CM中,如果打开CM提示缺少DLL的话就下载RuntimeLibrary.zip中的文件解压到CM目录下
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
holing 感觉作为签到题有点难了。。。做了几个小时。。。可能是我菜吧(逃