WannaShare | Writeups ASIS CTF Quals 2022 | Crypto + Pwn + Rev + Forensics

PHAPHA_JIàN
14:20 21/10/2022

CLB An toàn Thông tin Wanna.W^n chia sẻ một số Challenges giải được và việc chia sẻ writeup nhằm mục đích giao lưu học thuật. Mọi đóng-góp ý-kiến bọn mình luôn-luôn tiếp nhận qua mail: wannaone.uit@gmail.com hoặc inseclab@uit.edu.vn và fanpage: fb.com/inseclab Cám ơn các thành viên Wanna.W^N @InSecLab đã đóng góp: @vnc @EnKai @AstroKlock @Jinn @PkNova @toom @th3_bl1nd3r

Crypto

Binned

Description

People binned to the same public ID have no real-world connection to one another.

Solution

Ở bài này đại khái chúng ta sẽ đi giải phương trình

với n, c là các số cho trước, flag là x cần tìm. Cơ số (1 + n) gợi ý chúng ta khai triển Newton...

Như vậy ta đã có một phương trình đồng dư với ẩn là flag, tuy nhiên do n khá lớn so với flag nên ta có thể giải được trên ZZ luôn (thay vì Zmod(n^3))

Code mình để ở đây

Flag: ASIS{8!N0miaL_3XpAn5iOn_Us4G3_1N_cRyp7o_9rApHy!}


Chaffymasking

Description

Chaffy masking is a popular cryptography technique that is used to protect cryptographic implementations against several attacks.

Solution

Đại khái bài này mình nhập vô một chuỗi bất kì sau đó nó sẽ kiểm tra và pad cái chuỗi mình nhập cho đủ 128 bytes. Tiếp theo nó chia cái chuỗi làm 2 phần bằng nhau và thực hiện hàng loạt các bước tính toán để sinh ra 2 vector key1 và key2, cuối cùng kết quả trả về sẽ là flag xor key1 xor key2.

Điều "bất thường" ở bài này là nếu ta nhập chuỗi ban đầu có độ dài đúng bằng 128 và khi chia chuỗi đó làm đôi thì ta được 2 chuỗi khác nhau. Lúc này ta sẽ loại bỏ được các phần random padding lúc check length mà hoàn toàn tự implement để gen ra hai cái key1 và key2 lúc này chỉ việc xor ngược lại là ra flag thôi =))

Code mình để ở đây

FLag: ASIS{Lattice_based_hash_collision_it_was_sooooooooooooooo_easY!}


Mariana

Description

Mariana works in the areas of cryptography and security. But some flaws exists in her work!

Solution

Bài này bắt chúng ta giải phương trình

với p là số nguyên tố, g bất kì trong khoảng (3, p). Nhiệm vụ của ta là tìm x và pass qua 40 rounds (sau mỗi round p sẽ tăng dần) để lấy flag. Sau một hồi lựa chọn thì thật bất ngờ mình thấy 1 họ nghiệm thỏa yêu cầu đề đơn giản như sau

Một vấn đề nho nhỏ là nếu tính crt([1, g], [p - 1, p]) thì kết quả sẻ lớn hơn p, nhưng đề chỉ giới hạn x < p chứ không quan tâm cận dưới của x nếu lúc nay chỉ việc "dịch xuống" 1 bậc: x = crt([1, g], [p - 1, p]) - p(p - 1) là sẽ thỏa!

Code mình để ở đây

Flag: ASIS{fiX3d_pOIn7s_f0r_d!5Cret3_l0g4riThmS!}


Mindseat

Description

Cryptography Mindset: Be Unpredictable, build robust and stable applications where you'll handle every situation that user can face or predict.

Solution

Ý tưởng bài này như sau: đầu tiên chia flag thành 4 phần, mỗi phần 8 bytes, sau đó encrypt từng phần như sau:

Đầu tiên ta sẽ tìm cách khôi phục số k...

ở đây ta thấy k sẽ là số mũ đúng mod 2 của n - 1 nếu a + b lẻ. Vì a, b chọn ngẫu nhiên và ta có tới 4 bộ pubkey nên khả năng cao sẽ có 1 bộ mà a + b lẻ, từ đó ta khôi phục được k = 134

Một cách tự nhiên ta sẽ quan tâm tới đại lượng phi(n)...

ở đây ta đã có k vậy thử tìm ab xem...

tới đây ngon rồi!!! Ta đã có thể tính được phi(n) kết hợp với n ta hoàn toàn tìm được p, q. Vậy ta đã xử lý được phần pubkey, bây giờ tìm cách decrypt nữa là xong...

Ở đây r là một số random bất kì, chúng ta không biết. Vậy suy nghĩ một cách tự nhiên là chúng ta sẽ tìm cách loại bỏ r và chuyển sang giải DLP thoy...

Xong rồi, viết script lấy flag hoyyy!!! Mình đề code ở đây

Flag: ASIS{N3w_CTF_nEW_Joye_Libert_CrYpt0_5}


Pwn

babyscan_2

Bug:

Idea:

Sources


Revsersing

Figole

Description

This recipe for Figole, by ASIS, is from APK is a Full Android, one of the codebooks created in Android. We’ll help you start your own personal codebook! It’s easy and fun. Trong lúc làm bài này không hiểu sao mình bị thao túng tâm lí :))), bị nó lừa nên là mất thời gian khá nhiều mới có thể fix. Ah mình ngu quá…

Đề cho mình 1 file apk, thử mở bằng jadx

Đầu tiên mình chỉ xem mỗi class MainActivity mình nghĩ nó là luồng thực thi chính của chương trình, nhưng không…

Lúc mình chưa nhận ra mình làm sai chổ nào mà không ra flag thì xem lại mainfest mới biết là DActivity mới là luồng thực thi chính. Đấy mình bị lừa chổ này thôi, phần còn lại của bài rev khác là dễ.

Đối với bài này không cần cài đặt mà chúng ta chỉ cần chú ý vào hàm main, có thể thấy đây là một bài check flag bình thường.

Đầu tiên nó lấy và 2 chuỗi qy, sau đó input text của mình sẽ được đem xử lí cùng q và so sánh với y.

qy lần lượt lấy từ l2()l1()

Về l1() có thể thấy nó gọi 1 method khác có tên là gf()

gf() sẽ gọi gd(), có thể thấy nó lấy chuỗi đầu tiên từ database tên calibri.

Tìm file calibri.ttf, đổi đuôi file thành .db và mở bằng SQLite ta có 2 chuỗi như sau:

Ta có base64 sẽ là yvà tương tự với l2(), chuỗi còn lại sẽ là q

Trước khi gọi l3(), q được xử lí qua cdec(), cdec() chỉ là xor q với “key”.

Còn về l3() sẽ gọi method có tên là ech()

ech() sẽ cộng q với 1 chuỗi sau khi được decode bằng base64, và xử lí bằng getK(), getK() sẽ sẽ trả về chuỗi ở vị trí chẳn để làm key, còn chuỗi ở vị trí lẻ sẽ làm IV, sau đó trả về kết quả là base64 và so sánh với y. Tới đây có vẻ mọi thứ đã rõ ràng, mình dùng script này để decode flag:

from Crypto.Cipher import AES
import base64
from pwn import *
y = base64.b64decode(b'7mePfqpM6Wd1El2sj4dlUboU6PieF7La8IJ1e76cfp4=')
k = b"key"
x = base64.b64decode(b'Mzg2OTM3NjEzNDc0MzYzMTM1MzUzMjM2MzMzMjMxMzA=').decode()
q = '58504e58564f5d504a59534a58544e59564d5d504a5e524d585c4f5a564f5c57'
getK = bytes.fromhex(xor(bytes.fromhex(q),k).decode() + x)
key = []
iv = []
for i in range(len(getK)):
    if i%2==0:
        key.append(getK[i])
    else:
        iv.append(getK[i])
key =bytes(key)
iv = bytes(iv)
cipher = AES.new(key,AES.MODE_CBC,iv[:16])
plaintext = cipher.decrypt(y)
print(plaintext)
#b'ASIS{D3x_iZ_n0t_fOn7!}\n\n\n\n\n\n\n\n\n\n'

Bài này làm mình mất thời gian ở chổ phân tích sai class với lại IV và Key mình đều tính ra là length = 24 cho nên mình nghĩ là sai chổ này, ai ngờ là sai flow chương trình, xem như qua bài này mình cần cẩn thận hơn, tìm hiểu kĩ hơn và bình tĩnh giải quyết.


traditional

Flow của chương trình:

* Nội dung trong file flag.txt sẽ được đọc và encode base64 
* Nối b64encodedFlag với s1 = “This is the flag: ”, và s2= “ Just decode it :P” để tạo thành s = s1 + b64encodedFlag + s2
* Sau đó encode s bằng hàm tạm gọi là blackbox function (ở đây, nhìn pseudo code khá rối nên mình không xác định được thuật toán encode), được encodedStr
* encodedStr sẽ được thực hiện base64decode trước khi ghi mảng byte kết quả vào file flag.enc

Mục tiêu của mình là xác định được blackbox function.

Tại đây, mình có thể cheat bằng cách thay thế s bằng alphabet của base64 trước khi đi qua hàm blackbox function và check string trả về từ hàm này, mình nhận ra:

* Ký tự lower sẽ được shift left 19
* Ký tự upper sẽ được shift left 14
* Ký tự số sẽ được shift left 5
lower = list(b'abcdefghijklmnopqrstuvwxyz')
shift19_lower = list(b'tuvwxyzabcdefghijklmnopqrs')
upper           =   list(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
shift14_upper   =   list(b'OPQRSTUVWXYZABCDEFGHIJKLMN')
num= list(b'0123456789')
shift5_num  = list(b'5678901234')
cip = list(b'4TrGsT5ByJKBrJdwsW6LdBRxq57L8IeMyBRHp6IGsm8IXBJE')
import string
a = [0 for i in range(len(cip))]
for i in range(len(cip)):
    if cip[i] < (65  + 26) and cip[i] >= 65:
        ind = shift14_upper.index(cip[i])
        a[i]= upper[ind]
    elif cip[i] < 58 and cip[i] >= 48:
        ind = shift5_num.index(cip[i])
        a[i]= num[ind]
    elif cip[i] < (97  + 26) and cip[i] >= 97:
        ind = shift19_lower.index(cip[i])
        a[i]= lower[ind]
    else:
        print("error")
# print(a)
import base64
a1 = bytes(a)[::-1]
# print(a1)
print(base64.b64decode(a1))

Sources


Forensics

Wormrep

The challenge gave me a .klr.enc1 file, after digging for a few minutes, I found out that was an encoded scan report from Kasersky Virus Removal Tool.

So I downloaded KVRT, but before running it, I had to know how the tool reads the report file. Thanks to the support page I had to rename the challenge file and put it in C:\KVRT2020\Data\Reports Openning KVRT and go to report tab, sifted through the report, I found the flag.

Stacked QRs

Challange gave me an image: According to the description, no important part of QRs is damaged, that must mean only the position markers were overlapped.

After examining many QR codes that were mostly intact, I could safely assume the QRs had a dimension of 210x210 and the gaps between the QRs were 70 pixels.

I made a script to easily sift through the qr codes before fixing them

import cv2
img = cv2.copyMakeBorder(cv2.imread('stacked_qrs.png'), 0, 40, 0, 40, cv2.BORDER_CONSTANT, None, [255,255,255])
export = []
x, y = 0, 0
print(img.shape)
# cv2.imshow("original", img)
# cv2.waitKey(0)
for row in range(14):
    x = 0
    for column in range(14):
        crop = img[y:y+210,x:x+210]
        cv2.imshow("cropped", crop)
        key = cv2.waitKey(0)
        if(key == ord('s')):
            export.append(cv2.copyMakeBorder(crop,0,0,0,20,cv2.BORDER_CONSTANT, None, [255,0,128]))
        x += 70
    y+=70
concat_img = cv2.hconcat(export)
cv2.imwrite('.\\export.png',concat_img)
cv2.imshow('test',concat_img)
cv2.waitKey(0)

Got the QRs Fixed them. All I need to do is scan them


Compoti

Challenge gave me a .raw file. After examining the file further, it was a reiser file system.

Using rdrreiser, I could restore some files.

flag.txt was just a red herring. The other 2 files were Portable Gray Map Image, one was ASCII version and the other was binary version.

Looking inside the .pmg file, I could see comments and the file’s width, height and max gray value were changed to 0.

I could replace the number 0 from the comment into spaces, and 9 from the image into spaces and still get the message

OR I could edit the width, height and the max grey value then open the file in GIMP.

Decrypt with the key gave me the flag.

TIN LIÊN QUAN
Trong bài viết này, CLB Wanna.W^n sẽ hướng dẫn các bạn cách sử dụng nền tảng wannaGame với các bước thực hiện như sau: Đăng ký tài khoản Bước 1: Truy cập đường dẫn nền tảng wannaGame: https://cnsc.uit.edu.vn/ctf/ Bước 2: Chọn nút Register Bước 3: Tại màn hình đăng ký,...
CLB An toàn Thông tin Wanna.One chia sẻ một số Challenges giải được và việc chia sẻ writeup nhằm mục đích giao lưu học thuật. Mọi đóng-góp ý-kiến bọn mình luôn-luôn tiếp nhận qua mail: wannaone.uit@gmail.com hoặc inseclab@uit.edu.vn và fanpage: fb.com/inseclab Web @AP DISCO PARTY @AP GITFILE EXPLORER @AP miniblog++...
Cookie Arena được tổ chức bởi Cookie Hân Hoan, một tổ chức giáo dục nhằm phổ biến kiến thức an ninh mạng đến với cộng đồng bằng sự đồng cảm, tươi vui và hài hước. "Xin chào, mình là Gấu aka th3_5had0w đến từ Wanne.One, với tư cách là á...