映入眼帘的和CM1一样,也都是吃满20个给flag

还是打开CE追一下值

这里吃到第四个的时候其实就ok了

然后尝试改一下值,会发现改了没反应,或者改了也不生效一会就变回去了

猜测是有什么恢复逻辑之类的,于是给值的内存写入部分下个断点。

看了下三个地址当中的这个是主要的判断,因为每秒好像都在处理逻辑

看一下汇编,好像是这里一直在赋值.
再往上走了下看看edx的值是从哪来的

挨个下了断点简单看了下是

1.[rax+000000B8]内存指向的值赋给了rdx

1.1这里看下rdx被赋值的地址指向了一个8f 24

2.然后eax = 6208CECB

3.再imul[rdx]就是rdx指向的值和eax做了个乘法,然后将乘积的取了低位32给了la也就是rax..高位的32位给了ld也就是这里的rdx,可以看下面这个。
1 | print(bin((0x248f*0x6208CECB))) |

4.再将rdx向右移了0x9位
1 | print(hex(0xe00 >> 0x9)) |

5.又把rdx的值赋给了rax

6.再把rax或者说eax的值右移了0x1f位..因为值位数比较短,就给归零了…这里如果rdx之前算出的值太长的话,这里确实会受到影响.
1 | print(0x7 >> 0x1f) |

7.这里一个把eax的值加给edx后,edx就把值交给rsi了,然后看到游戏里就是吃到了7个。
总结下这里通过1.给rdx赋了个初始值,然后2.又给了rax一个0x6208CECB,他俩在3.那里rdx * rax然后高低位互相赋值,这里结束赋给rdx的值再>> 9之后基本就是我们的游戏的结果了.
那就说明他是一直从内存里写入,然后解密读取内存里的,所以我们直接改就没鸟用。
那我们知道的这个值咋来的之后就可以尝试构造一个能达成结果等于20的数值赋给对应的rdx指向的内存.
因为他最后是0xe00 >> 0x9
所以我们倒推,先弄个20 往左挪0x9
1 | print(hex(20 <<0x9)) |
然后看看谁和0x6208CECB相乘的高32位可以等于0x2800
1 | print(0b1010000000000011111111111111111111111111111111) |
反正就这个之间了..跑不出来也没招了..
1 | print(43984760078335 / 0x6208CECB) |
1 | for i in range(10000,26742): |
跑出来俩随便用一个..
1 | 0x6874 |
这里是小端序,改的时候注意倒换一下,比如68 74 填进去要填74 68

然后就出了
