RCTF2018 writeup1

前言

  CTFer是不存在周末的,更不存在520….

杂项

git

  首先查看了git log但没有线索,思索了一下就直接去查看git文件,最终找到flag.txt。




  接着在logs/HEAD里找到存在flag.txt的编码,再穿越回去即可恢复flag文件。




  flag为:RCTF{gIt_BranCh_aNd_l0g}

sign

  下载后是个exe,但不能运行,用IDA打开后在WinMain函数里可以找到明文的flag,但这个跟IDA的版本有关系,作者的IDA7.0就不行,但队友的OK。

Number Game

  比较有意思的一道题,一开始手工各种玩,但根据以往出题人的尿性,越往后时间肯定越短,所以只能考虑自动化脚本提交,然后就去Google了一下猜数字游戏,得到有价值的线索。




  点开看了一下,很真的是一样的玩法,而且下面还有个解题脚本,但由于那个脚本太过复杂,不利于快速修改,只好去gayhub(github)搜索,最终找到一个匹配度极高的solve.py传送门

PS: gayhub真是个好东西

  拿到脚本后进行改造,最终的脚本如下:

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
# -*-coding:utf-8 -*-
import string
import hashlib
import socket
import re
import random

def sha256(s):
return hashlib.sha256(s).hexdigest()

def fuzz(a, goal):
strs = string.letters + string.digits
print('[+]爆破中...')
rnds = ''
for i in strs:
for j in strs:
for k in strs:
for l in strs:
rnds = i + j + k + l
result = sha256(rnds + a)
if result == goal:
return rnds


all_char=['0','1','2','3','4','5','6','7','8','9']
is_visited=[0,0,0,0,0,0,0,0,0,0]
all_combine=[]
temp=['','','','']
def generate(step):
if step==4:
all_combine.append(''.join(temp))
else:
for i in range(0,10):
if is_visited[i]:continue
temp[step]=all_char[i]
is_visited[i]=1
generate(step+1)
is_visited[i]=0
generate(0)
now=all_combine[random.randint(0,len(all_combine)-1)]
the_leaf=all_combine[:]
def get_type_t(ra,rb):
return 10*(ra+1)+rb
def get_type_s(a,b):
aa=[a[0],a[1],a[2],a[3]]
bb=[b[0],b[1],b[2],b[3]]
cc=[0,0,0,0]
ra=0
rb=0
s=0
for i in range(0,4):
if aa[i]==bb[i]:
ra+=1
cc[i]=1
for i in range(0,4):
if cc[i]:continue
for j in range(0,4):
if aa[i]==bb[j]:
rb+=1
s=get_type_t(ra,rb)
return s

n = 1
# 传入a,b
# 返回now
def guess_num(a, b):
a = int(a)
b = int(b)
global n, now, the_leaf
print("第"+str(n)+"猜")
if a+b >4:
print("輸入有錯")
return None
elif a==4:
print("贏惹啦")
return None
else:
s=get_type_t(a,b)
temp=[]
for i in range(0,len(the_leaf)):
if get_type_s(now,the_leaf[i])==s:
temp.append(the_leaf[i])
the_leaf=temp[:]
if len(the_leaf)==0:
print("你一定有輸入錯")
return None
elif len(the_leaf)==1:
print("答案是 "+the_leaf[0]+" 不然就是你輸入有錯")
return the_leaf[0]
now=the_leaf[random.randint(0,len(the_leaf)-1)]
n+=1
return now


sc = socket.socket() # 创建 socket 对象
host = "149.28.139.172" # 获取本地主机名
port = 10002 # 设置端口
addr = (host, port)
sc.connect(addr) # 绑定端口号
tmp = sc.recv(1024)
print(tmp + sc.recv(1024))
gg = re.findall('\+(.*)\)', tmp)[0]
sha = re.findall('== (.*)', tmp)[0]
go = fuzz(gg, sha)
print('[*]爆破完成:'+go)
sc.send(go+'\n')
print(sc.recv(2048))
print(sc.recv(1024))

def one_round(rd):
nums = ' '.join(now)
print('[+]guess: ' + nums)
sc.send(nums + '\n')
rev = sc.recv(1024)
print('[+]raw: ' + rev)
a = re.findall('\d', rev)[0]
b = re.findall('\d', rev)[1]
print('[+]result: ' + a + ' ' + b)

for _ in range(6):
hh = guess_num(a,b)
if hh == None:
print('[*]程序出错!')
exit(1)
nums = ' '.join(hh)
print('[+]guess: ' + nums)
sc.send(nums + '\n')
rev = sc.recv(1024)
if re.search('You lose', rev):
print('[!]预测出错,请重新启动!')
exit(1)
if re.search('You got it', rev):
print('[*]第{}关完成!'.format(rd))
break
a = re.findall('\d', rev)[0]
b = re.findall('\d', rev)[1]
print('[+]result: ' + a + ' ' + b)

flag = sc.recv(1024)
print(flag)
if re.search('flag', flag, re.IGNORECASE):
print('[*]已找到flag!')
exit(0)

for rd in range(10):
generate(0)
now=all_combine[random.randint(0,len(all_combine)-1)]
the_leaf=all_combine[:]
one_round(rd + 1)

  脚本存在一定误差率,如果提示失败,请多试几次。

  flag:RCTF{0lD_GaM3_nAmed_Bu11s_4nd_C0ws}

RE

babyre

  这道题是跟队友一起做的,我负责打酱油。。。

  首先题目给出了两个文件,一个可执行文件(babyre),一个输出文件(out)。out文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
B80C91FE70573EFE
BEED92AE7F7A8193
7390C17B90347C6C
AA7A15DFAA7A15DF
526BA076153F1A32
545C15AD7D8AA463
526BA076FBCB7AA0
7D8AA4639C513266
526BA0766D7DF3E1
AA7A15DF9C513266
1EDC38649323BC07
7D8AA463FBCB7AA0
153F1A32526BA076
F5650025AA7A15DF
1EDC3864B13AD888

  一开始没看出这是程序运行过程产生的输出结果,是队友提供的思路。

  用IDA查看了一下,只有一个地方有printf输出。




  认真观察输出结果跟代码后可以发现,程序循环30次,每次输出8位字符,而这个跟题目给出的文件(15行,每行16位)高度吻合,所以猜测这些就是我们要找的flag。

  然后运行一下程序,发现特定的字符不管运行几次结果都一样,所以解题思路就是爆破ASCII码表。我们可以将可见字符的8位输出结果保存起来,然后进行比对。最后写了个半自动脚本:

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
# -*-coding:utf-8-*-
import re

fle = open('E:/Download/babyre/out', 'r')
goal = []
for one in fle.readlines():
one = one.strip('\n')
goal.append(one[:8])
goal.append(one[8:])

strs = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
strs = list(strs)

tmp = []
fle2 = open('E:/Download/babyre/shuju.txt', 'r')
for one in fle2.readlines():
tmp.append(one.strip('\n'))

flag = ''

for one in goal:
for ids, tt in enumerate(tmp):
ok = re.search(one, tt, re.IGNORECASE)
if ok:
flag += strs[ids]

print(flag)

  flag:RCTF{Kee1o9_1s_a1ready_so1ved}
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×