@zbnysjwsnd8 趁我陪女票先发啦可恶~
CheckCode的分析和解法提供另一种思路
查壳显示无运行显示Waring后直接结束,估计有反调试
于是拖入IDA检索该字符串,找到这里的调用:
稍微查了一下,TlsCallback是线程局部存储回调函数,简单来说就是在创建线程的时候调用这个函数
最简单的方法就是在OD中断下来,然后直接把它NOP掉
搞定以后重新运行,发现显示了几个字符串以后又挂了
说明还有别的地方调用反调呗╮(╯_╰)╭
查了一下WARNING字符串只有TlsCallback里调用了,那干脆把它Hook住好了:
这样就可以正常运行了,继续往下走,找到接收输入的地方,很明显这里就是关键:
0x00bd1316函数对User进行Check,IDA反编译一下比较方便:
逆序,然后通过一个乱七八糟的东西【对下标计算】,最后与输入值异或,然后比较
所以逆算法直接算出这个东西然后与比较值异或,再逆序即可:
[Python] 纯文本查看 复制代码 d = [0xA4, 0xA9, 170, 190, 188, 185, 179, 169, 190, 216, 190]
d1 = []
for j in range(11):
d1.append(chr(((((j ^ 0x76) - 52) ^ 0x80) + 43) ^ d[j]))
flag = "".join(d1)
print(flag[::-1])
得到Name:“M.KATSURAGI”
然后我把它提交了几十遍,没用(╯‵□′)╯︵┻━┻
刚开始上来就用IDA反编译main函数报错了:
一般在加壳、或是对解密代码段的时候会出现这种错误,堆栈识别错误
但是已经做到这里都没有出现对代码操作的地方,没道理啊
于是去0x413238看看:
记得勾上Option-general-stack pointer,查看堆栈偏移:
问题出在mov esp, ebp上了啊……ALT+K更改试试
嘿,还真行了
这样一眼就能看到CheckName之后还有Code的检查了
往下分析,跟着字符串走:
可以看到,先在sub_41114f中对input进行了第一次变换,然后分别用它得到了3个字符串,最后校验这3个部分依次查看:
变换1很简单,依次异或0x76即可后面3个变换其实思路一样,以变换2为例:
乍一看有点懵,但仔细分析就能看出端倪
&和|操作一般用于二进制位中的处理,“和”操作用于取出某些位,“或”操作用于合并拼接值
对这些敏感的话,再查一下关键的0xAA的二进制:
也就是说,实际上这个操作就是把每个数异或0xad后再将奇偶位交换
分析出它的意义,逆变换就很简单了:先将奇偶位交换,再异或0xad即可
变换3、4只是异或值和取的位不同,思路都是相同的,它们分别操作14-21位和21-28位
例如变换3的0xcc是11001100,再分别左移和右移2位
逆变换同样交换即可
最后与0x41b0dc进行比较,于是把它Dump下来,然后先分段进行变换2、3、4的逆,再进行变换1的逆即可:
[Python] 纯文本查看 复制代码
d2 = [30, 21, 2, 16, 13, 72, 72, 111, 221, 221, 72, 100, 99, 215, 46, 44, 254, 106, 109, 42, 242, 111, 154, 77, 139, 75, 154, 170, 65, 66, 66, 66, 19, 20, 11]
for i in range(7, 14):
p = (d2[i] & 0xaa)>>1
q = (d2[i]<<1) & 0xaa
d2[i] = (p|q)^0xad
for i in range(14, 21):
p = (d2[i] & 0xcc)>>2
q = (d2[i]<<2) & 0xcc
d2[i] = (p|q)^0xbe
for i in range(21, 28):
p = (d2[i] & 0xf0)>>4
q = (d2[i]<<4) & 0xf0
d2[i] = (p|q)^0xef
for i in d2:
print(chr(i^0x76), end='')
得到flag
这个算法还是很有意思的,不过到处都是反调有点麻烦~
嗯…………
我都是靠IDA反编译出来的算法来逆,管反调干啥呢(╯‵□′)╯︵┻━┻
附件在dalaohttps://www.52pojie.cn/thread-661434-1-1.html这里有,我就不再上传啦
(PS:注册码最后6位不同的话可能是由于官方每隔若干时间更换一次源程序和flag,防止地下交易嘛~) |