初步分析

从主函数输入用户名和序列后,容易定位到.text:00401120的函数是在checkserial

一开头call了一个函数,进去分析后不难得到是使用scanf把serial当做16进制数据读取,重命名为serial2hex。

接着qmemcpy可以分析出序列号长度67byte(134位16进制),提供的序列号长度也确实是134

然后开始异或操作,异或的数据静态看不清楚,利用调试发现edi是当前函数的地址401120, 跟程序自身代码异或,异或的部分长度是697
而serial长度67,所以用了取余

接下来第二轮,看起来花里胡哨的 但是仔细化简发现,第一轮就是serial[0]^[1]^[2]^[3]...[5]接着不难发现v4就等于serial从第0位自身异或到65位

第三轮,把v4^[66]作为秘钥,逐个将0~65项异或一遍,而第66下标项则相当于把v7存储起来,这个在后续复原中至关重要(也就是,所有67个数据异或到一起作为第三轮秘钥加密前66项,而最后一项保留这个秘钥)

serial的前置工作搞定了,终于看到跟name有关的部分

又是熟悉的各个字节异或

经过计算得出一个重要的数据(我写成了name after and),它决定了怎么切分serial

一段遍历,其实就是判断经过前面处理的serial是不是跟main函数的代码指定前n位一致,n就是name after and。(为什么我知道那个变量是指向main函数呢?还是调试的呀,发现edi是4010D0)

下面有一段完全相似的处理,是判断serial的44-n到最后一位是不是跟main对应的代码一致

注意到中间空出来了一段,长度67-44=23字节这就是最后一部分:

拷贝中间的23字节,经过[[#循环移位的代码特征|循环左移位]]操作(操作的位数依旧跟main函数代码有关),跟指定的slogan比较,如果一样那么就success了!

由此不难构造出解密代码(我是利用调试工具提取的main函数和check函数代码段16进制数据,hexed.it网站导出成python代码片段,当然什么方法都可以)
本人比较懒,所以没有写一般的注册机,只写了KCTF的,数组截取的长度写死了。

循环移位的代码特征


对于八位二进制dst_after_and2
令t=(*p_main_plus1 & 7) 这是一个只有4位的二进制,取值范围0~7
左移t位
右移8-t位
两个结果或运算

这就是完成了一次左移t位的循环移位

总结

其实现在看来本题没有任何阻碍,纯粹要求分析加密算法而已。但是作为新手,还是在分析代码花了很长时间(总共应该花了四五个小时做出来吧)。对着调试器寻找相关汇编指令,找到目标地址。过程中学会了下条件断点,内存跟踪也更熟练了。很适合当前的水平。

写出解密脚本也是一个挑战,有时会犯低级错误,要通过各种途径验证自己的reverse函数写得对不对。btw,kimi直接写的rev完全不能用哈哈哈。

最新回复:
XaraMysteria 2024-08-29 22:37:05

【solved】


大家可能注意到python代码注释有涉及到一个魔改为CC的说法,这是我调试遇到的一个很奇怪的问题:所有从指针取值,第0位读出来都是CC,第1位开始就正常 比如check函数前两位 0x83 0xEC,我调试的时候看见第0次是0xCC,第1次是0xEC,后续也完全正常。非常奇怪,有没有大佬能解答一下?


Ally Switch 2024-08-30 15:42:23
XaraMysteria 大家可能注意到python代码注释有涉及到一个魔改为CC的说法,这是我调试遇到的一个很奇怪的问题:所有从指针取值,第0位读出来都是CC,第1位开始就正常 比如check函数前两位 0x83 0x ...
你下断点了。程序原本的字节被替换成0xCC了
XaraMysteria 2024-08-30 20:27:54
Ally Switch 你下断点了。程序原本的字节被替换成0xCC了
是的,我也看了作者的wp,现在明白了,谢谢您