hackthebox challenge刷题系列2

xorxorxor

题目描述:

Who needs AES when you have XOR?

challenge.py内容如下:

#!/usr/bin/python3
import os
flag = open('flag.txt', 'r').read().strip().encode()

class XOR:
def __init__(self):
self.key = os.urandom(4)
def encrypt(self, data: bytes) -> bytes:
xored = b''
for i in range(len(data)):
xored += bytes([data[i] ^ self.key[i % len(self.key)]])
return xored
def decrypt(self, data: bytes) -> bytes:
return self.encrypt(data)

def main():
global flag
crypto = XOR()
print ('Flag:', crypto.encrypt(flag).hex())

if __name__ == '__main__':
main()

output.txt内容如下:

Flag: 134af6e1297bc4a96f6a87fe046684e8047084ee046d84c5282dd7ef292dc9

由于密钥只有4字节,且flag的前面的内容为HTB{,据此可以求出密钥,exp如下:

flag = '134af6e1297bc4a96f6a87fe046684e8047084ee046d84c5282dd7ef292dc9'
key = bytes(a ^ b for a,b in zip(b'HTB{', bytes.fromhex(flag)))
key = key * 10

flag = bytes(a ^ b for a,b in zip(key, bytes.fromhex(flag)))
print(flag)
$ python exp.py
b'HTB{rep34t3d_x0r_n0t_s0_s3cur3}'

RSAisEasy

题目描述:

I think this is safe… Right?

challenge.py内容如下:

#!/usr/bin/env python3
from Crypto.Util.number import bytes_to_long, getPrime
from secrets import flag1, flag2
from os import urandom

flag1 = bytes_to_long(flag1)
flag2 = bytes_to_long(flag2)

p, q, z = [getPrime(512) for i in range(3)]

e = 0x10001

n1 = p * q
n2 = q * z

c1 = pow(flag1, e, n1)
c2 = pow(flag2, e, n2)

E = bytes_to_long(urandom(69))

print(f'n1: {n1}')
print(f'c1: {c1}')
print(f'c2: {c2}')
print(f'(n1 * E) + n2: {n1 * E + n2}')

output.txt内容如下:

n1: 101302608234750530215072272904674037076286246679691423280860345380727387460347553585319149306846617895151397345134725469568034944362725840889803514170441153452816738520513986621545456486260186057658467757935510362350710672577390455772286945685838373154626020209228183673388592030449624410459900543470481715269
c1: 92506893588979548794790672542461288412902813248116064711808481112865246689691740816363092933206841082369015763989265012104504500670878633324061404374817814507356553697459987468562146726510492528932139036063681327547916073034377647100888763559498314765496171327071015998871821569774481702484239056959316014064
c2: 46096854429474193473315622000700040188659289972305530955007054362815555622172000229584906225161285873027049199121215251038480738839915061587734141659589689176363962259066462128434796823277974789556411556028716349578708536050061871052948425521408788256153194537438422533790942307426802114531079426322801866673
(n1 * E) + n2: 601613204734044874510382122719388369424704454445440856955212747733856646787417730534645761871794607755794569926160226856377491672497901427125762773794612714954548970049734347216746397532291215057264241745928752782099454036635249993278807842576939476615587990343335792606509594080976599605315657632227121700808996847129758656266941422227113386647519604149159248887809688029519252391934671647670787874483702292498358573950359909165677642135389614863992438265717898239252246163

由题目脚本可知:

从而得到:

对于$n_3$,有:

从而有:

求出p、q、z,便可按照rsa流程解密密文,exp如下:

import gmpy2
from Crypto.Util.number import long_to_bytes

n1 = 101302608234750530215072272904674037076286246679691423280860345380727387460347553585319149306846617895151397345134725469568034944362725840889803514170441153452816738520513986621545456486260186057658467757935510362350710672577390455772286945685838373154626020209228183673388592030449624410459900543470481715269
c1 = 92506893588979548794790672542461288412902813248116064711808481112865246689691740816363092933206841082369015763989265012104504500670878633324061404374817814507356553697459987468562146726510492528932139036063681327547916073034377647100888763559498314765496171327071015998871821569774481702484239056959316014064
c2 = 46096854429474193473315622000700040188659289972305530955007054362815555622172000229584906225161285873027049199121215251038480738839915061587734141659589689176363962259066462128434796823277974789556411556028716349578708536050061871052948425521408788256153194537438422533790942307426802114531079426322801866673
e = 0x10001
n3 = 601613204734044874510382122719388369424704454445440856955212747733856646787417730534645761871794607755794569926160226856377491672497901427125762773794612714954548970049734347216746397532291215057264241745928752782099454036635249993278807842576939476615587990343335792606509594080976599605315657632227121700808996847129758656266941422227113386647519604149159248887809688029519252391934671647670787874483702292498358573950359909165677642135389614863992438265717898239252246163

q = gmpy2.gcd(n1, n3)
n2 = n3 % n1

p = n1 // q
z = n2 // q

d1 = pow(e, -1, (q - 1) * (p - 1))
d2 = pow(e, -1, (q - 1) * (z - 1))
flag1 = pow(c1, d1, n1)
flag2 = pow(c2, d2, n2)
print(long_to_bytes(flag1) + long_to_bytes(flag2))
$ python exp.py
b'HTB{1_m1ght_h4v3_m3ss3d_uP_jU$t_4_l1ttle_b1t?}'

Quantum-Safe

题目描述:

I heard Shor’s algorithm can do all sorts of nasty things to RSA, so I’ve decided to be super modern and protect my flag with cool new maffs!

source.sage文件如下:

from random import randint
from secrets import flag, r

pubkey = Matrix(ZZ, [
[47, -77, -85],
[-49, 78, 50],
[57, -78, 99]
])

for c in flag:
v = vector([ord(c), randint(0, 100), randint(0, 100)]) * pubkey + r
print(v)

enc.txt内容如下:

(-981, 1395, -1668)
(6934, -10059, 4270)
(3871, -5475, 3976)
(4462, -7368, -8954)
(2794, -4413, -3461)
(5175, -7518, 3201)
(3102, -5051, -5457)
(7255, -10884, -266)
(5694, -8016, 6237)
(4160, -6038, 2582)
(4940, -7069, 3770)
(3185, -5158, -4939)
(7669, -11686, -2231)
(5601, -9013, -7971)
(5600, -8355, 575)
(1739, -2838, -3037)
(2572, -4120, -3788)
(8055, -11985, 1137)
(7088, -10247, 5141)
(8384, -12679, -1381)
(-785, 1095, -1841)
(4250, -6762, -5242)
(3716, -5364, 2126)
(5673, -7968, 6741)
(5877, -9190, -4803)
(5639, -8865, -5356)
(1980, -3230, -3366)
(6183, -9334, -1002)
(2575, -4068, -2828)
(7521, -11374, -1137)
(5639, -8551, -1501)
(4194, -6039, 3213)
(2072, -3025, 383)
(2444, -3699, -502)
(6313, -9653, -2447)
(4502, -7090, -4435)
(-421, 894, 2912)
(4667, -7142, -2266)
(4228, -6616, -3749)
(6258, -9719, -4407)
(6044, -9561, -6463)
(266, -423, -637)
(3849, -6223, -5988)
(5809, -9021, -4115)
(4794, -7128, 918)
(6340, -9442, 892)
(5322, -8614, -8334)

题目脚本使用了一个pubkey作为加密矩阵,flag中每个字符转换为ASCII值后,与两个随机数组成一个三维向量,然后通过加密矩阵做了一次乘法,最终加上r之后得到向量v。

有:

其中$random_1$和$random_2$为randint生成的随机数。

可以发现,根据enc.txt中得到的结果,我们可以穷举出所有的可能来得到r,因为对于flag的前四个字符是HTB{,并且后序的flag也是明文字符,而且随机数的范围是在0-100之间,exp如下:

import string

outputs = [
[-981, 1395, -1668],
[6934, -10059, 4270],
[3871, -5475, 3976],
[4462, -7368, -8954],
[2794, -4413, -3461],
[5175, -7518, 3201],
[3102, -5051, -5457],
[7255, -10884, -266],
[5694, -8016, 6237],
[4160, -6038, 2582],
[4940, -7069, 3770],
[3185, -5158, -4939],
[7669, -11686, -2231],
[5601, -9013, -7971],
[5600, -8355, 575],
[1739, -2838, -3037],
[2572, -4120, -3788],
[8055, -11985, 1137],
[7088, -10247, 5141],
[8384, -12679, -1381],
[-785, 1095, -1841],
[4250, -6762, -5242],
[3716, -5364, 2126],
[5673, -7968, 6741],
[5877, -9190, -4803],
[5639, -8865, -5356],
[1980, -3230, -3366],
[6183, -9334, -1002],
[2575, -4068, -2828],
[7521, -11374, -1137],
[5639, -8551, -1501],
[4194, -6039, 3213],
[2072, -3025, 383],
[2444, -3699, -502],
[6313, -9653, -2447],
[4502, -7090, -4435],
[-421, 894, 2912],
[4667, -7142, -2266],
[4228, -6616, -3749],
[6258, -9719, -4407],
[6044, -9561, -6463],
[266, -423, -637],
[3849, -6223, -5988],
[5809, -9021, -4115],
[4794, -7128, 918],
[6340, -9442, 892],
[5322, -8614, -8334]
]

# 可打印字符集
printable_chars = string.printable

def get_candidates(index, output, candidates, chars):
results = set()

for c in chars:
cc = ord(c)
for a1 in range(101):
for a2 in range(101):
r1 = output[0] - (cc * 47) - (a1 * -49) - (a2 * 57)
r2 = output[1] - (cc * -77) - (a1 * 78) - (a2 * -78)
r3 = output[2] - (cc * -85) - (a1 * 50) - (a2 * 99)
r = str([r1, r2, r3])

if (len(candidates) == 0) or (r in candidates):
candidate_map[index][r] = c
results.add(r)

return results

candidate_map = []
number_of_outputs = len(outputs)
candidates = set()

for i in range(number_of_outputs):
candidate_map.append(dict())
if i < 4:
chars = "HTB{"[i]
else:
chars = printable_chars

# 穷举可能的组合
candidates = get_candidates(i, outputs[i], candidates, chars)
print("number of candidates =", len(candidates))

for r in candidates:
print("r = ", r)
flag = ""
for i in range(number_of_outputs):
flag += (candidate_map[i][r])

print("flag = ", flag)
$ python exp.py
number of candidates = 10201
number of candidates = 522
number of candidates = 522
number of candidates = 360
number of candidates = 360
number of candidates = 288
number of candidates = 288
number of candidates = 288
number of candidates = 26
number of candidates = 26
number of candidates = 21
number of candidates = 11
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
number of candidates = 3
r = [-53, 75, 52]
flag = HTB{r3duc1nG_tH3_l4tTicE_l1kE_n0b0dY's_pr0bl3M}
r = [-102, 153, 102]
flag = HTB{r3duc1nG_tH3_l4tTicE_l1kE_n0b0dY's_pr0bl3M}
r = [-4, -3, 2]
flag = HTB{r3duc1nG_tH3_l4tTicE_l1kE_n0b0dY's_pr0bl3M}
文章作者: Alex
文章链接: http://example.com/2024/02/14/hackthebox-challenge-Crypto2/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alex's blog~