vnctf-part-wp

Posted by marginal on 2021-07-20
Estimated Reading Time 9 Minutes
Words 1.7k In Total
Viewed Times

VNCTF

filpgame

这个题目是仔细解读其实是一个翻牌游戏

输入减少‘7’如果输入为’A’ascii值为10,

输入16进制数值分别存放于v1,v2中

可以看到,把输入的把数word_18301C[v1]16bit中的v2位以及左右位变化,word_18301C[v1±1]的v2位变化

0 1 0 0 0 0 0 1 0 0 0 0 1 0 1 0

0 1 1 1 0 1 0 0 0 1 0 0 0 0 1 1

0 1 0 1 1 1 1 1 0 0 0 1 0 1 1 0

1 0 0 0 1 1 0 0 1 1 1 0 1 1 1 1

0 0 1 0 0 1 1 0 1 1 1 0 1 1 1 1

0 1 0 1 1 1 0 0 0 1 0 1 0 0 1 0

0 0 1 1 0 0 1 1 0 1 0 0 1 0 0 1

1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1

1 1 0 0 1 0 1 1 1 0 1 1 0 0 1 1

1 1 0 0 0 1 0 0 0 0 1 0 1 0 0 1

1 0 0 1 1 0 0 0 1 1 1 0 1 1 1 0

0 1 1 1 1 0 0 1 0 1 1 1 0 0 0 0

1 1 1 0 0 0 1 1 1 0 0 0 0 1 0 1

0 1 1 1 1 0 1 1 1 1 0 1 1 0 1 0

1 0 0 1 0 1 0 0 1 1 1 1 0 0 1 0

1 1 1 0 0 1 0 0 1 0 1 1 0 0 1 1

这个是数组的2进制表示,

要去数组每一个都等于-1,就是2进制表示每一个都等于1,这就成了翻转游戏(这不是算法题目dfs吗,吐了)

可以直接在网上找到模板,稍微修改一下,我不怎么看得懂这个东西,我直接把所有的0换为1,1换为0,一样的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include<cstdio>
#include<cstring>
#include<iostream>
//#define DEBUG
using namespace std;

int m, n;
int a[20][20], cnt[20][20], ans=0x3f3f3f3f, sumc = 0, anscnt[20][20];
int dir[5][2] = {{0,0},{0,1},{0,-1},{1,0},{-1,0}};

bool surpass(int i, int j){
if(i<0 || i>=m || j<0 || j>=n) return true;
return false;
}

int get(int i, int j)
{
int temp = a[i][j];
for(int k=0;k<5;k++)
{
int x = i+dir[k][0];
int y = j+dir[k][1];
if(!surpass(x, y)) temp += cnt[x][y];
}
return temp & 1;
}


void dfs()
{
for(int i=0;i<(1<<n);i++)
{
memset(cnt, 0, sizeof cnt);
sumc = 0; //改变的次数
int k = i;
for(int j=0;j<n;j++){
cnt[0][n-j-1] = k & 1;
sumc+= cnt[0][n-j-1];
k >>= 1;

}
for(int j=1;j<m;j++)
{
for(k=0;k<n;k++)
{
if(get(j-1, k)) //上方为1
{
cnt[j][k]=1;
sumc++;
}
}
}
int sumz = 0;
for(int j=0;j<n;j++)
{
sumz += get(m-1,j); // 统计最后一行的0
}
if(sumz==0 && sumc < ans)
{
ans = sumc;
memcpy(anscnt, cnt, sizeof cnt);
}
}
}

int main()
{
scanf("%d %d", &m, &n);
int sum=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++){
scanf("%d", &a[i][j]);
sum+=a[i][j];
}
}
memset(cnt, 0, sizeof cnt);
dfs();
if(ans == 0x3f3f3f3f) cout << "IMPOSSIBLE" << endl;
else
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
if (anscnt[i][j] == 1)
printf("%x%x", j, i);
}
}
return 0;
}

这样就直接得到输入结果,md5得到的结果4个,我是挨着试着交的32位小写交上了。

notsudoku

这个题目是一道python写的,然后打包成了exe文件。
查壳时发现,这个文件有upx壳,我当初想手脱的,但是dump出来的东西又有问题,就直接用upx工具脱了,再用exeinfope.exe工具查img
从这可以看出来是pyinstaller编译的,用pyinstxtractor.py提取pyc文件,(需要用python3.7做提取)
再次使用exeinfope.exe检查struct和2文件,可以发现struct是pyc文件,但是2文件却不是,2文件才是关键文件,需要更改文件头,不然不能uncompyle6反编译,直接把struct文件头和2文件头差异部分修改一下,把stuct文件头上多出来的加到2文件上面,更改一下后缀就可以uncompyle6了(不能python3.9)
接下来是2.py源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import time, sys, hashlib
class vm:
def __init__(self):
self.dict = {}
self.codeparameter = []
self._input = ''
self.d = [[],[],[],[],[]]
self.e = 65
self.flag1 = 0
def _add(self, key):
def の(f):
self.dict[key] = f
return f
return
def _get(self, key):
return self.dict.get(key)
def _run(self):
i = 0
while i < 28:
a = self.codeparameter[i][0]
b = self.codeparameter[i][1]
c = self.codeparameter[i][2]
fun = self._get(a)
fun(b, c)
i += 1
_vm = vm()
@_vm._add('_init')
def f1(a, b):
_vm.d[a] = b
@_vm._add('_output')
def f2(a, b):
\# if a == 1:
\# print(_vm._input)
\# else:
\# if a == 2:
\# print(_vm.d)
\# else:
if a == 3 and _vm.flag1 == 0:
print((_vm.flag), end='')
\# else:
\# print(a, end='')
@_vm._add('_exit()')
def f3(a, b):
_vm.flag1 = 0
\# @_vm._add('_input')
\# def f4(a, b):
_vm._input = input()
@_vm._add('_stop')#线程延迟,防止暴力a
def f5(a, b):
time.sleep(a)
@_vm._add('_cmp')#输入限制&&md5加密输入
def f6(a, b):
if len(_vm._input) % 2 != 0:#输入为偶数
_vm.flag1 = 1
for i in _vm._input:
if ord(i) > 52 or ord(i) < 48:#input is between 1 and 3
_vm.flag1 = 1
str1 = ''.join(_vm._input)
x = str(hashlib.new('md5', bytes((str1), encoding='utf8')).hexdigest())
if x[:6] != 'e3a912':
_vm.flag1 = 1
_vm.flag = x
@_vm._add('inputeffect')#输入效果
def f7(a, b):
j = 0
for i in range(0, len(_vm._input), 2):
j += 1
a = int(_vm._input[i])
b = int(_vm._input[(i + 1)])
_vm.d[a][b] = j
@_vm._add('_cmp2')#位置特定值判断
def f8(a, b):
if _vm.d[0][1] != 24 or _vm.d[4][3] != 2:
_vm.flag1 = 1
if _vm.d[0][2] != 1 or _vm.d[2][3] != 20:
_vm.flag1 = 1
if _vm.d[1][0] != 23 or _vm.d[3][4] != 3:
_vm.flag1 = 1
@_vm._add('_cmp3')#每一行每一列加起来为65
def f9(a, b):
e = 0
if b == -1:
for i in range(5):
e += _vm.d[a][i]
if e != _vm.e:
_vm.flag1 = 1
else:
for i in range(5):
e += _vm.d[i][b]
if e != _vm.e:
_vm.flag1 = 1
_vm.codeparameter = [#代码集合+参数
[
'_output', 'welcome baby~ ', 0],
[
'_output', 'input your flag~:', 0],
[
'_input', 0, 0],
[
'_output', 'your input is:', 0],
[
'_output', 1, 0],
[
'_output', "let's check......", 0],
[
'_stop', 0.5, 0],
[
'_init', 0, [0 for i in range(5)]],
[
'_init', 1, [0 for i in range(5)]],
[
'_init', 2, [0 for i in range(5)]],
[
'_init', 3, [0 for i in range(5)]],
[
'_init', 4, [0 for i in range(5)]],
[
'_cmp', 0, 0],
[
'inputeffect', 0, 0],
[
'_cmp2', 0, 0],
[
'_cmp3', 0, -1],
[
'_cmp3', 1, -1],
[
'_cmp3', 2, -1],
[
'_cmp3', 3, -1],
[
'_cmp3', 4, -1],
[
'_cmp3', 0, 0],
[
'_cmp3', 0, 1],
[
'_cmp3', 0, 2],
[
'_cmp3', 0, 3],
[
'_cmp3', 0, 4],
[
'_output', 'Goodjob!', 0],
[
'_output', 'The flag is vnctf{', 0],
[
'_output', 3, 0],
[
'_output', '}', 0],
[
'_exit()', 0, 0]]



_vm.flag1 = 0
_vm._run()

又是虚拟机,,,,,
+5阶幻方
具体算法我尝试搞了一下,搞了半天不出来,放弃了,还是网上搜模板把。


如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !