Crypto
CRYPTO01
2023 Jiangsu Province Pilot Cup bd Original Question:
Title:
from import *
from secret import flag
p = getPrime(512)
q = getPrime(512)
n = p * q
d = getPrime(299)
e = inverse(d,(p-1)*(q-1))
m = bytes_to_long(flag)
c = pow(m,e,n)
hint1 = p >> (512-70)
hint2 = q >> (512-70)
print(f"n = {n}")
print(f"e = {e}")
print(f"c = {c}")
print(f"hint1 = {hint1}")
print(f"hint2 = {hint2}")
n = 95987463597889741532025162535631829592517704738860431905943824498597890101136796870879646153634795544527837591685182170270252555997933421564167468816667980089869165228796395618775798781717091178143300536302805947806332962230499807469654672313206953750808878098101882367253566423367338396717229488061237787619
e = 12761568528114005244342182138319275328501544878744699681091257281459893043102455333575012392492554249378138377894473691530001400901111860569849400611145049669197371290112261284014768486937294128410391332641648640840309135718123516725634190495261570498188176102281061084366456374907755950527213961595506707585
c = 35154471719082941146017277238175991504655570882040897713927696748547265178059291385527810510087300325678561502592029686486144851647754163110759942860051150957340793828236482243293747881251009434747066136505663782280758979333019882382608002308773317613847702048959887017010151916544703971113441862351668075919
hint1 = 1175980694459189065778
hint2 = 632846170973644915854
Thoughts:
Utilizing the upper high boneh_durfee attack
Reference Paper:
[ ()](/2023/)
Scripts from their experiments:Codes of the manuscript—Practical Attacks on Small Private Exponent RSA—New Records and New Insi -
exp:
Recover d first
import time
=
debug = True
strict = False
helpful_only = True
dimension_min = 7 # If the lattice reaches that size,then stop removing
# Display statistics of useful vectors
def helpful_vectors(BB, modulus):
nothelpful = 0
for ii in range(()[0]):
if BB[ii,ii] >= modulus:
nothelpful += 1
# Display with 0 cap (a poem) X matrices
def matrix_overview(BB, bound):
for ii in range(()[0]):
a = ('%02d ' % ii)
for jj in range(()[1]):
a += '0' if BB[ii,jj] == 0 else 'X'
if ()[0] < 60:
a += ' '
if BB[ii, ii] >= bound:
a += '~'
#print (a)
# Trying to remove useless vectors
# current = n-1(The last vector)commencement
def remove_unhelpful(BB, monomials, bound, current):
# 我们current = n-1(The last vector)commencement
if current == -1 or ()[0] <= dimension_min:
return BB
# commencement从后面检查
for ii in range(current, -1, -1):
# If it doesn't work
if BB[ii, ii] >= bound:
affected_vectors = 0
affected_vector_index = 0
# Let's check if it affects other vectors
for jj in range(ii + 1, ()[0]):
# If another vector is affected:
# Let's increase the count.
if BB[jj, ii] != 0:
affected_vectors += 1
affected_vector_index = jj
# hierarchy:0
# If no other carriers are ultimately affected
# Let's delete it.
if affected_vectors == 0:
#print ("* removing unhelpful vector", ii)
BB = BB.delete_columns([ii])
BB = BB.delete_rows([ii])
(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# hierarchy:1
#If only one is affected,We'll check.
# If it is affecting another vector
elif affected_vectors == 1:
affected_deeper = True
for kk in range(affected_vector_index + 1, ()[0]):
# If it affects even one vector
# Let's drop this.
if BB[kk, affected_vector_index] != 0:
affected_deeper = False
# If no other vectors are affected,then delete it,besides
# This useful vector is not useful enough
#Compared to our useless
if affected_deeper and abs(bound - BB[affected_vector_index, affected_vector_index]) < abs(bound - BB[ii, ii]):
#print ("* removing unhelpful vectors", ii, "and", affected_vector_index)
BB = BB.delete_columns([affected_vector_index, ii])
BB = BB.delete_rows([affected_vector_index, ii])
(affected_vector_index)
(ii)
BB = remove_unhelpful(BB, monomials, bound, ii-1)
return BB
# nothing happened
return BB
"""
Returns:
* 0,0 if it fails
* -1,-1 in the event that "strict=true",besides行列式不受约束
* x0,y0 the solutions of `pol`
"""
def boneh_durfee(pol, modulus, mm, tt, XX, YY):
"""
Boneh and Durfee revisited by Herrmann and May
Find solutions in the following cases:
* d < N^delta
* |x|< e^delta
* |y|< e^0.5
on every delta < 1 - sqrt(2)/2 ~ 0.292
"""
# substitution (Herrman and May)
PR.<u, x, y> = PolynomialRing(ZZ) #polynomial ring
Q = (x*y + 1 - u) # u = xy + 1
polZ = Q(pol).lift()
UU = XX*YY + 1
# x-(medicine) dislocation
gg = []
for kk in range(mm + 1):
for ii in range(mm - kk + 1):
xshift = x^ii * modulus^(mm - kk) * polZ(u, x, y)^kk
(xshift)
()
# monomial x (medicine) dislocation列表
monomials = []
for polynomial in gg:
for monomial in (): #insofar aspolynomial (math.)中(used form a nominal expression)monomial。monomial():
if monomial not in monomials: # in the event that单项不在单项中
(monomial)
()
# y-(medicine) dislocation
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
yshift = y^jj * polZ(u, x, y)^kk * modulus^(mm - kk)
yshift = Q(yshift).lift()
(yshift) # substitution
# monomial y (medicine) dislocation列表
for jj in range(1, tt + 1):
for kk in range(floor(mm/tt) * jj, mm + 1):
(u^kk * y^jj)
# tectonic plate B
nn = len(monomials)
BB = Matrix(ZZ, nn)
for ii in range(nn):
BB[ii, 0] = gg[ii](0, 0, 0)
for jj in range(1, ii + 1):
if monomials[jj] in gg[ii].monomials():
BB[ii, jj] = gg[ii].monomial_coefficient(monomials[jj]) * monomials[jj](UU,XX,YY)
#Prototype of the approximation lattice
if helpful_only:
# #automatic deletion
BB = remove_unhelpful(BB, monomials, modulus^mm, nn-1)
# (math.) reset dimension
nn = ()[0]
if nn == 0:
print ("failure")
return 0,0
# Check if vectors are helpful
if debug:
helpful_vectors(BB, modulus^mm)
# Check that determinants are correctly defined
det = ()
bound = modulus^(mm*nn)
if det >= bound:
print ("We do not have det < bound. Solutions might not be found.")
print ("Try with highers m and t.")
if debug:
diff = (log(det) - log(bound)) / log(2)
print ("size det(L) - size e^(m*n) = ", floor(diff))
if strict:
return -1, -1
else:
print ("det(L) < e^(m*n) (good! If a solution exists < N^delta, it will be found)")
# display the lattice basis
if debug:
matrix_overview(BB, modulus^mm)
# LLL
if debug:
print ("optimizing basis of the lattice via LLL, this can take a long time")
#BB = (block_size=25)
BB = ()
if debug:
print ("LLL is done!")
# substitution vector i cap (a poem) j ->polynomial (math.) 1 cap (a poem) 2
if debug:
print ("Finding linearly uncorrelated vectors in a lattice")
found_polynomials = False
for pol1_idx in range(nn - 1):
for pol2_idx in range(pol1_idx + 1, nn):
# insofar asi and j, 构造两个polynomial (math.)
PR.<w,z> = PolynomialRing(ZZ)
pol1 = pol2 = 0
for jj in range(nn):
pol1 += monomials[jj](w*z+1,w,z) * BB[pol1_idx, jj] / monomials[jj](UU,XX,YY)
pol2 += monomials[jj](w*z+1,w,z) * BB[pol2_idx, jj] / monomials[jj](UU,XX,YY)
# in the end
PR.<q> = PolynomialRing(ZZ)
rr = (pol2)
if rr.is_zero() or () == [1]:
continue
else:
print ("found them, using vectors", pol1_idx, "and", pol2_idx)
found_polynomials = True
break
if found_polynomials:
break
if not found_polynomials:
print ("no independant vectors could be found. This should very rarely happen...")
return 0, 0
rr = rr(q, q)
# solutions
soly = ()
if len(soly) == 0:
print ("Your prediction (delta) is too small")
return 0, 0
soly = soly[0][0]
ss = pol1(q, soly)
solx = ()[0][0]
return solx, soly
def example():
############################################
# Random generation of data
##########################################
#start_time =time.perf_counter
start =()
size=512
length_N = 2*size;
ss=0
s=70;
M=1 # the number of experiments
delta = 299/1024
# p = random_prime(2^512,2^511)
for i in range(M):
# p = random_prime(2^size,None,2^(size-1))
# q = random_prime(2^size,None,2^(size-1))
# if(p<q):
# temp=p
# p=q
# q=temp
N = 95987463597889741532025162535631829592517704738860431905943824498597890101136796870879646153634795544527837591685182170270252555997933421564167468816667980089869165228796395618775798781717091178143300536302805947806332962230499807469654672313206953750808878098101882367253566423367338396717229488061237787619
e = 12761568528114005244342182138319275328501544878744699681091257281459893043102455333575012392492554249378138377894473691530001400901111860569849400611145049669197371290112261284014768486937294128410391332641648640840309135718123516725634190495261570498188176102281061084366456374907755950527213961595506707585
c = 35154471719082941146017277238175991504655570882040897713927696748547265178059291385527810510087300325678561502592029686486144851647754163110759942860051150957340793828236482243293747881251009434747066136505663782280758979333019882382608002308773317613847702048959887017010151916544703971113441862351668075919
hint1 = 1175980694459189065778
hint2 = 632846170973644915854
# print ("pauthentically high",s,"bit (binary digit) (loanword):", int(p/2^(512-s)))
# print ("qauthentically high",s,"bit (binary digit) (loanword):", int(q/2^(512-s)))
# N = p*q;
# Decryption indexdexponential( greatest0.292)
m = 7 # frame size(The bigger the better./slower)
t = round(((1-2*delta) * m)) # come from (a place) Herrmann cap (a poem) May optimization
X = floor(N^delta) #
Y = floor(N^(1/2)/2^s) # in the event that p、 q same size,follow
for l in range(int(hint1),int(hint1)+1):
print('\n\n\n l=',l)
pM=l;
p0=pM*2^(size-s)+2^(size-s)-1;
q0=N/p0;
qM=int(q0/2^(size-s))
A = N + 1-pM*2^(size-s)-qM*2^(size-s);
#A = N+1
P.<x,y> = PolynomialRing(ZZ)
pol = 1 + x * (A + y) #Constructed equations
# Checking bounds
#if debug:
#print ("=== Verification of data ===")
#print ("* delta:", delta)
#print ("* delta < 0.292", delta < 0.292)
#print ("* size of e:", ceil(log(e)/log(2))) # e(used form a nominal expression)bitcriticize (i.e. enumerate shortcomings)
# print ("* size of N:", len(bin(N))) # N(used form a nominal expression)bitcriticize (i.e. enumerate shortcomings)
#print ("* size of N:", ceil(log(N)/log(2))) # N(used form a nominal expression)bitcriticize (i.e. enumerate shortcomings)
#print ("* m:", m, ", t:", t)
# boneh_durfee
if debug:
##print ("=== running algorithm ===")
start_time = ()
solx, soly = boneh_durfee(pol, e, m, t, X, Y)
if solx > 0:
#print ("=== solution found ===")
if False:
print ("x:", solx)
print ("y:", soly)
d_sol = int(pol(solx, soly) / e)
ss=ss+1
print ("=== solution found ===")
print ("p(used form a nominal expression)高bit (binary digit) (loanword)为:",l)
print ("q(used form a nominal expression)高bit (binary digit) (loanword)为:",qM)
print ("d=",d_sol)
if debug:
print("=== %s seconds ===" % (() - start_time))
#break
print("ss=",ss)
#end=time.process_time
end=()
print('Running time: %s Seconds'%(end-start))
if __name__ == "__main__":
example()
And then solve the rsa normally.
from import *
import gmpy2
n = 95987463597889741532025162535631829592517704738860431905943824498597890101136796870879646153634795544527837591685182170270252555997933421564167468816667980089869165228796395618775798781717091178143300536302805947806332962230499807469654672313206953750808878098101882367253566423367338396717229488061237787619
e = 12761568528114005244342182138319275328501544878744699681091257281459893043102455333575012392492554249378138377894473691530001400901111860569849400611145049669197371290112261284014768486937294128410391332641648640840309135718123516725634190495261570498188176102281061084366456374907755950527213961595506707585
c = 35154471719082941146017277238175991504655570882040897713927696748547265178059291385527810510087300325678561502592029686486144851647754163110759942860051150957340793828236482243293747881251009434747066136505663782280758979333019882382608002308773317613847702048959887017010151916544703971113441862351668075919
hint1 = 1175980694459189065778
hint2 = 632846170973644915854
d = 994872951830622609173239108988480436496396666299008546372509127121113351371824434704770953
m = pow(c,d,n)
print(long_to_bytes(m))
flag: wdflag{a14a7fa0-4e7b-4624-ad0c-36c31dd8012e}
CRYPTO02
Title:
# coding: utf-8
#!/usr/bin/env python2
import gmpy2
import random
import binascii
from hashlib import sha256
from sympy import nextprime
from import AES
from import pad
from import long_to_bytes
from FLAG import flag
#flag = 'wdflag{123}'
def victory_encrypt(plaintext, key):
key = ()
key_length = len(key)
plaintext = ()
ciphertext = ''
for i, char in enumerate(plaintext):
if ():
shift = ord(key[i % key_length]) - ord('A')
encrypted_char = chr((ord(char) - ord('A') + shift) % 26 + ord('A'))
ciphertext += encrypted_char
else:
ciphertext += char
return ciphertext
victory_key = "WANGDINGCUP"
victory_encrypted_flag = victory_encrypt(flag, victory_key)
p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
h = 1
zero = (0,0)
dA = nextprime((0, n))
if dA > n:
print("warning!!")
def addition(t1, t2):
if t1 == zero:
return t2
if t2 == zero:
return t2
(m1, n1) = t1
(m2, n2) = t2
if m1 == m2:
if n1 == 0 or n1 != n2:
return zero
else:
k = (3 * m1 * m1 + a) % p * (2 * n1 , p) % p
else:
k = (n2 - n1 + p) % p * ((m2 - m1 + p) % p, p) % p
m3 = (k * k % p - m1 - m2 + p * 2) % p
n3 = (k * (m1 - m3) % p - n1 + p) % p
return (int(m3),int(n3))
def multiplication(x, k):
ans = zero
t = 1
while(t <= k):
if (k &t )>0:
ans = addition(ans, x)
x = addition(x, x)
t <<= 1
return ans
def getrs(z, k):
(xp, yp) = P
r = xp
s = (z + r * dA % n) % n * (k, n) % n
return r,s
z1 = (0, p)
z2 = (0, p)
k = (0, n)
P = multiplication(G, k)
hA = multiplication(G, dA)
r1, s1 = getrs(z1, k)
r2, s2 = getrs(z2, k)
print("r1 = {}".format(r1))
print("r2 = {}".format(r2))
print("s1 = {}".format(s1))
print("s2 = {}".format(s2))
print("z1 = {}".format(z1))
print("z2 = {}".format(z2))
key = sha256(long_to_bytes(dA)).digest()
cipher = (key, AES.MODE_CBC)
iv =
encrypted_flag = (pad(victory_encrypted_flag.encode(), AES.block_size))
encrypted_flag_hex = (iv + encrypted_flag).decode('utf-8')
print("Encrypted flag (AES in CBC mode, hex):", encrypted_flag_hex)
# output
# r1 = 11455446275324978121918764201975007376236576456980676251003353868423934779741
# r2 = 11455446275324978121918764201975007376236576456980676251003353868423934779741
# s1 = 40939314972385973234538799073526528418921185412931089406906904671430814294251
# s2 = 20521265832237322311837491925934175279870547563516618597235100170259508682349
# z1 = 86373733089658748931377346977504497606857910789811212034370600969224209571891
# z2 = 114906325375159287808320541183977807561041047925384600130919891200501605749979
# ('Encrypted flag (AES in CBC mode, hex):', u'57608ba208813e738e7a354399e77272017548f9abf0da7a179a1136cda57579720b68a3ed46d85f5997c35af18f42175f43e856a0f64d964e7ab1e8a672b689')
Thoughts:
**Direct torture ai**
First find, dA
k = ((z1 - z2) * inverse(s1 - s2, n)) % n
# print(k)
dA = ((s1 * k - z1) * inverse(r1, n)) % n
# print(dA)
Next, we decrypt it using the AES key and CBC modeencrypted_flag
:
from import AES
from import unpad
import binascii
# declassification AES encrypted flag
encrypted_flag_hex = '57608ba208813e738e7a354399e77272017548f9abf0da7a179a1136cda57579720b68a3ed46d85f5997c35af18f42175f43e856a0f64d964e7ab1e8a672b689'
iv_and_encrypted_flag = (encrypted_flag_hex)
iv = iv_and_encrypted_flag[:16]
encrypted_flag = iv_and_encrypted_flag[16:]
cipher = (key, AES.MODE_CBC, iv=iv)
decrypted_flag = unpad((encrypted_flag), AES.block_size)
The final step is to decrypt the victory password. Since the victory password is a simple multi-table substitution password, we only need to reverse the encryption process to decrypt it:
def victory_decrypt(ciphertext, key):
key = ()
key_length = len(key)
plaintext = ''
for i, char in enumerate(ciphertext):
if ():
shift = ord(key[i % key_length]) - ord('A')
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
plaintext += decrypted_char
else:
plaintext += char
return plaintext
# Decrypting the Victory Code
victory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(decrypted_flag.decode(), victory_key)
print("Decrypted flag:", decrypted_flag)
Full exp:
from import *
import gmpy2
from hashlib import sha256
p = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc2f
a = 0
b = 7
xG = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
yG = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
G = (xG, yG)
h = 1
zero = (0,0)
r1 = 11455446275324978121918764201975007376236576456980676251003353868423934779741
r2 = 11455446275324978121918764201975007376236576456980676251003353868423934779741
s1 = 40939314972385973234538799073526528418921185412931089406906904671430814294251
s2 = 20521265832237322311837491925934175279870547563516618597235100170259508682349
z1 = 86373733089658748931377346977504497606857910789811212034370600969224209571891
z2 = 114906325375159287808320541183977807561041047925384600130919891200501605749979
c = ' 57608ba208813e738e7a354399e77272017548f9abf0da7a179a1136cda57579720b68a3ed46d85f5997c35af18f42175f43e856a0f64d964e7ab1e8a672b689'
k = ((z1 - z2) * inverse(s1 - s2, n)) % n
# print(k)
dA = ((s1 * k - z1) * inverse(r1, n)) % n
# print(dA)
key = sha256(long_to_bytes(dA)).digest()
print(key)
# Decrypt aes
from import AES
from import unpad
import binascii
# Decrypt AES encrypted flag
encrypted_flag_hex = ' 57608ba208813e738e7a354399e77272017548f9abf0da7a179a1136cda57579720b68a3ed46d85f5997c35af18f42175f43e856a0f64d964e7ab1e8a672b689'
iv_and_encrypted_flag = (encrypted_flag_hex)
iv = iv_and_encrypted_flag[:16]
encrypted_flag = iv_and_encrypted_flag[16:]
cipher = (key, AES.MODE_CBC, iv=iv)
decrypted_flag = unpad((encrypted_flag), AES.block_size)
def victory_decrypt(ciphertext, key).
key = ()
key_length = len(key)
plaintext = ''
if ().
shift = ord(key[i % key_length]) - ord('A')
decrypted_char = chr((ord(char) - ord('A') - shift) % 26 + ord('A'))
plaintext += decrypted_char
else: plaintext += char
plaintext += char
return plaintext
# Decrypt the victory code
victory_key = "WANGDINGCUP"
decrypted_flag = victory_decrypt(decrypted_flag.decode(), victory_key)
# Convert to lowercase
print("Decrypted flag:", decrypted_flag.lower())
flag: wdflag{8ed62e3b409bb214e6fdb0a78f63569c}
Misc
MISC01
Description:
A unit of the network was illegally attacked, security personnel on the flow of investigation and forensics after the preservation of key evidence, found that the personnel's location information has been leaked, please analyze it. flag 32-bit md5 hash for the user's location information
Format of submitted flags: wdflag
Study:Diameter Protocol Summary - StevensFollower - Blogland
Diameter Protocol - CSDN Blog
Thoughts:
Analyzing the traffic packet reveals a diameter protocol analysis. filter diameter first.
And then going down to the AVP where one of the messages indicates the geographic location.
You can see that E-UTRAN-Cell-Global-Identit is the val, which means the leaked information, so you can copy it out and throw it to chat to analyze it.
Just encrypt it with md5 at the end.
flag: wdflag{0d1e868390ea06522d2c9f04c7ade736}
MISC03
Title:
Recently, a company server was maliciously attacked, then the company immediately on the traffic monitoring system suffered an attack on the time of the traffic forensics, but the company a network security trainee to analyze the traceability did not find the attacker's attack on the IP, so the company decided to re-task this to the more experienced you to carry out the work after taking over the work, you immediately carry out an in-depth investigation of it!
Format of submitted flags: wdflag
Analyzing the packets, filtering the http streams, and looking at the 200 return packets, we can see that this is a malicious operation.
ip 39.168.5.60
flag: wdflag{39.168.5.60}
MISC04
IrisCTF-2024-Challenges/peanoscramble at main · IrisSec/IrisCTF-2024-Challenges
IrisCTF2024 | 1r0ny
(Piano) Curve[Fractal Geometry] (Piano) Curves - Knowledgeable
Presumably it should be scripted to restore the pixels to their original positions according to the trajectory of the curve
exp:
from PIL import Image
from tqdm import tqdm
def peano(n):
if n == 0:
return [[0,0]]
else:
in_lst = peano(n - 1)
lst = in_lst.copy()
px,py = lst[-1]
([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
([px + i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
([px + 1 + i[0], py - i[1]] for i in in_lst)
px,py = lst[-1]
([px - i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
([px + i[0], py - 1 - i[1]] for i in in_lst)
px,py = lst[-1]
([px + 1 + i[0], py + i[1]] for i in in_lst)
px,py = lst[-1]
([px - i[0], py + 1 + i[1]] for i in in_lst)
px,py = lst[-1]
([px + i[0], py + 1 + i[1]] for i in in_lst)
return lst
order = peano(6)
img = ('')
width, height =
block_width = width # // 3
block_height = height # // 3
new_image = ("RGB", (width, height))
for i, (x, y) in tqdm(enumerate(order)):
# Get new coordinates according to the order of the list
new_x, new_y = i % width, i // width
# Get original pixel
pixel = ((x, height - 1 - y))
# Placing pixels in a new image
new_image.putpixel((new_x, new_y), pixel)
new_image.save("rearranged_image.jpg")
flag: wdflag{793a67fd-58b2-4267-860a-b94ca4842761}
Reverse
REVERSE01
An Android reverse question to analyze the main program
A so file is loaded
Reverse the so program.
Found sm4 encryption in sub_940, key is 16 bytes.
The second half of the key
key:A11223574689900Z
extract a ciphertext
85FCBC1D8A32907CB6CACAAAA9109957E38C80651EADF138C3FE849A62DA68B36EFF51FCD8B69FEB7AE0738619A4CA13
flag: wdflag{f28268d3-35b2-4d43-bdeb-a03ad186346a}
REVERSE02
Thoughts:
Check the shell, then use ida64 to open it, analyze the main function, split the flag into 4 segments, explained in the comments
It's straightforward to decrypt the base64 table and trace the base64_encode function to the
exp:
# first paragraph
s2 = [0x70, 0xC2, 0x6C, 0xCA]
s1 = [ord(c) for c in "nppl"]
s = s2 + s1
dest = [s[i] // 2 for i in range(8)]
flag1 = ''.join(chr(i) for i in dest)
print('flag1 = ', flag1)
# second paragraph
# define v11 cap (a poem) v22
v11 = [ord('9'), ord('['), 23, 16, 127, 13, 71, 6]
v22 = [ord(c) for c in "XorrLord"]
# initialization dest arrays
dest = [0] * 8
flag2 = []
for i in range(8):
for j in range(1, 128):
if j ^ v22[i] == v11[i]:
(j)
break
# count dest thirteenth meeting of the Conference of the Parties to the Convention on Biological Diversity (CBD)8up to the eighth (of a series of)15individual element
# for j in range(8):
# dest[j] = v11[j - 8] ^ v22[j - 8]
# print("dest =", ''.join(chr(i) for i in dest))
flag2 = ''.join(chr(i) for i in flag2)
print('flag2 = ', flag2)
# third paragraph
import base64
import string
str1 = "PVLlQVPhPFW"
string1 = "CDEFGHIJKLMNOPQRSTUVWXYZABabcdefghijklmnopqrstuvwxyz0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
# Convert String
translated_str = ((string1,string2))
# because of Base64 Decode Add Fill
padding_needed = len(translated_str) % 4
if padding_needed:
translated_str += '=' * (4 - padding_needed)
# Decode and print results
try:
flag3 = base64.b64decode(translated_str).decode()
print("flag3 = ", flag3)
except Exception as e:
print("decoding error:", e)
# fourth paragraph
from import AES
key = b"AesMasterAesMast"
c = [0xA7, 0x20, 0x15, 0xFF, 0xCD, 0xF4, 0x50, 0xDE, 0x78, 0xBE, 0xA7, 0x94, 0x7F, 0xBF, 0xAC, 0xC5]
cipher = (key, AES.MODE_ECB)
flag4 = (bytes(c)).decode()
print("flag4 = ", flag4)
flag = flag1 + flag2 + flag3 + flag4
print("flag = ", "wdflag{" + flag )
print(len(flag))
flag: wdflag{8a6e7886a4eb3b5b52e93a4506d28a04}