---
# System prepended metadata

title: picoCTF2024
tags: [writeup]

---

# picoCTF2024 writeups
JMGSH y1w3n
||有空打打而已沒啥分，後續也有空會補齊||
![image](https://hackmd.io/_uploads/HkTppH3RT.png)
## Web Exploitation
### WebDecode
#### 題目說明
![image](https://hackmd.io/_uploads/HJmh07lRp.png)
http://titan.picoctf.net:58480/
#### solve
進去進到about，按``F12``查看網頁原始碼
看到notify_true那邊有cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfMDdiOTFjNzl9
![image](https://hackmd.io/_uploads/ByOQ1VlR6.png)
from base64
![image](https://hackmd.io/_uploads/S1lgOwl0p.png)
#### answer
``picoCTF{web_succ3ssfully_d3c0ded_07b91c79}``
#### note

### Bookmarklet
#### 題目說明
![image](https://hackmd.io/_uploads/S1ZCOwg06.png)
http://titan.picoctf.net:51073/
#### solve
![image](https://hackmd.io/_uploads/rJ1VKve0p.png)
點一下框框內的程式碼，結果他說程式已複製到剪貼簿
:::spoiler 程式
```javascript=
javascript:(function() {
    var encryptedFlag = "àÒÆÞ¦È¬ëÙ£ÖÓÚåÛÑ¢ÕÓÓÇ¡¥Ìí";
    var key = "picoctf";
    var decryptedFlag = "";
    for (var i = 0; i < encryptedFlag.length; i++) {
        decryptedFlag += String.fromCharCode((encryptedFlag.charCodeAt(i) - key.charCodeAt(i % key.length) + 256) % 256);
    }
    alert(decryptedFlag);
})();
    
```
:::
:::success
flag就是``àÒÆÞ¦È¬ëÙ£ÖÓÚåÛÑ¢ÕÓÓÇ¡¥Ì``加密後的內容
key是"picoctf"
反正直接執行程式
:::
![image](https://hackmd.io/_uploads/Sk6_owxRp.png)
[網站](https://jsfiddle.net/)
#### answer
``picoCTF{p@g3_turn3r_0c0d211f}``
### IntroToBurp
#### 題目說明
![image](https://hackmd.io/_uploads/SJNUcxbF1x.png)
http://titan.picoctf.net:50233/
#### slove
> tools: Burp Suite

![image](https://hackmd.io/_uploads/rJNAeMbKkx.png)
隨便輸入點東西後按Register，然後burpsuite 中按forward 把資料送出去
![image](https://hackmd.io/_uploads/SJ0OZG-Ykx.png)
發現之後是要輸入OTP (一次性密碼)
隨邊輸入點東西(我這裡都是輸入'a') 後按Submit，同樣在burpsuite 中按forward 把資料送出去
![image](https://hackmd.io/_uploads/BkMZfzbtyg.png)
出現Invalid OTP，由此可見這題是要bypass OTP
![image](https://hackmd.io/_uploads/B17wQzbKyg.png)
回到上一個步驟，看到當我forward 之前第16行有```otp=a```
把這行刪掉後forward出去
![image](https://hackmd.io/_uploads/HJhBIGZFkl.png)
#### answer
``picoCTF{#0TP_Bypvss_SuCc3$S_6bffad21}``
## Cryptography
### interencdec
#### 題目說明
![image](https://hackmd.io/_uploads/HkGgq_gC6.png)
* 一個文字檔:enc_flag
![image](https://hackmd.io/_uploads/ryPt3PgR6.png)
#### solve
* 看到兩個'=' : base64特徵
![image](https://hackmd.io/_uploads/rkDE6wgAa.png)
* 得到的結果再base64一次(去掉b前綴)
![image](https://hackmd.io/_uploads/rytcTvxAT.png)
* 現在逐漸有flag的樣子了，但字母不對，所以用凱薩去解密，因為凱薩加密是字母位移的加密方式
![image](https://hackmd.io/_uploads/Hk980Dl0p.png)
位移19得到flag
![image](https://hackmd.io/_uploads/Hkk5CDgRp.png)
[網站](https://cryptii.com/)
#### answer
``picoCTF{caesar_d3cr9pt3d_f0212758}``
## Reverse Engineering
### WinAntiDbg0x100
#### 題目說明
![image](https://hackmd.io/_uploads/rJdz9CkTC.png)
>hint: Hints will be displayed to the Debug console. Good luck!

![image](https://hackmd.io/_uploads/rJEDoDA3A.png)
* 執行下來發現他叫我using a debugger
#### slove
* 進到IDA中看看哪裡會輸出flag
* 發現這裡是判斷會不會輸出flag的地方
![image](https://hackmd.io/_uploads/Byo4WIyaA.png)
* 在``` jz short loc_C6161B```設中斷點
* 使用Debugger功能執行
* 會發現直接執行後輸出:
![image](https://hackmd.io/_uploads/HJBoArJaC.png)
* 也就是說沒嘗試bypass不會跳到輸出flag的地方
* 回去看看上面跳轉的條件
![image](https://hackmd.io/_uploads/HJEByLJpA.png)
    * ```call ds:IsDebuggerPresent```: 偵測有沒有debugger存在，沒有的話就return 0
    * ```test eax, eax```: 概念和AND eax,eax差不多，不一樣的是test不會改變eax。==現在我們有使用debugger所以值不為0==
        ![image](https://hackmd.io/_uploads/SJMWQ816C.png)
    * ```jz```: 如果為0則跳轉到輸出flag的地方
* 把eax值改成0
![image](https://hackmd.io/_uploads/BkPPX8yaA.png)
* 成功跳轉，得到答案
![image](https://hackmd.io/_uploads/BkvbNLJa0.png)
#### Answer
``picoCTF{d3bug_f0r_th3_Win_0x100_cc0ff664}``
### WinAntiDbg0x200
#### 題目說明
![image](https://hackmd.io/_uploads/BkByIIJpR.png)
> hints: Hints will be displayed to the Debug console. Good luck!
* 使用管理員權限執行
![image](https://hackmd.io/_uploads/HkecsU1pR.png)
* 跟前一題一樣要用debugger
#### slove
* 一開始有先判斷是否為管理員權限執行
![image](https://hackmd.io/_uploads/By04Vak60.png)
* 先看看哪裡的執行步驟會前往不輸出flag的路線
![image](https://hackmd.io/_uploads/rJ6oVp1pA.png)
    * ```test edx, edx```：測試 edx 是否為零
    * ```jnz short loc_F11832```：如果結果為==非零==，則跳轉到```loc_F11832```
    * ```loc_F11832```: 輸出### Oops! The debugger was detected. Try to bypass
    * ==現在edx為1，1!=0，會前往```loc_F11832```輸出錯誤==
    ![image](https://hackmd.io/_uploads/HykCvaya0.png)
* 修改其值，成功前往下一步
![image](https://hackmd.io/_uploads/r1hSuaJTA.png)
* 繼續往下看發現還有檢查是否在Debugger執行
![image](https://hackmd.io/_uploads/H1hTupk60.png)
    * ```call ds:IsDebuggerPresent```: 回傳值0（如果沒有Debugger）或 1（如果有Debugger）
    * 現在eax值為1
    * ``jz short loc_F11847``: 如果為0則跳轉到輸出flag的地方
* 跟前一題一樣，修改eax暫存器值
![image](https://hackmd.io/_uploads/ByZ-ZAka0.png)
* 得到答案
![image](https://hackmd.io/_uploads/SyQBbCkpA.png)
#### Answer
``picoCTF{0x200_debug_f0r_Win_c6db2768}``
## Forensics
### Scan Surprise
#### 題目說明
給一個壓縮過的challenge.zip裡面有一個QRcode的圖
或者ssh也是得到一樣的東西
![image](https://hackmd.io/_uploads/HJ2Lgue0a.png)
![image](https://hackmd.io/_uploads/BJDjlOxAa.png)
#### solve
用它給的圖上網找QRcode掃描器去看，得到flag
![image](https://hackmd.io/_uploads/Sysk-_eAT.png)
#### answer
``picoCTF{p33k_@_b00_0194a007}``

### CanYouSee
#### 題目說明
![image](https://hackmd.io/_uploads/H1eO5dz06.png)
題目給了一張圖片: ukn_reality
![image](https://hackmd.io/_uploads/HJyc2_f0a.png)
#### solve
使用``nano``文字編輯器打開看圖片詳細的內容
![image](https://hackmd.io/_uploads/ByvzTdM0p.png)
看到裡面長這樣:
![image](https://hackmd.io/_uploads/S1J8pOMR6.png)
有一串base64的內容，拿去解碼
![image](https://hackmd.io/_uploads/BkGqadMC6.png)
得到flag
#### answer
``picoCTF{ME74D47A_HIDD3N_b32040b8}``
### Secret of the Polyglot
#### 題目說明
![image](https://hackmd.io/_uploads/BJBDX1I0a.png)
給一個pdf檔: flag2of2-final.pdf
![image](https://hackmd.io/_uploads/r10p71LC6.png)
只有一半的flag
#### solve
* ``nano  flag2of2-final.pdf`` : 用文字編輯器打開
![image](https://hackmd.io/_uploads/S1784JIAT.png)
看到它其實是個PNG檔
* 把副檔名改成.png
* 得到前半段的flag
    ![image](https://hackmd.io/_uploads/ryyXSy8Ap.png)
* 合併兩段
#### answer
``picoCTF{f1u3n7_1n_pn9_&_pdf_724b1287}``
## General Skills
### Super SSH
#### 題目說明
![image](https://hackmd.io/_uploads/BJX3Oul06.png)
#### solve
照題目說的做就得到flag了
![image](https://hackmd.io/_uploads/H1XMtugRp.png)
#### answer
``picoCTF{s3cur3_c0nn3ct10n_07a987ac}``
#### note
* 輸入密碼的時候它不會顯示出來你打什麼
### Time Machine
#### 題目說明
![image](https://hackmd.io/_uploads/B1TX1ogCp.png)
* challenge
    * message.txt
#### solve
* ``git log`` : 查看提交歷史
![image](https://hackmd.io/_uploads/SkPtyigCT.png)
得到flag
#### answer
``picoCTF{t1m3m@ch1n3_8defe16a}``
#### note
### Commitment Issues
#### 題目說明
![image](https://hackmd.io/_uploads/H1ksG_lCT.png)
* 一個壓縮的資料夾: challenge.zip
#### solve
他說他刪掉了flag所以我用``git log``查看提交歷史
![image](https://hackmd.io/_uploads/BywIrue0a.png)
看到``picoCTF <ops@picoctf.com>``他在3/12創建了flag後又刪掉了
因此用``git show``，顯示指定提交的詳細訊息
![image](https://hackmd.io/_uploads/B1XaI_e0a.png)
#### answer
``picoCTF{s@n1t1z3_cf09a485}``
#### note
* ``git``: 版本控制
[常用指令](https://hellojs-tw.github.io/git-101/cheat-sheet.html)
### Verify
#### 題目說明
![image](https://hackmd.io/_uploads/SJlA4ceCa.png)
* challenge
    * files(資料夾，裡面放了一堆要比對的文件)
    * decrypt. sh
    * checksum.txt
    ![image](https://hackmd.io/_uploads/HyIlI9gC6.png)
#### solve
要找到跟checksum.txt裡面hash值一樣的檔案
* 使用``sha256sum files/* | grep 3ad37ed6c5ab81d31e4c94ae611e0adf2e9e3e6bee55804ebc7f386283e366a4
3ad37ed6c5ab81d31e4c94ae611e0adf2e9e3e6bee55804ebc7f386283e366a4  files/e018b574
``
![image](https://hackmd.io/_uploads/SyR2w5lAp.png)
看到files裡e018b574的文件符合條件

接著用它給的decrypt. sh解密
![image](https://hackmd.io/_uploads/H1MlOcg0T.png)
#### answer
``picoCTF{trust_but_verify_e018b574}``
#### note
* ``sha256sum`` : 驗證文件
    1. 計算文件的校驗和
    2. 跟預期值做比較
* ``file/*`` : file資料夾中所有檔案

### Blame Game
#### 題目說明
![image](https://hackmd.io/_uploads/ry2ylqgAp.png)
給一個壓縮過的challenge.zip裡面有一個message. py
#### solve
* ``git blame <file>`` : 顯示檔案的每一行是在哪個提交中被修改的，並顯示修改者的資訊
![image](https://hackmd.io/_uploads/BkUdW9lAp.png)
得到flag
#### answer
``picoCTF{@sk_th3_1nt3rn_cfca95b2}``
### Collaborative Development
#### 題目說明
![image](https://hackmd.io/_uploads/BkGrJsVR6.png)
給了一個flag. py ，裡面只有一行:``print("Printing the flag...")``就沒了
![image](https://hackmd.io/_uploads/rkZe_mHCT.png)
#### solve
* ``git branch -a``:看可用的分支
    ![image](https://hackmd.io/_uploads/BylEd7rAT.png)
    看到我現在在``main``，然後還有``feature/part-1``、``feature/part-2``、``feature/part-3``這幾個分支
* ``git merge feature/part-1``
    ![image](https://hackmd.io/_uploads/rkq0ZNrCp.png)
    flag.py中有未提交的更改，而合併操作會覆蓋這些更改。
    * 如何解決?
        * ``git checkout -- flag.py`` : 撤銷修改
        * 然後再執行一次``git merge feature/part-1``就好了，現在flag.py長這樣:
        ![image](https://hackmd.io/_uploads/SJ4qmVrCa.png)
* ``git merge feature/part-2``
    ![image](https://hackmd.io/_uploads/BkZVU4SR6.png)
    無法確定身份資訊（作者和提交者）
    * 如何解決?
        * 登入就好www(直接拿人家的XD)
        ![image](https://hackmd.io/_uploads/By6aU4rRa.png)
        *  然後再執行一次``git merge feature/part-2``就好了，現在flag.py長這樣:
        ![image](https://hackmd.io/_uploads/ByDQPVBRa.png)
* ``git merge feature/part-3``
    ![image](https://hackmd.io/_uploads/r1cnv4SR6.png)
    嘗試合併feature/part-3分支時發生了衝突，導致合併無法進行
    * 如何解決?
        * 打開flag. py，看到衝突標記，``<<<<<<< HEAD``、``=======``和``>>>>>>> feature/part-2``表示目前分支（main分支）和要合併的分支（feature/part-2分支）之間有衝突
        ![image](https://hackmd.io/_uploads/Skrzi4S0T.png)
        * 手動把衝突標記刪掉
        ![image](https://hackmd.io/_uploads/r1KKiESRa.png)
        * ``git add flag.py`` : 提交
        * ``git merge --continue`` : 繼續
        * 再執行一次``git merge feature/part-3``就好了，現在flag.py長這樣:
        ![image](https://hackmd.io/_uploads/Bkiz3NBRT.png)
* 已經有flag了但如果想做到完美就把這邊的合併衝突也手動解決掉
    ![image](https://hackmd.io/_uploads/Bylxc3EHRT.png)
* 執行
    ![image](https://hackmd.io/_uploads/rJlCnESC6.png)
#### answer
``picoCTF{t3@mw0rk_m@k3s_th3_dr3@m_w0rk_7ae8dd33}``
#### note
分支是獨立的。使得團隊成員能夠在不互相干擾的情況下並行開發和合作。
### binhexa
#### 題目說明
![image](https://hackmd.io/_uploads/rybcGxMCa.png)
進去之後長這樣
![image](https://hackmd.io/_uploads/rJtIBgfRT.png)
就是它給了兩個二進制數字接著出題要我們答，共六題，我無聊玩了三次，每次出題那兩個數字是隨機的
#### solve
* Question 1/6:
    * ">> 1" 右循環1 bits: 把每個右移1 bits，最後一個補到最前面
![image](https://hackmd.io/_uploads/HyiOBeMCT.png)
* Question 2/6:
    * '+'加法運算
![image](https://hackmd.io/_uploads/B1cZUxMC6.png)
* Question 3/6:
    * '*' 乘法運算
![image](https://hackmd.io/_uploads/S14BLlMCp.png)
* Question 4/6:
    * "<< 1" 左循環1 bits: 把每個左移1 bits，第一個捕到最後面
![image](https://hackmd.io/_uploads/HyfOIez0p.png)
* Question 5/6:
    * AND運算: 2個都是1才會輸出1
![image](https://hackmd.io/_uploads/SkJUvlfR6.png)
* Question 6/6:
    * OR運算: 其中一個是1結果就是1
![image](https://hackmd.io/_uploads/BJSpPgfA6.png)

* 最後要我給最後一題答案的16進制
    * 11111111 -> ff
![image](https://hackmd.io/_uploads/By3PuxGAa.png)
最後得到flag
#### answer
``picoCTF{b1tw^3se_0p3eR@tI0n_su33essFuL_d9a7ddd2}``
#### note
[運算式運算子概念](https://ithelp.ithome.com.tw/articles/10214404)
[二進制計算機](https://miniwebtool.com/zh-tw/binary-calculator/?number1=01110111&operate=3&number2=10011110)
[進制轉換網站](https://www.kwuntung.net/hkunit/base/base.php)

### Binary Search
#### 題目說明
![image](https://hackmd.io/_uploads/H1PiwuG0p.png)

![image](https://hackmd.io/_uploads/Sy_4_OMC6.png)
一個終極密碼的遊戲，有10次機會給你猜，答案的數字是隨機的
#### solve
:::success
使用二分搜尋法即可解題
猜的數字=(最小範圍+最大範圍)/2，我的話小數4捨5入
:::
![image](https://hackmd.io/_uploads/HyHPFdG0a.png)
#### answer
``picoCTF{g00d_gu355_2e90d29b}``
## Binary Exploitation
### heap 0
#### 題目說明
![image](https://hackmd.io/_uploads/HySeqmxRa.png)
* linux 執行檔 : chall
* 跟它的原始檔 : chall.c
#### solve
先看chall.c
::: spoiler chall.c
```gcc=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FLAGSIZE_MAX 64
// amount of memory allocated for input_data
#define INPUT_DATA_SIZE 5
// amount of memory allocated for safe_var
#define SAFE_VAR_SIZE 5

int num_allocs;
char *safe_var;
char *input_data;

void check_win() {
    if (strcmp(safe_var, "bico") != 0) {
        printf("\nYOU WIN\n");

        // Print flag
        char buf[FLAGSIZE_MAX];
        FILE *fd = fopen("flag.txt", "r");
        fgets(buf, FLAGSIZE_MAX, fd);
        printf("%s\n", buf);
        fflush(stdout);

        exit(0);
    } else {
        printf("Looks like everything is still secure!\n");
        printf("\nNo flage for you :(\n");
        fflush(stdout);
    }
}

void print_menu() {
    printf("\n1. Print Heap:\t\t(print the current state of the heap)"
           "\n2. Write to buffer:\t(write to your own personal block of data "
           "on the heap)"
           "\n3. Print safe_var:\t(I'll even let you look at my variable on "
           "the heap, "
           "I'm confident it can't be modified)"
           "\n4. Print Flag:\t\t(Try to print the flag, good luck)"
           "\n5. Exit\n\nEnter your choice: ");
    fflush(stdout);
}

void init() {
    printf("\nWelcome to heap0!\n");
    printf(
        "I put my data on the heap so it should be safe from any tampering.\n");
    printf("Since my data isn't on the stack I'll even let you write whatever "
           "info you want to the heap, I already took care of using malloc for "
           "you.\n\n");
    fflush(stdout);
    input_data = malloc(INPUT_DATA_SIZE);
    strncpy(input_data, "pico", INPUT_DATA_SIZE);
    safe_var = malloc(SAFE_VAR_SIZE);
    strncpy(safe_var, "bico", SAFE_VAR_SIZE);
}

void write_buffer() {
    printf("Data for buffer: ");
    fflush(stdout);
    scanf("%s", input_data);
}

void print_heap() {
    printf("Heap State:\n");
    printf("+-------------+----------------+\n");
    printf("[*] Address   ->   Heap Data   \n");
    printf("+-------------+----------------+\n");
    printf("[*]   %p  ->   %s\n", input_data, input_data);
    printf("+-------------+----------------+\n");
    printf("[*]   %p  ->   %s\n", safe_var, safe_var);
    printf("+-------------+----------------+\n");
    fflush(stdout);
}

int main(void) {

    // Setup
    init();
    print_heap();

    int choice;

    while (1) {
        print_menu();
	int rval = scanf("%d", &choice);
	if (rval == EOF){
	    exit(0);
	}
        if (rval != 1) {
            //printf("Invalid input. Please enter a valid choice.\n");
            //fflush(stdout);
            // Clear input buffer
            //while (getchar() != '\n');
            //continue;
	    exit(0);
        }

        switch (choice) {
        case 1:
            // print heap
            print_heap();
            break;
        case 2:
            write_buffer();
            break;
        case 3:
            // print safe_var
            printf("\n\nTake a look at my variable: safe_var = %s\n\n",
                   safe_var);
            fflush(stdout);
            break;
        case 4:
            // Check for win condition
            check_win();
            break;
        case 5:
            // exit
            return 0;
        default:
            printf("Invalid choice\n");
            fflush(stdout);
        }
    }
}

```
:::
* ``input_data``和``safe_var``的記憶體分配都是5字節，因此溢出時的空間有限。
* 程式使用了strncpy來防止緩衝區溢出，但strncpy在沒有添加null 終止符的情況下可能導致字串不完整。
* 在選單中選擇4（Print Flag）將觸發``check_win``函數，該函數透過比較``safe_var``和 "bico" 來決定是否輸出flag
:::success
buffer overflow 得到 flag，需要輸入超過5個字元的內容，覆蓋到safe_var記憶體區域，讓它的內容不再是"bico"。最後選4（Print Flag）進入check_win函數並輸出flag.txt
:::
* 執行
![image](https://hackmd.io/_uploads/BkUVhXgR6.png)
#### answer
``picoCTF{my_first_heap_overflow_c3935a08}``




