红帽杯2018部分writeup

熬了一天,感觉pwn和re的水平退步不少。

PWN

这次比赛中的pwn的题目难度一般,3个pwn分别涉及到

  • 栈溢出 ——game server
  • null byte offset-by-one —— shellcode manager
  • 格式化串漏洞 —— Starcraft RPG

中间在漏洞利用过程中也踩到了一些坑(可能是长期没打没有手感,有时间会整理一下)。

RE

re只看了最简单的icm,感觉自己re方面真是非常菜,赛后重新整理了getFlag的脚本,进行了简化:

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
#!/usr/bin/env python
'''
pip install cryptography
'''
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend


def getCipherAlgorithm(key, mode):
backend = default_backend()
cipher = Cipher(algorithms.IDEA(key), mode, backend=backend)
return cipher

def encrypt(plainMsg, key, mode):
cipher = getCipherAlgorithm(key, mode)
encryptor = cipher.encryptor()
res = encryptor.update(plainMsg) + encryptor.finalize()
return res

def decrypt(cipherMsg, key, mode):
cipher = getCipherAlgorithm(key, mode)
decryptor = cipher.decryptor()
res = decryptor.update(cipherMsg) + decryptor.finalize()
return res

def getKey():
from ctypes import *
res = []
buf = ""
libc = cdll.LoadLibrary("libc.so.6")
libc.srand(0x78C819C3)
for i in range(16):
buf += "{:02x}".format(libc.rand() % 256).decode('hex')
return buf

def getCipherText():
secret = [
0xd0, 0xe0, 0xab, 0x9c, 0xcd, 0x78, 0x5b, 0x54,
0x3d, 0xe4, 0xea, 0x33, 0x51, 0x44, 0x6d, 0x3c,
0x4e, 0xce, 0xdf, 0xb5, 0x41, 0x0, 0x1c, 0xec,
0xe3, 0x1b, 0xc3, 0x8c, 0x91, 0x25, 0x7f, 0x1b,
0x60, 0xfe, 0x35, 0x9c, 0xea, 0x4, 0x4c, 0x87,
0x8d, 0x97, 0x93, 0x5c, 0xb8, 0x9a, 0x70, 0x75,
]
buf = ""
for i in range(len(secret)):
secret[i] = (119-i) ^ secret[i]
for i in range(len(secret)):
secret[i] = secret[i] ^ (8 - i%8)
buf += "{:02x}".format(secret[i]).decode('hex')

return buf

def getFlag():
cipherText = getCipherText()
key = getKey()
mode = modes.ECB()
msg = decrypt(cipherText, key, mode)
print msg

if __name__ == '__main__':
getFlag()

wcm解密脚本:

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
'''
SM4 from https://github.com/yixiangzhike/AlgorithmSM
'''
from SM4 import *
from ctypes import *


def getKey():
key = ""
libc = cdll.msvcrt
libc.srand(0x2872DD1B)
for i in range(16):
key += "{:02x}".format(libc.rand() % 256)
return key.decode('hex')


def getCipherText():
secret = [
0xf4, 0x88, 0x91, 0xc2, 0x9b, 0x20, 0x5b, 0x3,
0xf1, 0xed, 0xf6, 0x13, 0x46, 0x3c, 0x55, 0x81,
0x61, 0xf, 0xff, 0x14, 0x6e, 0x1c, 0x48, 0x28,
0x79, 0x9f, 0x85, 0xaf, 0xc5, 0x58, 0xd, 0xd6,
0xa5, 0xd9, 0x64, 0xfd, 0x46, 0x9, 0x8c, 0xdf,
0x3b, 0xa5, 0x37, 0x62, 0x5a, 0xa6, 0xd2, 0x4b,
]
v9 = 51
cipherText = ""
while v9 - 51 < 48:
cipherText += "{:02x}".format(secret[v9-51] ^ v9)
v9 += 1
return cipherText.decode('hex')


key = getKey().encode('hex')
print "key is {}".format(key)
cipherText = getCipherText().encode('hex')
print "cipherText is {}".format(cipherText)
sm4 = SM4(key=key)
msg = sm4.sm4_decrypt(cipherText, SM4_ECB)
print msg.decode('hex')

Crypto

3dlight,当时就考虑用解多元一次方程组的方法来求解,当时搞不动了,后来抽空写了下生成系数矩阵的脚本,迎刃而解

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
import numpy as np
import os


def str2arr(str):
return [[[(ord(str[i * 8 + j]) >> k & 1) for k in xrange(8)] for j in xrange(8)] for i in xrange(8)]


def str2arr_rev(arr):
ret = ""
for i in xrange(8):
for j in xrange(8):
ret += chr(int(''.join(map(str, arr[i][j][::-1])), 2))
return ret


def arr2str(arr):
ret = ''
for i in xrange(8):
for j in xrange(8):
for k in xrange(8):
ret += chr(arr[i][j][k])
return ret


def arr2str_rev(str2):
ret = [[[0 for k in xrange(8)] for j in xrange(8)] for i in xrange(8)]
for i in xrange(8):
for j in xrange(8):
for k in xrange(8):
ret[i][j][k] = ord(str2[i*64+j*8+k])
return ret


def check(x, y, z):
if x < 0 or x > 7 or y < 0 or y > 7 or z < 0 or z > 7:
return False
return True


def light(arr, i, j, k, x, y, z, power): # square
if check(i + x, j + y, k + z):
arr[i + x][j + y][k + z] += power # top right
if x != 0 and check(i - x, j + y, k + z):
arr[i - x][j + y][k + z] += power #
if y != 0 and check(i + x, j - y, k + z):
arr[i + x][j - y][k + z] += power
if z != 0 and check(i + x, j + y, k - z):
arr[i + x][j + y][k - z] += power
if x != 0 and y != 0 and check(i - x, j - y, k + z):
arr[i - x][j - y][k + z] += power
if x != 0 and z != 0 and check(i - x, j + y, k - z):
arr[i - x][j + y][k - z] += power
if y != 0 and z != 0 and check(i + x, j - y, k - z):
arr[i + x][j - y][k - z] += power
if x != 0 and y != 0 and z != 0 and check(i - x, j - y, k - z):
arr[i - x][j - y][k - z] += power


def encrypt(flag, power):
ret = [[[0 for _ in xrange(8)] for _ in xrange(8)] for _ in xrange(8)]
lights = str2arr(flag)
for i in range(8):
for j in range(8):
for k in range(8):
if lights[i][j][k] == 1: # bit is 1
for x in range(power):
for y in range(power - x):
for z in range(power - x - y):
light(ret, i, j, k, x, y, z, power - x - y - z)
return arr2str(ret)


def getMatrix():
A = [[ 0 for i in range(8**3)] for j in range(8**3)]
for row in range(len(A)):
ord_x = row / 8**2
ord_y = (row - ord_x*(8**2))/8
ord_z = row % 8
A[row][ord_x * 8**2 + ord_y * 8 + ord_z] = 2
if ord_x > 0:
A[row][(ord_x-1)* 8**2 + ord_y*8 + ord_z] = 1
if ord_x < 7:
A[row][(ord_x+1)* 8**2 + ord_y*8 + ord_z] = 1
if ord_y > 0:
A[row][ord_x* 8**2 + (ord_y-1) *8 + ord_z] = 1
if ord_y < 7:
A[row][ord_x* 8**2 + (ord_y+1) *8 + ord_z] = 1
if ord_z > 0:
A[row][ord_x * 8**2 + ord_y * 8 + ord_z -1 ] = 1
if ord_z < 7:
A[row][ord_x * 8**2 + ord_y * 8 + ord_z + 1] = 1
return np.array(A)


def getCipher():
flag = "flag{abcdefg_hij_klm_nop_qrst_uvwxyz_0123456789_1234567890__xyz}"
shuffle_flag = ''.join(flag[0::2][i] + flag[-1::-2][i] for i in xrange(32))
cipher = encrypt(shuffle_flag, 2)
CipherArr =arr2str_rev(cipher)
return np.array(CipherArr).flatten()


def decrypt():
solvea = np.linalg.solve(getMatrix(), getCipher())
t = []
for a in solvea:
if abs(a) < 0.0001:
t.append(0)
else:
t.append(1)
flag = ""
for i in range(0, len(t), 8):
flag += chr(int(''.join(map(str, t[i:i+8]))[::-1], 2))
return ''.join(flag[0::2][i] + flag[-1::-2][i] for i in xrange(32))


print decrypt()