PicoCTF 2023

Crypto

ReadMyCert

Challenge cho một file đuôi .csr chúng ta cần đọc file đó để tìm được flag.Dưới đây là đoạn code đọc file .csr bằng python

script.py

from OpenSSL import crypto


with open('readmycert.csr', 'rb') as f:
    csr_data = f.read()


csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_data)


print("CSR subject: ", csr.get_subject())
print("CSR public key: ", csr.get_pubkey())

Flag: picoCTF{read_mycert_4448b598}

Rotation

encrypt.txt

xqkwKBN{z0bib1wv_l3kzgxb3l_4i3lkj4k}

Khi quan sát thấy chuỗi encrypt có định dạng giống flag nhưng chỉ khác kí tự.Mình đoán đấy là một loại mật mã thay thế.Cụ thể là ROT13 dịch chuyển 18 kí tự
decode bằng cyber chef

Flag: picoCTF{r0tat1on_d3crypt3d_4a3dcb4c}

HideToSee


Challenge cho file ảnh atbash.jpg
Vì hint là extract file ảnh nên mình thử extract bằng exiftool,binwalk nhưng không được.Đến khi thử dùng stegseek thì thành công.
Extract bằng stegseek sau đó decode bằng atbash-cipher

Đoạn mã thu được là một loại mã hóa tên là atbash trùng với tên file ảnh.

Flag: picoCTF{atbash_crack_ca00558b}

SRA

Challnge cho đoạn code

from Crypto.Util.number import getPrime, inverse, bytes_to_long
from string import ascii_letters, digits
from random import choice

pride = "".join(choice(ascii_letters + digits) for _ in range(16))
gluttony = getPrime(128) 
greed = getPrime(128)
lust = gluttony * greed
sloth = 65537
envy = inverse(sloth, (gluttony - 1) * (greed - 1))

anger = pow(bytes_to_long(pride.encode()), sloth, lust)

print(f"{anger = }")
print(f"{envy = }")

print("vainglory?")
vainglory = input("> ").strip()

if vainglory == pride:
    print("Conquered!")
    with open("/challenge/flag.txt") as f:
        print(f.read())
else:
    print("Hubris!")

Quan sát đoạn code có vẻ giống loại mật mã RSA.Chúng ta hay cùng tổng hợp lại một chút.

p = gluttony
q = greed
n = lust = p*q
e = sloth = 65537
phi(n) = envy
c = anger

Phân tích bài toán ta thấy challenge cho e,c,d mà không biết n.Vì vậy ta cần tìm n từ e và d.Có một bài viết nói về điều này .
Khi nc tới máy chủ ta có được c ,d cùng với e mặc định bằng 65537

c = 55741649401010274818307845605092679008667616413355244947750414224114746208832
d = 74333584447180894103145403792590710950534075890992511958613172332631940860353
e = 65537
e*d-1 = 4871600123914894256837840328355017423565151731667976256231631475163699508164954560

Ta đi phân tích e*d-1 thành các số nguyên tố. Có nhiều trang web để factor . Ở đây mình sử dụng website này

[5164281078969082913193808065574117,353365039597,69171677,15863401,113081,3581,1907,71,71,31,7,5,3,3,2,2,2,2,2,2]

Từ tập hợp các số factor này ta có thể xây dựng một tập hợp các số nguyên tố 128 bits.Vì p,q có kích thước 128 bit. Từ đó ta sẽ chọn từng cặp 2 số trong tập hợp mảng các số nguyên tố 128 bits gán cho p ,q và dựng lại bài toán RSA nếu tính ra được số mũ giải mã d bằng với số mũ d của challenge cho thì p,q chúng ta tìm được là chính xác.Sau đó dễ dàng tìm được chuỗi plaintext để get flag.
Các bước cụ thể :
Từ tập hợp các số factor của ed-1 ta tạo các tập hợp con với n phân tử .Trong python có hàm combinations giúp chúng ta làm điều này .Ví dụ array = [1,2,3] tạo mảng các mảng con 2 phần tử , combinations(array,2) sẽ trả về [(1,2),(1,3),(2,3)]
Trong bài, ta sẽ sử dụng đối với mảng các số factor và n là độ dài mảng giảm dần để thử từng trường hợp.Từ từng tập hợp con này ta sẽ tính tích của tất cả các phần tử sau đó check số bit của kết quả. Nếu kết quả này nằm trong khoảng 124 -> 129 bits thì tiến hành tăng từng bit .Khi số đó nằm trong khoảng 127-129 bits,tức là số này là một số 128 bits (lấy trong khoảng này vì khi lấy log2 một số 128 bit có thể lệch trên hoặc lệch dưới nửa bit ,các số ngoài khoảng này không phải là số 128 bit).Nếu số 128 bit này là số nguyên tố thì thêm vào mảng các số nguyên tố 128 bit của chúng ta.

for combin in factorCombins:
        u = math.prod(combin)
        bitsU = math.log2(u)
        if 124<= bitsU <= 129:
            p = u << 1 
            p = p + 1          
            bitsP = math.log2(p)
            if 127<= bitsP <= 129:
                isPrime =  sympy.isprime(p)
                if isPrime :
                    if p not in primeArray:
                        print(f"{p = }")
                        primeArray.append(p)

Sau nhiều lần thử các tập hợp con như vậy ,kết quả thu được là một mảng gồm các số nguyên tố 128 bit. Ta sẽ chọn theo từng cặp với nhau gán cho p,q và xây dựng lại bài toán RSA ,tính phi_n ,số mũ giải mã d .Nếu có trường hợp số mũ d này bằng với số mũ d của challenge cho thì chúng ta thành công.

pairs = get_combinations(primeArray,2)

for pair in pairs :
    p = pair[0]
    q = pair[1]
    n = p*q
    phi_n = (p-1)*(q-1)
    combined_d = inverse(e,phi_n)
    if combined_d == d:
        print("OK")
        plaintext = long_to_bytes(pow(c,d,n))
        print(f"{plaintext = }")

Full code

import math
import sympy
from itertools import combinations
from Crypto.Util.number import  inverse, bytes_to_long, long_to_bytes

def get_combinations(arr, n):
    return [list(c) for c in combinations(arr, n)]

c = 55741649401010274818307845605092679008667616413355244947750414224114746208832
d = 74333584447180894103145403792590710950534075890992511958613172332631940860353
e = 65537 

factorNum = e*d-1
print(f"{factorNum = }")

factorArray = [5164281078969082913193808065574117,353365039597,69171677,15863401,113081,3581,1907,71,71,31,7,5,3,3,2,2,2,2,2,2]
arrayLen = len(factorArray)
print(f"{arrayLen = }")

n = arrayLen + 1
primeArray = []
i = 0
while i < arrayLen:
    n = n-1
    factorCombins = get_combinations(factorArray,n)
    for combin in factorCombins:
        u = math.prod(combin)
        bitsU = math.log2(u)
        if 124<= bitsU <= 129:
            p = u << 1 
            p = p + 1          
            bitsP = math.log2(p)
            if 127<= bitsP <= 129:
                isPrime =  sympy.isprime(p)
                if isPrime :
                    if p not in primeArray:
                        print(f"{p = }")
                        primeArray.append(p)
    i = i + 1

print(primeArray)
pairs = get_combinations(primeArray,2)

for pair in pairs :
    p = pair[0]
    q = pair[1]
    n = p*q
    phi_n = (p-1)*(q-1)
    combined_d = inverse(e,phi_n)
    if combined_d == d:
        print("OK")
        plaintext = long_to_bytes(pow(c,d,n))
        print(f"{plaintext = }")

Sau khi run script thu được output


Điền vào terminal và get flag

Flag: picoCTF{7h053_51n5_4r3_n0_m0r3_2b7ad1ae}

General Skill

chrono

ssh tới server

Crontab là một tiện ích trong các hệ điều hành giống Unix cho phép người dùng lên lịch để các tác vụ chạy tự động theo các khoảng thời gian được chỉ định.

repetitions


Challenge cho 1 đoạn cipher base64

VmpGU1EyRXlUWGxTYmxKVVYwZFNWbGxyV21GV1JteDBUbFpPYWxKdFVsaFpWVlUxWVZaS1ZWWnVh
RmRXZWtab1dWWmtSMk5yTlZWWApiVVpUVm10d1VWZFdVa2RpYlZaWFZtNVdVZ3BpU0VKeldWUkNk
MlZXVlhoWGJYQk9VbFJXU0ZkcVRuTldaM0JZVWpGS2VWWkdaSGRXCk1sWnpWV3hhVm1KRk5XOVVW
VkpEVGxaYVdFMVhSbGhhTTBKWVZXeG9RMlZXV2tkWGJYUlVDbUY2VmtoWmEyaEhWMGRHZEdWRlZs
aGkKYlRrelZERldUMkpzUWxWTlJYTkxDZz09Cg==

Decode bằng Cyberchef

Flag: picoCTF{base64_n3st3d_dic0d!n8_d0wnl04d3d_a2d1b8b6}

Rules 2023


Flag: picoCTF{h34rd_und3r5700d_4ck_cba1c711}

money-ware

Flag: picoCTF{Petya}

Permissions



Flag: picoCTF{uS1ng_v1m_3dit0r_3dd6dcf4}

Forensics

PcapPoisoning

Flag: picoCTF{P64P_4N4L7S1S_SU55355FUL_f621fa37}

hideme


extract ảnh bằng binwalk:

Flag: picoCTF{Hiddinng_An_imag3_within_@n_ima9e_96539bea}