CCE Final ํ›„๊ธฐ ๐Ÿ˜„

ORIU9RIยท2024๋…„ 9์›” 12์ผ
0

Writeup

๋ชฉ๋ก ๋ณด๊ธฐ
1/2

๊ณต๊ณต๋ถ€๋ฌธ 2๋“ฑ์œผ๋กœ ๋งˆ๋ฌด๋ฆฌํ•œ CCE ํ›„๊ธฐ

Jeopardy 2086 ์  + Live Fire 2010 ์ ์œผ๋กœ 2**12 ์ ์„ ๋‹ฌ์„ฑํ•˜๋ฉฐ ๊ณต๊ณต 2์œ„ ์ด 6์œ„๋ฅผ ๊ธฐ๋กํ–ˆ๋‹ค.
๋‚˜๋Š” Live Fire ์™€ 01 ๋ฒˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€๋‹ค. 01๋ฒˆ์ด ์ƒ๊ฐ๋ณด๋‹ค ๋Šฆ์–ด์ง€๋ฉด์„œ ๋‹ค๋ฅธ ๋ฌธ์ œ๋ฅผ ์ œ๋Œ€๋กœ ๋ชป๋ดค๋Š”๋ฐ ๋Œ€ํšŒ ์‹œ๊ฐ„์ด ์งง๋‹ค๊ณ  ๋Š๊ปด์กŒ๋‹ค. ๋ฌธ์ œ๋Š” ๋‹ค ์žฌ๋ฐŒ์–ด๋ณด์˜€๋Š”๋ฐ ๐Ÿ˜ฅ

TMI

์šฐ๋ฆฌ ํŒ€ NOOP์„ ์†Œ๊ฐœํ•˜์ž๋ฉด ์œก๊ตฐ ์‚ฌ์ด๋ฒ„์ž‘์ „์„ผํ„ฐ ์—์„œ ๊ทผ๋ฌดํ•˜๋Š” ๋ณ‘์‚ฌ 2๋ช…๊ณผ ๊ฐ„๋ถ€ 2๋ช…์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค
๋ณ‘์‚ฌ๋Š” ๋‚˜์™€ ์‚ฌ์ด๋ฒ„์ž‘์ „๋ณ‘ ์•Œ๋™๊ธฐ์ธ ์ •์›…์ด, ๊ทธ๋ฆฌ๊ณ  ๊น€์ข…๋ฏผ ์†Œ๋ น๋‹˜, ์ด๋„์› ๋Œ€์œ„๋‹˜๊นŒ์ง€.
์ธ์ƒ์—์„œ ์•„๋งˆ ํ•˜๋‚˜๋ฟ์ผ ๊ณต๊ณต ๋ถ€๋ฌธ ์ถœ์ „์ด์–ด์„œ 1๋“ฑ์„ ๊ธฐ๋Œ€ํ–ˆ์ง€๋งŒ ์ˆจ์–ด์žˆ๋˜ ์‚ฌ๊ตญ 2๋ถ„๊ป˜ 1๋“ฑ ์ž๋ฆฌ๋Š” ๋„˜์–ด๊ฐ”๋‹ค.

Live Fire ๋Š” ๋ชจ๋“  ํŒ€์—๊ฒŒ 2500 ์ ์„ ๋Œ€ํšŒ ์‹œ์ž‘ํ•  ๋•Œ ๋ถ€์—ฌํ•˜๊ณ , ๊ฐ ํŒ€๋งˆ๋‹ค ์ฃผ์–ด์ง„ ์„œ๋ฒ„์— 20๋ถ„๋งˆ๋‹ค 5๊ฐœ ์ทจ์•ฝ์ ์„ ๊ณต๊ฒฉ์ด ์ด๋ฃจ์–ด์กŒ๋‹ค. ๊ฐ ์ทจ์•ฝ์ ๋‹น 10์ ์”ฉ ์ฐจ๊ฐ๋˜๋ฉฐ ์ •์ƒ์ ์ธ ๊ธฐ๋Šฅ์ด ๊ณ ์žฅ๋‚  ์‹œ ๊ทธ๋ƒฅ 50์ ์ด ๊นŒ์ด๋Š” ๋ฐฉ์‹์ด๋‹ค. 2022๋…„ CCE ๋•Œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ๋งŒ ์ฃผ์–ด์ง€๊ณ  ์–ด์…ˆ ํŒจ์น˜๋ฅผ ํ†ตํ•ด ์—…๋กœ๋“œํ•ด์•ผ ํ–ˆ๋Š”๋ฐ ์ด๋ฒˆ์—๋Š” ์„œ๋ฒ„ ๋‚ด์— ssh ์ ‘์†ํ•˜์—ฌ ์ง์ ‘ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ˆ˜์ • ํ›„ ๋นŒ๋“œํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํŒจ์น˜๊ฐ€ ์ง„ํ–‰๋˜์—ˆ๋‹ค. ๊ทธ๋•Œ ๋‹น์‹œ Live Fire ์˜ ๋„ํŠธ๋”œ์ด ์ƒ๊ฐ๋ณด๋‹ค ์ปธ๊ณ  (๋Œ€ํšŒ ์‹œ๊ฐ„์ด ๋” ๊ธธ์—ˆ๊ธฐ์—) ์ด๋ฒˆ์—๋„ Live Fire๊ฐ€ ์ค‘์š”ํ•  ๊ฒƒ ๊ฐ™์•„ Live Fire ๋ถ€ํ„ฐ ํ™•์ธํ–ˆ๋‹ค.
๊ณ„์‚ฐํ•ด๋ณด๋ฉด 1200์ ์ด ์ตœ์†Œ ์ ์ˆ˜์ด๋‹ค. 150์ ์”ฉ 9์‹œ๊ฐ„๋งˆ๋‹ค ๊ฐ์†Œ๋˜๊ณ  ๋งˆ์ง€๋ง‰ ํ•œ๋ฒˆ์€ ์•„๋‹ˆ๋‹ˆ 2500์ ์—์„œ 1300์ ์ด ๊นŒ์—ฌ 1200์ ์ด ์ตœ์†Œ ์ ์ˆ˜.

2019๋…„๋ถ€ํ„ฐ ๋งค๋…„ ๋Œ€ํšŒ๋ฅผ ์—ฌ๊ธฐ์ €๊ธฐ ๋‹ค๋‹ˆ๋ฉด์„œ ์ฒ˜์Œ ๊ฒช๋Š” ์ƒํ™ฉ์ด ์ผ์–ด๋‚ฌ๋‹ค.
๋Œ€ํšŒ์žฅ ์ž…์žฅํ•˜๋Š” ์ค„์ด ๋ญ์ด๋ฆฌ ๊ธธ์ง€ ์˜์•„ํ–ˆ๋Š”๋ฐ ์ € ๋์— ์œก๊ตฐ ๋ณธ์ฒญ๊ณผ ๊ณตํ•ญ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒ€์ƒ‰๋Œ€๊ฐ€ ์žˆ์—ˆ๋‹ค. ์•ˆ๋‚ด์‚ฌํ•ญ์œผ๋กœ๋„ ๊ฒ€์ƒ‰๋Œ€ ํ†ต์ œ ์‹œ๊ฐ„์„ ์ง€๋‚  ๊ฒฝ์šฐ ์ž…์žฅ์ด ํž˜๋“ค ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์‹ฌ์žฅํ•œ ๋ฌธ์ž๊ฐ€ ์™”์—ˆ๋‹ค. ์•”ํŠผ ์ค„ ์„œ๋‹ค๋ณด๋‹ˆ ๊ฒฝ์ฐฐ๋ถ„๋“ค๊ณผ ์ •์žฅ์ž…์€ ๋ถ„๋“ค์ด ์†Œ์ง€ํ’ˆ ๊ฒ€์‚ฌ ๋ฐ ๋ชธ ์Šค์บ”์„ ํ•˜๋Š”๋ฐ ์™œ์ด๋Ÿด๊นŒ ์‹ถ์—ˆ๋‹ค.

์„ค๋งˆ์„ค๋งˆ ํ–ˆ๋Š”๋ฐ ๋Œ€ํ†ต๋ น์ด ์ง์ ‘ ์˜ค์…จ๋‹ค. ๐Ÿ˜ต CCE ํ–‰์‚ฌ ์˜†์— APEX ? ๋ญ” ํ–‰์‚ฌ๋„ ๊ฐ™์ด ํ•˜๋Š๋ผ ์™ธ๊ตญ์ธ๋“ค๋„ ๋งŽ์ด ์™”๊ณ  ๋ฐ–์—๋Š” ๋ณด์•ˆ ๊ด€๋ จ ํšŒ์‚ฌ๋“ค ๋ถ€์Šค๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ ์˜ค์ „ 11์‹œ์— ๋Œ€ํ†ต๋ น์˜ ๊ธฐ๋… ์ดฌ์˜์‹์ด ์žˆ์—ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ์ด๋ณ‘ ๋ถ€ํ„ฐ ๋ณ‘์žฅ, ํ•˜์‚ฌ๋ถ€ํ„ฐ ์ค€์œ„, ์†Œ์œ„๋ถ€ํ„ฐ 5์Šคํƒ€๊นŒ์ง€ ๋ชจ๋‘ ๋„๊ฐ์— ๋“ฑ๋ก๋˜์—ˆ๋‹ค.๐Ÿ˜Ž

writeup

Live Fire - 1 / SQLI

๊ฐ€์žฅ ๋จผ์ € ๋กœ๊ทธ์ธ ์ฝ”๋“œ๊ฐ€ ๋ˆˆ์— ๋„์—ˆ๋‹ค.

bool Server::Authentication::initAccount() {
    char *err;
    const char *statement = "DROP TABLE IF EXISTS Account;" 
                            "CREATE TABLE Account(Id TEXT, Password TEXT);" 
                            "INSERT INTO Account VALUES('admin', 'CCE2024LIVEFIRE');";
    Check(sqlite3_open(":memory:", &m_db) == SQLITE_OK);
    Check(sqlite3_exec(m_db, statement, 0, 0, &err) == SQLITE_OK);
    return true;
}

int callback(void *ptr, int argc, char **argv, char **azColName) {
    auto me = (Server::Authentication *)ptr;
    for (int i = 0; i < argc; i++) {
        if (!strcmp(argv[i], me->userPW())) {
            me->setAdmin(true);
            me->setAuthorized(true);
            break;
        }
    }
    return 0;
}

bool Server::Authentication::doAuthorize(const char *requestID, const char *password) {
    char *err;
    m_userID = (char *)requestID;
    m_userPW = (char *)password;
    if (strncmp("admin", requestID, 5)) {
        std::cout << "Log in as guest" << std::endl;
        m_authorized = true;
        return true;
    }
    
    const char *statement = "SELECT Password FROM Account WHERE Id = '%s'";
    if (res != SQLITE_DONE) {
        std::cerr << "Execution failed: " << sqlite3_errmsg(m_db) << std::endl;
    }
    auto statementBuffer = alloca(strlen(statement) + strlen(requestID));
    memset(statementBuffer, 0, strlen(statement) + strlen(requestID));
    snprintf((char *)statementBuffer, strlen(statement) + strlen(requestID), statement, requestID);
    std::cout << "Query: " << (char *)statementBuffer << std::endl;
    Check(sqlite3_exec(m_db, (const char *)statementBuffer, callback, (void *)this, &err) == SQLITE_OK);
    return false;
}

๋ฌผ๊ตฌ๋‚˜๋ฌด ์„œ์„œ ๋ด๋„ ๋ฌธ์ œ์ธ '%s' ๊ฐ€ ๋ณด์ธ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ id ๋น„๊ต ๋˜ํ•œ strncmp ๋กœ ์•ž 5๋ฐ”์ดํŠธ๋งŒ admin ์ธ์ง€ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์— admin' or 1=1 -- ์ฒ˜๋Ÿผ sqli๊ฐ€ ๊ฐ€๋Šฅํ•ด๋ณด์ธ๋‹ค. ์‹œ๋„ํ•ด๋ณด๋ฉด ์ž˜ ๋œ๋‹ค.


bool Server::Authentication::doAuthorize(const char *requestID, const char *password) {
    char *err;
    sqlite3_stmt *stmt;
    m_userID = (char *)requestID;
    m_userPW = (char *)password;
    if (strncmp("admin", requestID, 5)) {
        std::cout << "Log in as guest" << std::endl;
        m_authorized = true;
        return true;
    }
    
    const char *statement = "SELECT Password FROM Account WHERE Id = ?";
    std::cout << "doAuthorize" << std::endl;
    if (sqlite3_prepare_v2(m_db, statement, -1, &stmt, nullptr) != SQLITE_OK) {
        std::cerr << "Failed to prepare statement: " << sqlite3_errmsg(m_db) << std::endl;
        sqlite3_close(m_db);
        return 1;
    }
    
    if (sqlite3_bind_text(stmt, 1, requestID, -1, SQLITE_STATIC) != SQLITE_OK) {
        std::cerr << "Failed to bind text: " << sqlite3_errmsg(m_db) << std::endl;
    }
    
    int res = sqlite3_step(stmt);
    if (res == SQLITE_ROW) {
        const char *_password = (const char*)sqlite3_column_text(stmt, 0);
        std::cout << _password << std::endl;
        if (!strncmp(_password, password, strlen(_password))) {
            std::cout << "Login Success" << std::endl;
            sqlite3_finalize(stmt);
            
            this->setAdmin(true);
            this->setAuthorized(true);
            return true;
        }
    } else if (res != SQLITE_DONE) {
        std::cerr << "Execution failed: " << sqlite3_errmsg(m_db) << std::endl;
    }  

    sqlite3_finalize(stmt);
    std::cout << "Login Failed" << std::endl;
    return false;
}

์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ '%s' ๋ฅผ ? ๋กœ ๋Œ€์ฒดํ•˜๊ณ  prepare - bind - step ์ˆœ์œผ๋กœ ํ˜ธ์ถœํ•˜๋ฉฐ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ํ•ด์ค€๋‹ค.

์•ฝ๊ฐ„ ํ—ค๋งค๋‹ค ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ด ์ž‘๋™์•ˆํ•ด์„œ ๋‘ ํƒ€์ž„? ๋‚ ๋ ค๋จน์—ˆ์ง€๋งŒ 10์‹œ์— ์„ฑ๊ณต์ ์œผ๋กœ ํŒจ์น˜ํ–ˆ๋‹ค.

๋‚จ์€ 8์‹œ๊ฐ„ => 10 point * 3 / 1hour => 240 ์  ๋ฐฉ์–ด

Live Fire - 2 / Command Injection

bool CommandServer::CommandServer::runcmd(const httplib::Request &request, std::string &result) {
    std::ostringstream tmp;
    auto cmd = request.get_param_value("command");
    Check(!cmd.empty());
    auto runCommand = Check(filter(cmd.c_str()));
    std::cout << "Running command: " << runCommand << std::endl;
    auto ret = exec(runCommand);
    auto rdbuf = ret.rdbuf();
    tmp << cmd;
    tmp << "\n";
    tmp << rdbuf;
    result.append(tmp.str());
    return true;
}

char *CommandServer::CommandServer::filter(const char *cmd) {
    for (auto &allowedCmd : sCommandList) {
        if (!strncmp(allowedCmd, cmd, strlen(allowedCmd))) {
            auto streambuf = std::string(cmd);

            if (streambuf.contains(' ')) {
                auto buffer = (char *)Check(malloc(strlen(cmd) + 0x100));
                bzero(buffer, strlen(cmd) + 0x100);
                auto splited = split(streambuf, ' ');
                Check(splited.size() == 2);
                snprintf(buffer, strlen(cmd) + 0x100, "%s '%s'", splited[0].c_str(), res.c_str());
                std::cout << buffer << std::endl;
                return buffer;
            }
            return (char *)cmd;
        }
    }
    return nullptr;
}

๋ณด๋‹ค์‹œํ”ผ ์—ฌ๊ธฐ๋„ %s '%s' ๋กœ sprintf ํ•ด์ฃผ๊ณ  ์žˆ๋‹ค. ๐Ÿ˜‘ ๋ง‰ command ์‚ฝ์ž…ํ•ด๋ฒ„๋ฆฌ๊ณ  ์‹ถ์€ ๋งˆ์Œ์ด ๋“ค๊ณ  ๊ทธ๋Ÿด ๊ฒƒ์ด๋‹ค. ์—ญ์‹œ๋‚˜ echo ';ls;' ํ•ด๋ณธ ๊ฒฐ๊ณผ ์ž˜ ์‹คํ–‰๋๋‹ค. ์–ด๋–ป๊ฒŒ ํŒจ์น˜ํ• ๊นŒ ํ•˜๋‹ค๊ฐ€ ๊ทธ๋ƒฅ quote escape ์ฒ˜๋ฆฌ ํ–ˆ๋‹ค. + ` ์ฒ˜๋ฆฌ๊นŒ์ง€.

std::string escapeSpecialChars(const std::string& input) {
    std::string result;

    for (char c : input) {
        if (c == '\'') {
            result += "'\\''"; 
        } else if (c == '`') {
            result += "\\`";
        } else {
            result += c; 
        }
    }

    return result;
}

char *CommandServer::CommandServer::filter(const char *cmd) {
    for (auto &allowedCmd : sCommandList) {
        if (!strncmp(allowedCmd, cmd, strlen(allowedCmd))) {
            auto streambuf = std::string(cmd);
            // echo ';ls;'
            if (streambuf.contains(' ')) {
                auto buffer = (char *)Check(malloc(strlen(cmd) + 0x100));
                bzero(buffer, strlen(cmd) + 0x100);
                auto splited = split(streambuf, ' ');
                Check(splited.size() == 2);

                std::string res = escapeSpecialChars(splited[1]);
                
                snprintf(buffer, strlen(cmd) + 0x100, "%s '%s'", splited[0].c_str(), res.c_str());
                std::cout << buffer << std::endl;
                return buffer;
            }
            return (char *)cmd;
        }
    }
    return nullptr;
}

๋ฐฉ์–ด ์„ฑ๊ณต ~
(์™œ์ธ์ง€ ๋ชจ๋ฅด๊ฒŒ 3๊ฐœ๊ฐ€ ๋ฐฉ์–ด๋˜์–ด์„œ ๋ญ”๊ฐ€ ์‹ถ์—ˆ๋‹ค)

๋‚จ์€ 7์‹œ๊ฐ„ => 10p * 3/1h => 210p ๋ฐฉ์–ด ~

Live Fire - 3 / UAF

๊ฐ‘์ž๊ธฐ ๋ง‰ 50์ ์”ฉ ๊นŽ์ด๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ์ ์ˆ˜๋ฅผ ๋ณด๊ณ  ๋‹นํ™ฉ์Šค๋Ÿฌ์› ๋‹ค. ํ•œ ๋‘์–ด ์ฐจ๋ก€ ์–ดํผ์ปท ๋งž๊ณ  ๋ณด๋‹ˆ ์„œ๋ฒ„๋ฅผ ์ž˜๋ชป ๋Œ๋ฆฌ๊ณ  ์žˆ์—ˆ๋‹ค. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋Œ์•„๊ฐ€๋Š” run.sh ๊ฐ€ ์žˆ๋Š”์ค„ ๋ชจ๋ฅด๊ณ  ๋”ฐ๋กœ ๋Œ๋ฆฌ๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ์ด๋†ˆ์ด ํŒจํ‚ท์„ ๋‚˜๋ˆ  ๋จน์œผ๋ฉด์„œ ๋น„์ •์ƒ์ ์ธ ๊ฒฐ๊ณผ๋กœ ์ด์–ด์ง€๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค. ๐Ÿ˜ญ

?! ๋ฐ”๋กœ ํ™•์ธํ•ด๋ณด์ž

bool Server::Server::prepareTLEs() {
    std::ifstream file;
    file.open("/home/user/Livefire2024/src/Resource/tles.txt", std::ifstream::in);
    Check(file.is_open());
    std::string line, temp;
    while (std::getline(file, line)) {
        line.append("\n");
        Check(line.length() == 70);
        if (line.at(0) == '\x32') {
            std::string TLE;
            TLE.append("XXXX                                                                 \n");
            TLE.append(temp);
            TLE.append(line);
            Check(TLE.length() == 70 * 3);
            auto number = Satellite::satellite_number(TLE);
            auto it = m_satellites.find(number);
            if (it != m_satellites.end()) { continue; }
            auto object = std::unique_ptr<Satellite::Satellite>(new Satellite::Satellite(std::to_string(number), TLE));
            m_satellites.insert(std::make_pair(number, std::move(object)));
            m_numTLEs++;
        } else {
            temp = line;
        }
    }
    return true;
}

..

    m_server.Post("/register", [&](const httplib::Request &request, httplib::Response &response) {
        m_mutex.lock();
        SCOPE_EXIT({ m_mutex.unlock(); });
        DEBUG_DUMP_REQUEST;

        
        if (!m_authenticator.isAuthorized()) {
            response.set_redirect("/");
        }
        auto content = std::make_unique<uint8_t[]>(0x1000);
        bzero(content.get(), 0x1000);
        auto name = request.get_param_value("name");
        CheckVoid(!name.empty());
        auto TLE = request.get_param_value("TLE");
        auto pos = TLE.find("\n");
        CheckVoid(pos != std::string::npos);
        auto substr = TLE.substr(pos + 1);
        auto number = Satellite::satellite_number(substr);
        auto it = m_satellites.find(number);
        if (it == m_satellites.end()) {
            auto object = std::unique_ptr<Satellite::Satellite>(new Satellite::Satellite(name, TLE));
            m_satellites.insert(std::make_pair(number, std::move(object)));
            m_numTLEs++;
            snprintf((char *)content.get(), 0x1000, "Success to register, Total TLEs: %d", m_numTLEs);
            response.set_content((char *)content.get(), "text/plain");
        } else {
            snprintf((char *)content.get(), 0x1000, "Failed to register, Total TLEs: %d", m_numTLEs);
            response.set_content((char *)content.get(), "text/plain");
        }
    });

    m_server.Post("/unregister", [&](const httplib::Request &request, httplib::Response &response) {
        m_mutex.lock();
        SCOPE_EXIT({ m_mutex.unlock(); });
        DEBUG_DUMP_REQUEST;

        if (!m_authenticator.isAuthorized()) {
            response.set_redirect("/");
        }
        auto numberAsStr = request.get_param_value("number");
        CheckVoid(!numberAsStr.empty());
        auto number = stoi(numberAsStr);
        auto it = m_satellites.find(number);
        if (it != m_satellites.end()) {
            auto object = it->second.get();
            m_satellites.erase(it);
            response.set_content(object->dumpInfo(), "text/plain");
        }
    });

prepareTLEs ์—์„œ ์‚ฌ์ „์— ์ •์˜๋œ ์ธ๊ณต์œ„์„ฑ ์ •๋ณด๋“ค์„ std::map<int, std::unique_ptr<Satellite::Satellite>> m_satellites ์— ์ €์žฅํ•œ๋‹ค. ๋˜ register ๊ธฐ๋Šฅ์—์„œ๋„ ์ถ”๊ฐ€์ ์ธ TLE ๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ๋‘˜๋‹ค m_numTLEs ๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ค๋Š”๋ฐ, unregister ์—๋Š” ๊ฐ์†Œ์‹œํ‚ค๋Š” ์ฝ”๋“œ๊ฐ€ ์—†๊ธธ๋ž˜ m_numTLEs-- ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  m_satellites.erase(it) ํ›„ object->dumpInfo() ๋ฅผ ์‹คํ–‰ํ•˜๋Š”๋ฐ UAF๋กœ ์ธํ•œ Segfault๊ฐ€ ๋œจ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ erase ์ „์— ๋ฏธ๋ฆฌ dumpInfo๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ฆฌํ„ดํ•˜๋Š” ์‹์œผ๋กœ ๋ฐ”๊ฟ”์คฌ๋‹ค.

    m_server.Post("/unregister", [&](const httplib::Request &request, httplib::Response &response) {
        m_mutex.lock();
        SCOPE_EXIT({ m_mutex.unlock(); });
        DEBUG_DUMP_REQUEST;

        if (!m_authenticator.isAuthorized()) {
            response.set_redirect("/");
        }
        auto numberAsStr = request.get_param_value("number");
        CheckVoid(!numberAsStr.empty());
        auto number = stoi(numberAsStr);
        auto it = m_satellites.find(number);
        if (it != m_satellites.end()) {
            auto object = it->second.get();
            std::string res = object->dumpInfo();
            m_numTLEs--;
            m_satellites.erase(it);
            response.set_content(res, "text/plain");
        }
    });

๋‚จ์€ 6์‹œ๊ฐ„ => 10p * 3/1h => 180 ์  ๋ฐฉ์–ด

Live Fire - 4 / statistic ์ •์ƒํ™”

    m_server.Get("/statistic", [&](const httplib::Request &request, httplib::Response &response) {
        std::string content;
        m_mutex.lock();
        SCOPE_EXIT({ m_mutex.unlock(); });
        DEBUG_DUMP_REQUEST;
        
        if (!m_authenticator.isAuthorized()) {
            response.set_redirect("/");
        }
        for (auto const&it : m_satellites) {
            auto satellite = it.second.get();
            
            content.append(satellite->dumpInfo());
            content.append("\n");
        }
        response.set_content(content, "text/plain");
    });

์ €์žฅ๋œ ๋ชจ๋“  ์ธ๊ณต์œ„์„ฑ๋“ค์˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.

ํ…Œ์ŠคํŠธ ํ•ด๋ดค๋Š”๋ฐ ์ด๊ฒŒ ๋ญ๋žŒ ๋ชจ๋‘ ๊ฐ™์€ ์ •๋ณด๋ฅผ ๋ฑ‰๊ณ  ์žˆ๋‹ค. ํŠน์ง•์ด๋ผ๋ฉด ๋งˆ์ง€๋ง‰์œผ๋กœ ๋“ฑ๋ก๋˜์—ˆ๋˜ 41866 ์ธ๊ณต์œ„์„ฑ์˜ ์ •๋ณด์ด๋‹ค. ๋Œ€๊ฐœ ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ์•ž์„  ์ธ๊ณต์œ„์„ฑ๋“ค์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๋Š” m_TLE ๋ฌธ์ž์—ด์ด ๋ชจ๋‘ 41866 ์ธ๊ณต์œ„์„ฑ์˜ m_TLE๋กœ ๋ฎ์–ด์ง„ ์ƒํƒœ์ด๋‹ค. ํ™•์ธํ•ด๋ณธ ๊ฒฐ๊ณผ ์œ„ ์‚ฌ์ง„์ฒ˜๋Ÿผ ๋˜‘๊ฐ™์€ ๋ฌธ์ž์—ด์„ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ๋‹ค.

// Server.cc
bool Server::Server::prepareTLEs() {
    std::ifstream file;
    file.open("/home/user/Livefire2024/src/Resource/tles.txt", std::ifstream::in);
    Check(file.is_open());
    std::string line, temp;
    while (std::getline(file, line)) {
        line.append("\n");
        Check(line.length() == 70);
        if (line.at(0) == '\x32') {
            std::string TLE;
            TLE.append("XXXX                                                                 \n");
            TLE.append(temp);
            TLE.append(line);
            Check(TLE.length() == 70 * 3);
            auto number = Satellite::satellite_number(TLE);
            auto it = m_satellites.find(number);
            if (it != m_satellites.end()) { continue; }
            auto object = std::unique_ptr<Satellite::Satellite>(new Satellite::Satellite(std::to_string(number), TLE));
            m_satellites.insert(std::make_pair(number, std::move(object)));
            m_numTLEs++;
        } else {
            temp = line;
        }
    }
    return true;
}

//Satellite.h
class Satellite {
    public:
        Satellite(std::string_view name, std::string_view TLE) {
            std::random_device rd;
            m_name = (char *)malloc(name.length());
            memcpy(m_name, name.data(), name.length());
            m_TLE = std::move(TLE);
            std::cout << "Adding new satellite " << name << std::endl;
            std::mt19937 gen(rd());
            std::normal_distribution<float> generator(0, 1);
            m_location = std::make_pair(generator(gen) * 160 - 80, generator(gen) * 360 - 180);
        }

๊ฐ์ฒด๋งˆ๋‹ค์˜ m_TLE ๊ฐ€ ๋งˆ์ง€๋ง‰์˜ TLE ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค๋Š” ๊ฒƒ์€ prepareTLEs ๋‚ด์˜ TLE ๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค๋Š” ๊ฒƒ์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค
๊ฐ์ฒด๋งˆ๋‹ค ๋‹ค๋ฅธ string ์„ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋Œ€์ถฉ ๋•œ๋นตํ•ด์คฌ๋‹ค ใ…‹ใ…‹;

        if (line.at(0) == '\x32') {
            std::string* TLE = new std::string();
            TLE->append("XXXX                                                                 \n");
            TLE->append(temp);
            TLE->append(line);
            Check((*TLE).length() == 70 * 3);
            auto number = Satellite::satellite_number(*TLE);
            auto it = m_satellites.find(number);
            if (it != m_satellites.end()) { continue; }
            auto object = std::unique_ptr<Satellite::Satellite>(new Satellite::Satellite(std::to_string(number), *TLE));
            m_satellites.insert(std::make_pair(number, std::move(object)));
            m_numTLEs++;
        }

๋‚จ์€ 6์‹œ๊ฐ„ => 180์  ๋ฐฉ์–ด

์ตœ์†Œ ์ ์ˆ˜ 1200 ์ ์—์„œ ๋ฐฉ์–ด ์„ฑ๊ณตํ•œ 240 + 210 + 180 + 180 = 810 ์ ์„ ๋”ํ•˜์—ฌ ์šฐ๋ฆฌ ํŒ€์€ 2010์  Live Fire ์ ์ˆ˜๋ฅผ ๊ธฐ๋กํ•˜์˜€๋‹ค.

๋ฌธ์ œ ์ ์ˆ˜ 2086 ์ ๊ณผ ๋”ํ•˜๋ฉด 4096์ , ์ตœ์ข… ์ ์ˆ˜๊ฐ€ ๋‚˜์˜จ๋‹ค.

01. LNG ๋ณธ๋ถ€ (rev)

arm PE ํŒŒ์ผ๊ณผ ์•”ํ˜ธํ™”๋œ ํŒŒ์ผ์ด ์ฃผ์–ด์ง„๋‹ค.
์•”ํ˜ธํ™” ๊ณผ์ •์„ ๋ถ„์„ํ•˜์—ฌ ๋ณตํ˜ธํ™”ํ•ด์•ผํ•˜๋Š” ๋ฌธ์ œ์ผ ๊ฒƒ์ด๋‹ค.

IDA๋กœ ์Šฅ ๋ณด๋ฉด ๋ฐ”๋กœ WinCrypt ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ์•”ํ˜ธํ™” ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ , ๊ธˆ๋ฐฉ ํ’€๋ฆด ๊ฑฐ๋ผ ์˜ˆ์ƒํ–ˆ๋‹ค.

AES 256๋น„ํŠธ ํ‚ค๋ฅผ ์ƒ์„ฑํ•œ ํ›„ ํŒŒ์ผ์„ ์•”ํ˜ธํ™”ํ•œ๋‹ค. AES ํ‚ค๋ฅผ RSA ๊ณต๊ฐœํ‚ค๋กœ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์•”ํ˜ธํ™” ํŒŒ์ผ ์•ž๋ถ€๋ถ„์— ์ €์žฅํ•˜๋Š”๋ฐ, RSA ๊ณต๊ฐœํ‚ค๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ๋‚ด์— ์งฑ๋ฐ•ํ˜€์žˆ๋‹ค.

์ € v9 ์— ์ €์žฅ๋˜๋Š” ๊ฐ’์„ ๋ฝ‘์•„๋ณด๋ฉด

์™€ ๊ฐ™์€๋ฐ ์ด๋Š” PUBLICKEYBLOB ๊ตฌ์กฐ์ฒด ํ˜•์‹์ด๋‹ค. CryptExportKey ํ•  ๋•Œ PUBLICKEYBLOB ํ˜•์‹์œผ๋กœ ๋‚ด๋ณด๋‚ธ ๊ฒฐ๊ณผ์™€ ๊ฐ™์€๋ฐ ๊ตฌ์กฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๊ทธ๋ ‡๊ฒŒ 2049๋น„ํŠธ์งœ๋ฆฌ N ์„ ์ถ”์ถœํ•ด๋ณด๋ฉด(Little Endian ์œผ๋กœ ์ €์žฅ๋จ)
N = 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c5d341864e53fc1f46aed6e24a13f6a1a4a3795ff787068cdcfc892d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b1de37580ed5eeec2c6e5b7506de185673f8b93a478b3a9740d2cd012bb8d06e47d849e646eeabf83bd075a46879584072282b588825dd8d4b

๋ณด๋ฉด ์ค‘๊ฐ„์— 00์ด ์—„์ฒญ ๋งŽ๋‹ค. ๋”ฑ ๋ด๋„ ์ˆ˜์ƒํ•ด๋ณด์ด๊ธธ๋ž˜ ์˜†์— ์•‰์€ ์ •์›…์ด์—๊ฒŒ ๋ณด์—ฌ์คฌ๋‹ค.
ํ˜ผ์ž ์Šฅ์Šฅ ํ•˜๋”๋‹ˆ ๋…ธํŠธ์— ์ด๊ฑธ ์ ์–ด์„œ ๋ณด์—ฌ์คฌ๋‹ค.

N = (2^1024 + a) * (2^1024 + b) = 2^2048 + 2^1024(a + b) + ab
WOW ๐Ÿ˜ฎ ์œ„ ์‹์ด๋ฉด ์ € ๋นต๊พธ ๋šซ๋ฆฐ N ์„ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ตœ์ƒ์œ„์˜ 1์ด 1 << 2048 ์ด๊ณ , ์ค‘๊ฐ„์— 4c5d341...2d4 ๋Š” 2^1024(a+b), 5b1d..8d4b ๋Š” ab ์ธ ๊ฒƒ์ด๋‹ค.

a+b ์™€ ab๋ฅผ ์•Œ๊ธฐ ๋•Œ๋ฌธ์— a ์™€ b ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ณ , ๊ทธ ๊ฐ’์€

from z3 import *

n = 0x10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c5d341864e53fc1f46aed6e24a13f6a1a4a3795ff787068cdcfc892d40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005b1de37580ed5eeec2c6e5b7506de185673f8b93a478b3a9740d2cd012bb8d06e47d849e646eeabf83bd075a46879584072282b588825dd8d4b
5b1de37580ed5eeec2c6e5b7506de185673f8b93a478b3a9740d2cd012bb8d06e47d849e646eeabf83bd075a46879584072282b588825dd8d4b
pab = 0x4c5d341864e53fc1f46aed6e24a13f6a1a4a3795ff787068cdcfc892d4
ab = 0x5b1de37580ed5eeec2c6e5b7506de185673f8b93a478b3a9740d2cd012bb8d06e47d849e646eeabf83bd075a46879584072282b588825dd8d4b

a = Int('a')
b = Int('b')

s = Solver()
s.add(a > 0)
s.add(b > 0)
s.add(a * b == ab)
s.add(a + b == pab)
'''
s.check()
m = s.model()
[b = 1029385710293857012310298374019823740519823750198237501982375019825445,
 a = 1029385710293857012310298374019823740519823750198237501982375019825583]
'''

์œ„์™€ ๊ฐ™๋‹ค.

๊ทธ๋Ÿฌ๋ฉด p์™€ q๋Š” ๊ฐ๊ฐ ((1 << 1024) + a), ((1 << 1024) + b) ๊ฐ€ ๋˜๊ณ  RSA ๊ฐœ์ธํ‚ค๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

q = 1029385710293857012310298374019823740519823750198237501982375019825445
p = 1029385710293857012310298374019823740519823750198237501982375019825583

p, q = ((1 << 1024) + p), ((1 << 1024) + q)

assert p * q == n

e = 0x10001
phi = (p-1) * (q-1)
d = pow(e, -1, phi)

๊ทธ๋ฆฌ๊ณ  ์‚ฝ์งˆ์˜ ์‹œ๊ฐ„์ด ์ด์–ด์กŒ๋Š”๋ฐ, WinCrypt ๊ฐ€ aes key ๋ฅผ RSA ๋กœ CryptExportKey ํ•  ๋•Œ PKCS ํŒจ๋”ฉ์„ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์€๋ฐ, python ์œผ๋กœ decrypt ํ•  ๋•Œ ์ž๊พธ ๋ป‘๋‚ฌ๋‹ค. n ์ด 2049 ๋น„ํŠธ์ธ๋ฐ ์•”ํ˜ธํ™”๋œ ๋ฐ์ดํ„ฐ๋Š” 257 ๋ฐ”์ดํŠธ, ์ด ๋‘๊ฐœ๊ฐ€ PKCS์™€ RSA ์‚ฌ์ด์—์„œ ์ถฉ๋Œ? ์ด ์ผ์–ด๋‚œ ๊ฒƒ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ž˜์„œ CryptExportKey ๋กœ ๊ฐœ์ธํ‚ค๋ฅผ PRIVATEKEYBLOB ๊ตฌ์กฐ์ฒด๋กœ ์ถœ๋ ฅํ•œ blob ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด์„œ cpp ์ฝ”๋“œ์—์„œ CryptImportKey ํ•œ ๋‹ด์— CryptDecrypt ํ•˜๋Š” ๊ฝค ๋ฉ์ฒญํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ aes key ๋ฅผ ๋ณต๊ตฌํ–ˆ๋‹ค. ks ๋‹˜์˜ ์†”๋ฒ„๋ฅผ ๋ณด๋‹ˆ aes_key = long_to_bytes(pow(int.from_bytes(aes_key, 'little'), d, n))[::-1][:32][::-1] ์™€ ๊ฐ™์ด ๋ณต๊ตฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์‹œ๋„๋ฅผ ํ•ด๋ดค๋˜ ๊ฑด๋ฐ little ์—”๋””์•ˆ์œผ๋กœ ์ฝ๊ณ  ๋’ค์ง‘๊ณ  32๋ฐ”์ดํŠธ ๊ฐ€์ ธ์˜ค๊ณ  ๋‹ค์‹œ ๋’ค์ง‘๋Š” ๊ตฌ์กฐ๋ฅผ ์•„์˜ˆ ๋ชฐ๋ž๋‹ค ใ…‹ใ…‹;
์ถœ์ œ์ž๋ถ„ ์†”๋ฒ„ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€๋ฐ(๋‚˜๋„ ์ €๊ฑธ ๋ฐ”๋ž๋‹ค.)

rsakey = RSA.construct((n, e, d))
cipher = PKCS1_v1_5.new(rsakey)
aes_key = cipher.decrypt(aes_key[::-1], None)

PKCS1_v1_5 ์— 256๋ฐ”์ดํŠธ๋ฅผ ๋„˜์ค˜์•ผ ๋œ๋‹ค. ๊น”๋”ํ•˜๊ฒŒ

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
HCRYPTKEY* ImportRSAKey(HCRYPTPROV hProv) {
    BYTE aa[] = {0x4B, 0x8D, 0xDD, 0x25, 0x88, 0x58, 0x2B, 0x28, 0x72, 0x40, 0x58, 0x79, 0x68, 0xA4, 0x75, 0xD0, 0x3B, 0xF8, 0xAB, 0xEE, 0x46, 0xE6, 0x49, 0xD8, 0x47, 0x6E, 0xD0, 0xB8, 0x2B, 0x01, 0xCD, 0xD2, 0x40, 0x97, 0x3A, 0x8B, 0x47, 0x3A, 0xB9, 0xF8, 0x73, 0x56, 0x18, 0xDE, 0x06, 0x75, 0x5B, 0x6E, 0x2C, 0xEC, 0xEE, 0xD5, 0x0E, 0x58, 0x37, 0xDE, 0xB1, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0x92, 0xC8, 0xCF, 0xCD, 0x68, 0x70, 0x78, 0xFF, 0x95, 0x37, 0x4A, 0x1A, 0x6A, 0x3F, 0xA1, 0x24, 0x6E, 0xED, 0x6A, 0xF4, 0xC1, 0x3F, 0xE5, 0x64, 0x18, 0x34, 0x5D, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xAF, 0x49, 0xE4, 0xE7, 0x66, 0x34, 0x38, 0xBC, 0xFF, 0xCA, 0x1B, 0x25, 0x0D, 0xB5, 0x9F, 0x50, 0x12, 0xB7, 0x76, 0x35, 0xFA, 0xE0, 0x9F, 0x72, 0x32, 0x0C, 0x9A, 0x2E, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x25, 0x49, 0xE4, 0xE7, 0x66, 0x34, 0x38, 0xBC, 0xFF, 0xCA, 0x1B, 0x25, 0x0D, 0xB5, 0x9F, 0x50, 0x12, 0xB7, 0x76, 0x35, 0xFA, 0xE0, 0x9F, 0x72, 0x32, 0x0C, 0x9A, 0x2E, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x69, 0xF8, 0xF4, 0x6B, 0x2D, 0xD0, 0x1F, 0x22, 0x1D, 0xD0, 0x59, 0xFC, 0x0E, 0x93, 0xAA, 0xCE, 0x09, 0x64, 0xA4, 0x4F, 0x64, 0x12, 0x69, 0x33, 0xE8, 0xB6, 0x79, 0x36, 0xB8, 0x91, 0xBA, 0x4E, 0x25, 0x71, 0x9C, 0xDF, 0x6C, 0x94, 0x70, 0xC8, 0xD2, 0xAA, 0xF2, 0xE6, 0x2E, 0x20, 0x83, 0xC0, 0x60, 0xAF, 0x4C, 0xF0, 0xA5, 0x80, 0xD8, 0xE9, 0x01, 0x51, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xA0, 0x4C, 0x5F, 0xB3, 0xD6, 0x44, 0x6C, 0x8A, 0x28, 0xF7, 0xC1, 0xE4, 0xFB, 0xB4, 0x25, 0xA9, 0xFC, 0x8C, 0x7A, 0xFB, 0x74, 0xBA, 0x67, 0xDE, 0x30, 0x3F, 0xD7, 0xD8, 0x24, 0x08, 0xBA, 0x7F, 0x58, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0x1D, 0x3B, 0xE2, 0xC4, 0xCD, 0x8A, 0x46, 0x94, 0x53, 0xE6, 0x5C, 0xDB, 0x38, 0x79, 0xC4, 0xCC, 0xC7, 0x3F, 0x85, 0x4A, 0xA9, 0x86, 0xEC, 0xD1, 0x8B, 0x2A, 0xFC, 0x02, 0xD0, 0x72, 0x1A, 0xCD, 0xF0, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0xE5, 0xB2, 0x1A, 0x4D, 0x83, 0x73, 0xA4, 0x38, 0xFC, 0x0B, 0x61, 0x11, 0x32, 0xD0, 0x22, 0x82, 0x19, 0x48, 0xA4, 0xD3, 0xB0, 0x23, 0x25, 0xF2, 0xF3, 0x5A, 0x31, 0xF6, 0xBE, 0x5E, 0xC5, 0x9A, 0xDF, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0xD9, 0xD4, 0x26, 0x2B, 0x27, 0x2C, 0x8C, 0x7C, 0x6C, 0x91, 0x05, 0xDD, 0xB3, 0xDD, 0x66, 0x39, 0x66, 0x94, 0x3A, 0xA1, 0x5C, 0x50, 0xFC, 0x34, 0x3F, 0x57, 0x3E, 0xF9, 0x9B, 0x90, 0xE3, 0x66, 0xD7, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0xCC, 0xB5, 0x03, 0x73, 0xED, 0xC0, 0x5C, 0x3B, 0x30, 0xD7, 0x0E, 0x4C};
    DWORD bitlen = 2049;  
    
    BLOBHEADER blobHeader;
    blobHeader.bType = PRIVATEKEYBLOB;
    blobHeader.bVersion = 0x02;
    blobHeader.reserved = 0;
    blobHeader.aiKeyAlg = CALG_RSA_KEYX;
    
    RSAPUBKEY rsaPubKey;
    rsaPubKey.magic = 0x32415352;  
    rsaPubKey.bitlen = bitlen;
    rsaPubKey.pubexp = 65537;  
    
    DWORD blobSize = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
                     bitlen / 8 * 7;  
    BYTE *keyBlob = (BYTE*)malloc(blobSize);
    BYTE *ptr = keyBlob;
    
    memcpy(ptr, &blobHeader, sizeof(BLOBHEADER));
    ptr += sizeof(BLOBHEADER);
    
    memcpy(ptr, &rsaPubKey, sizeof(RSAPUBKEY));
    ptr += sizeof(RSAPUBKEY);
    
    memcpy(ptr, aa, sizeof(aa));
    ptr += sizeof(aa);
    
    HCRYPTKEY* hKey = (HCRYPTKEY*) malloc(sizeof(HCRYPTKEY));
    if (!CryptImportKey(hProv, keyBlob, blobSize, 0, 0, hKey)) {
        printf("CryptImportKey failed: %d\n", GetLastError());
    } else {
        printf("Key imported successfully\n");
    }
    free(keyBlob);
    return hKey;
}

BOOL DecryptAESKey(HCRYPTKEY hPrivateKey, const BYTE* pbEncryptedAESKey, DWORD dwEncryptedAESKeyLen, BYTE** ppDecryptedAESKey, DWORD* pdwDecryptedAESKeyLen) {
    
    *pdwDecryptedAESKeyLen = dwEncryptedAESKeyLen; 
    
    
    *ppDecryptedAESKey = (BYTE*)malloc(*pdwDecryptedAESKeyLen);
    if (*ppDecryptedAESKey == NULL) {
        printf("Memory allocation failed\n");
        return FALSE;
    }
    memcpy(*ppDecryptedAESKey, pbEncryptedAESKey, dwEncryptedAESKeyLen);
    
    
    if (!CryptDecrypt(hPrivateKey, 0, TRUE, 0, *ppDecryptedAESKey, pdwDecryptedAESKeyLen)) {
        printf("CryptDecrypt failed: %d\n", GetLastError());
        free(*ppDecryptedAESKey);
        return FALSE;
    }
    return TRUE;
}
int main() {
    HCRYPTPROV hProv;
    
    
    if (!CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
        printf("CryptAcquireContext failed: %d\n", GetLastError());
        return 1;
    }
    
    
    BYTE encryptedAESKey[] = { 0xB5, 0x14, 0x9D, 0x1F, 0x12, 0x0B, 0x68, 0xF8, 0xF0, 0x9B, 0xD0, 0x53, 0xFB, 0x04, 0x60, 0xDF, 0xE8, 0xEB, 0x70, 0x8D, 0x28, 0xEA, 0x51, 0xAE, 0xCB, 0xBC, 0x0C, 0x40, 0xFD, 0x8B, 0x72, 0x89, 0xE9, 0x52, 0x5E, 0x32, 0xCF, 0x93, 0x72, 0x0C, 0x83, 0x62, 0xC5, 0xC3, 0xCF, 0xFD, 0xBB, 0x03, 0x3A, 0x19, 0xA0, 0x49, 0x33, 0x0B, 0x29, 0x2B, 0x19, 0x13, 0xB2, 0x1C, 0xD4, 0x83, 0x41, 0x82, 0xF2, 0xEC, 0xD5, 0x3C, 0xAD, 0x66, 0xD7, 0xDA, 0x83, 0x31, 0x8D, 0x0F, 0x01, 0xE3, 0x25, 0xBE, 0x50, 0x52, 0xBE, 0x1C, 0x7A, 0x0D, 0x12, 0x4F, 0x82, 0x7C, 0x48, 0x15, 0x32, 0xF1, 0xD5, 0x76, 0x42, 0x77, 0x02, 0x2F, 0x39, 0x3D, 0x14, 0x21, 0x7F, 0x24, 0x80, 0x51, 0x6B, 0xE2, 0xCA, 0xDF, 0xEB, 0xC5, 0x76, 0x17, 0x0F, 0x3E, 0x57, 0xB3, 0x27, 0x7A, 0x59, 0xAC, 0x12, 0x08, 0x9D, 0x0C, 0xAE, 0x9F, 0x65, 0xDB, 0xBE, 0x60, 0x31, 0x9D, 0xA1, 0xD6, 0x2D, 0xEF, 0x91, 0x66, 0x2C, 0x24, 0x21, 0xC2, 0xF5, 0x82, 0x4B, 0xA7, 0xE1, 0x79, 0x23, 0x68, 0x7C, 0xBE, 0x59, 0xF0, 0x55, 0xB8, 0x1B, 0xB9, 0xF6, 0x3A, 0xDB, 0x24, 0xED, 0x9D, 0x5A, 0xAC, 0xB2, 0x43, 0x1C, 0xF2, 0x31, 0xB3, 0x82, 0x35, 0x36, 0xD4, 0xDC, 0xE0, 0xB8, 0xB8, 0x4B, 0xCB, 0xAE, 0xFE, 0xE7, 0x0B, 0x85, 0x37, 0x13, 0xFC, 0x26, 0xBF, 0x49, 0x20, 0xC3, 0xCC, 0x22, 0x5D, 0xA6, 0x1F, 0x1F, 0xE8, 0x07, 0xE2, 0x96, 0xE5, 0x4B, 0x73, 0x61, 0xD1, 0x82, 0x67, 0x7C, 0x4F, 0xFC, 0xF0, 0x97, 0x49, 0x11, 0x88, 0x7C, 0x27, 0x65, 0x8C, 0x73, 0x4D, 0x36, 0x56, 0xC7, 0x10, 0x36, 0x90, 0x0E, 0xD6, 0xA9, 0xC1, 0xEB, 0x61, 0x09, 0xC5, 0x93, 0x54, 0x0F, 0xAB, 0xAD, 0xBF, 0x7A, 0x2F, 0x5C, 0x3E, 0x9B, 0x4B, 0x00 };
    DWORD encryptedAESKeyLen = sizeof(encryptedAESKey);
    
    
    HCRYPTKEY* hPrivateKey = ImportRSAKey(hProv);
    
    BYTE* decryptedAESKey = NULL;
    DWORD decryptedAESKeyLen = 0;
    if (DecryptAESKey(*hPrivateKey, encryptedAESKey, encryptedAESKeyLen, &decryptedAESKey, &decryptedAESKeyLen)) {
        printf("Decrypted AES Key: ");
        for (DWORD i = 0; i < decryptedAESKeyLen; i++) {
            printf("%02X", decryptedAESKey[i]);
        }
        printf("\n");
        free(decryptedAESKey);
    } else {
        printf("Failed to decrypt AES key\n");
    }
    CryptReleaseContext(hProv, 0);
    return 0;
}

GPT ๊ฐ€ ์งœ์ค€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋ฉด

๐Ÿ‘๐Ÿ‘๐Ÿ‘

aes_key = bytes.fromhex('68D71403FA7BBC9E7437A13709CFBCE0B0DE984FADD5F729384DCE682A6ACD42')
print(f'Decrypted aes key : ', len(aes_key), aes_key.hex())
i = 4 + size


cipher = AES.new(aes_key, AES.MODE_CBC)

out = b''
while i < len(enc):
    data = enc[i:i+1024]
    out += cipher.decrypt(data)
    i += 1024
open('./important.pdf', 'wb').write(out)

IV ๋•œ์— ๋งจ ์•ž 16๋ฐ”์ดํŠธ๊ฐ€ ๊นจ์ง„๋‹ค.

์ •์ƒ pdf ํŒŒ์ผ ์•ž๋ถ€๋ถ„์œผ๋กœ ๋ฐ”๊ฟ”์น˜๊ธฐ

๋ณต๊ตฌ ์™„๋ฃŒ~

profile
์˜ค๋ฆฌ๋„ˆ๊ตฌ๋ฆฌ

0๊ฐœ์˜ ๋Œ“๊ธ€