CubeMadness2-gamepwn

ctf
1.5k words

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

gp1

还是打开CE追一下值

gp2

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

gp3

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

gp4

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

gp5

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

gp6

看一下汇编,好像是这里一直在赋值.

再往上走了下看看edx的值是从哪来的

gp7

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

gp8

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


gp8.1

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


gp9

2.然后eax = 6208CECB


gp10

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

1
2
3
4
5
6
>>> print(bin((0x248f*0x6208CECB)))
0b11100000000000000000000000000000111101100101
>>> print(hex(0b111101100101))
0xf65
>>> print(hex(0b111000000000))
0xe00

gp12

4.再将rdx向右移了0x9

1
2
>>> print(hex(0xe00 >> 0x9))
0x7

gp13

5.又把rdx的值赋给了rax


gp14

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

1
2
>>> print(0x7 >> 0x1f)
0

gp15

7.这里一个把eax的值加给edx后,edx就把值交给rsi了,然后看到游戏里就是吃到了7个。


总结下这里通过1.rdx赋了个初始值,然后2.又给了rax一个0x6208CECB,他俩在3.那里rdx * rax然后高低位互相赋值,这里结束赋给rdx的值再>> 9之后基本就是我们的游戏的结果了.

那就说明他是一直从内存里写入,然后解密读取内存里的,所以我们直接改就没鸟用。

那我们知道的这个值咋来的之后就可以尝试构造一个能达成结果等于20的数值赋给对应的rdx指向的内存.


因为他最后是0xe00 >> 0x9

所以我们倒推,先弄个20 往左挪0x9

1
2
>>> print(hex(20 <<0x9))
0x2800

然后看看谁和0x6208CECB相乘的高32位可以等于0x2800

1
2
3
4
5
print(0b1010000000000011111111111111111111111111111111)
43984760078335

print(0b1010000000000000000000000000000000000000000000)
43980465111040

反正就这个之间了..跑不出来也没招了..

1
2
>>> print(43984760078335 / 0x6208CECB)
26742.611321277676
1
2
3
4
5
for i in range(10000,26742):
a= bin(i * 0x6208CECB)
if len(str(a)[2::]) == 46:
if a[0:8] == "0b101000": #<--因为0x2800 -- 0x28ff都可以
print(hex(i))

跑出来俩随便用一个..

1
2
0x6874
0x6875

这里是小端序,改的时候注意倒换一下,比如68 74 填进去要填74 68

gp16

然后就出了

gp17