Location>code7788 >text

The 4th "NetDynasty Cup" Cyber Security Competition - Qinglong Group

Popularity:251 ℃/2024-10-30 11:00:51

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()  

image-20241029095622-3r1ouci

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**

image-20241029114422-mbrxlv2

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.

image-20241030102311-fyx5frn

And then going down to the AVP where one of the messages indicates the geographic location.

image-20241030103034-ebm4tku

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.

image-20241030103151-cm2jiou

image-20241030103524-xrmghzb

Just encrypt it with md5 at the end.

image-20241030103703-ivhvrs2

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

image-20241029142431-hd5m3g9

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")

rearranged_image-20241029160335-fx3c03o

image-20241029160349-pgmzxeu

flag: wdflag{793a67fd-58b2-4267-860a-b94ca4842761}

Reverse

REVERSE01

An Android reverse question to analyze the main program

image-20241029142921-3lojd4d

A so file is loaded

image-20241029142951-k615sla

Reverse the so program.

image-20241029143205-9z7wj3c

Found sm4 encryption in sub_940, key is 16 bytes.

image-20241029143949-04lubql

The second half of the key

key:A11223574689900Z

image-20241029143726-vfrqvav

extract a ciphertext

image-20241029144116-gc51y4q

85FCBC1D8A32907CB6CACAAAA9109957E38C80651EADF138C3FE849A62DA68B36EFF51FCD8B69FEB7AE0738619A4CA13

image-20241029144321-ikpicyj

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

image-20241029133453-a5f6qxr

image-20241029133514-igja4qn

It's straightforward to decrypt the base64 table and trace the base64_encode function to the

image-20241029133609-ariawk2

image-20241029133617-95e72zt

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}