二木 王者

PMKF

将题目拖入ida中进行分析,进入此函数中进行分析.

Untitled

Untitled

Untitled

其中我们需要知道这个函数

readfile:从指定的文件或输入/输出 (I/O) 设备读取数据。 如果设备支持,则读取发生在文件指针指定的位置。

这里我们并没有发现到底是哪里读取了文件,我们动态调试,在push处下断点,发现断点不能断下,我们去找找,我们会发现这个.函数,在内存中读取一个名为,nk.ctf的文件,这样我们创建一个文件即可.

发现能够动态调试了.

Untitled

其他的逻辑就比较简单了.

Untitled

1处读取一个数据放在buffer中,然后判断,buffer大小.\

2处读入五个数据,放在v15中,可以直接提取出来nkman

3处将flag读取出来.

v11的值为,nkman的数据值之和.但是这里需要注意:v11的数据类型为char,而char的数据类型,存储的最大数据为512,超过512将会溢出,这里nkman的值为533因此会发生溢出,所以最终v11所存的值为21

Untitled

Untitled

到此处为对我们的flag进行异或.v11.

Untitled

Untitled

通过下面的数据,我们可以知道,这里是迷宫,我们写个脚本将迷宫打印出来.

Untitled

将路线走出来即可

但是,这里是对我们的数据进行加密了的,但是位移运算是不可逆的,我们用z3将其爆破出来

Untitled

然后按照这个逻辑进行逆向即可,可以写出脚本.

#coding:utf-8
from z3 import *

data = [1, 1, 2, 2, 3, 3, 2, 2, 1, 2, 2, 3, 2, 2, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0,
        0, 0, 1, 0, 1, 1, 2, 1, 1, 0, 1, 1, 1, 2, 2, 2, 3, 2, 3, 3, 0, 3, 3, 2, 3, 2, 2, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3]

s = Solver()
flag = [BitVec(('x%d' % i), 8) for i in range(16)]
# for i in range(0, 16):
#     s.add(flag[i] < 127)
#     s.add(flag[i] > 32)

v7 = 0
n = 0
x = [6, 4, 2, 0]
for v7 in range(16):
    for k in x:
        s.add((data[n]==(flag[v7] >> k) & 3))
        n+=1

if s.check() == sat:
    model = s.model()
    string = [model[flag[i]].as_long().real for i in range(16)]
    print(string)
    exit()
else:
    print("无解")

将得出的数据,异或一下,然后保存在nk.ctf中,将其用winhex将其二进制数据提取出来,这就是我们的flag

nkctf{056e6b6d616e4fef7eb0004415047000bea9eeb043aa}

 评论