C 生成的 asm 调用指向错误的偏移量

C generated asm calls point to wrong offset

我用 C 写了一个弹出消息框的 shellcode。我已经编译了它的两个变体。一个说“你好世界!” (shellcodeA) 另一个说“再见世界!” (shellcodeB).

#define WIN32_LEAN_AND_MEAN

#pragma warning( disable : 4201 ) // Disable warning about 'nameless struct/union'

#include "GetProcAddressWithHash.h"

#include <Windows.h>

/** NOTE: module hashes are computed using all-caps unicode strings */
#define LDRLOADDLL_HASH                 0xbdbf9c13
#define LDRGETPROCADDRESS_HASH          0x5ed941b5

typedef int (WINAPI* MESSAGEBOXW)(HWND, LPCWSTR, LPCWSTR, UINT);
typedef NTSTATUS(WINAPI* LDRLOADDLL)(PWCHAR, ULONG, PUNICODE_STRING, PHANDLE);
typedef NTSTATUS(WINAPI* LDRGETPROCADDRESS)(HMODULE, PANSI_STRING, WORD, PVOID*);

#define FILL_STRING_WITH_BUF(string, buffer) \
    string.Length = sizeof(buffer); \
    string.MaximumLength = string.Length; \
    string.Buffer = (PCHAR)buffer

VOID Run()
{
#pragma warning( push )
#pragma warning( disable : 4055 ) // Ignore cast warnings

    // Function pointers
    LDRLOADDLL pLdrLoadDll = NULL;
    LDRGETPROCADDRESS pLdrGetProcAddress = NULL;
    MESSAGEBOXW pMessageBoxW = NULL;

    // General
    HANDLE hUser32;

    // String
    UNICODE_STRING uString = { 0 };
    STRING aString = { 0 };

    WCHAR sUser32[] = { 'u', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l' };

    BYTE sMessageBoxW[] = { 'M', 'e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'W', 0 };

    WCHAR sMsgContent[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
    WCHAR sMsgTitle[] = { 'D', 'e', 'm', 'o', '!', 0 };

    ///
    // STEP 1: locate all the required functions
    ///

    pLdrLoadDll = (LDRLOADDLL)GetProcAddressWithHash(LDRLOADDLL_HASH);
    pLdrGetProcAddress = (LDRGETPROCADDRESS)GetProcAddressWithHash(LDRGETPROCADDRESS_HASH);

    uString.Buffer = sUser32;
    uString.MaximumLength = sizeof(sUser32);
    uString.Length = sizeof(sUser32);

    pLdrLoadDll(NULL, 0, &uString, &hUser32);

    FILL_STRING_WITH_BUF(aString, sMessageBoxW);
    pLdrGetProcAddress(hUser32, &aString, 0, (PVOID*)&pMessageBoxW);

    ///
    // STEP 2: pop messagebox
    ///

    pMessageBoxW(NULL, sMsgContent, sMsgTitle, 0x00000000L);
}

现在我正在尝试编写一个生成第三段 shellcode 的 c++ 程序,该 shellcode 将 shellcode A 和 B 粘合在一起。我这样做的方法是让一段 bootstrap asm 调用 shellcodeA,然后调用 shellcodeB。所以它在内存中看起来像这样:

    // Bootstrap shellcode
    // shellCodeA
    // shellCodeB

程序如下:

#include <cstdio>
#include <fstream>

#include "Windows.h"

BOOL ConvertToShellcode(LPSTR& outBytes, DWORD& outLength)
{
    //MARKER:S
    LPSTR shellCodeA32 = const_cast<LPSTR>("\x83\xEC\x60\x53\x55\x56\x57\x6A\x75\x58\x6A\x73\x59\x6A\x65\x5B\x6A\x72\x5F\x6A\x33\x66\x89\x44\x24\x44\x58\x6A\x32\x66\x89\x44\x24\x4C\x58\x6A\x2E\x66\x89\x44\x24\x4E\x58\x6A\x64\x5E\x6A\x6C\x5A\x6A\x6F\x83\x64\x24\x14\x00\x66\x89\x5C\x24\x48\x88\x5C\x24\x2D\x88\x5C\x24\x32\x5B\x6A\x57\x66\x89\x4C\x24\x46\x66\x89\x44\x24\x50\x88\x4C\x24\x2E\x88\x4C\x24\x2F\x59\x6A\x48\x58\x6A\x65\x5D\x6A\x20\x66\x89\x44\x24\x58\x58\x6A\x21\x66\x89\x44\x24\x62\x33\xC0\x88\x4C\x24\x36\x66\x89\x4C\x24\x64\x59\x6A\x44\x66\x89\x44\x24\x70\x58\x66\x89\x44\x24\x34\x6A\x6D\x58\x66\x89\x44\x24\x38\x33\xC0\x66\x89\x7C\x24\x46\x66\x89\x74\x24\x4E\x66\x89\x54\x24\x50\x66\x89\x54\x24\x52\xC6\x44\x24\x28\x4D\x66\xC7\x44\x24\x2C\x61\x67\xC6\x44\x24\x2F\x42\x88\x5C\x24\x30\xC6\x44\x24\x31\x78\xC6\x44\x24\x33\x00\x66\x89\x6C\x24\x56\x66\x89\x54\x24\x58\x66\x89\x54\x24\x5A\x66\x89\x5C\x24\x5C\x66\x89\x5C\x24\x62\x66\x89\x7C\x24\x64\x66\x89\x54\x24\x66\x66\x89\x74\x24\x68\x66\x89\x4C\x24\x6A\x66\x89\x6C\x24\x36\x66\x89\x5C\x24\x3A\x66\x89\x4C\x24\x3C\x66\x89\x44\x24\x3E\xB9\x13\x9C\xBF\xBD\xE8\x71\x00\x00\x00\xB9\xB5\x41\xD9\x5E\x8B\xF0\xE8\x65\x00\x00\x00\x8B\xF8\x33\xDB\x6A\x14\x8D\x44\x24\x44\x89\x44\x24\x20\x58\x66\x89\x44\x24\x1A\x66\x89\x44\x24\x18\x8D\x44\x24\x14\x50\x8D\x44\x24\x1C\x50\x53\x53\xFF\xD6\x6A\x0C\x58\x66\x89\x44\x24\x20\x66\x89\x44\x24\x22\x8D\x44\x24\x28\x89\x44\x24\x24\x8D\x44\x24\x10\x50\x53\x8D\x44\x24\x28\x50\xFF\x74\x24\x20\xFF\xD7\x53\x8D\x44\x24\x38\x50\x8D\x44\x24\x5C\x50\x53\xFF\x54\x24\x20\x5F\x5E\x5D\x5B\x83\xC4\x60\xC3\x83\xEC\x14\x64\xA1\x30\x00\x00\x00\x53\x55\x56\x8B\x40\x0C\x57\x89\x4C\x24\x1C\x8B\x78\x0C\xE9\xA5\x00\x00\x00\x8B\x47\x30\x33\xF6\x8B\x5F\x2C\x8B\x3F\x89\x44\x24\x10\x8B\x42\x3C\x89\x7C\x24\x14\x8B\x6C\x10\x78\x89\x6C\x24\x18\x85\xED\x0F\x84\x80\x00\x00\x00\xC1\xEB\x10\x33\xC9\x85\xDB\x74\x2F\x8B\x7C\x24\x10\x0F\xBE\x2C\x0F\xC1\xCE\x0D\x80\x3C\x0F\x61\x89\x6C\x24\x10\x7C\x09\x8B\xC5\x83\xC0\xE0\x03\xF0\xEB\x04\x03\x74\x24\x10\x41\x3B\xCB\x72\xDD\x8B\x7C\x24\x14\x8B\x6C\x24\x18\x8B\x44\x2A\x20\x33\xDB\x8B\x4C\x2A\x18\x03\xC2\x89\x4C\x24\x10\x85\xC9\x74\x34\x8B\x38\x33\xED\x03\xFA\x83\xC0\x04\x89\x44\x24\x20\x8A\x0F\xC1\xCD\x0D\x0F\xBE\xC1\x03\xE8\x47\x84\xC9\x75\xF1\x8B\x7C\x24\x14\x8D\x04\x2E\x3B\x44\x24\x1C\x74\x20\x8B\x44\x24\x20\x43\x3B\x5C\x24\x10\x72\xCC\x8B\x57\x18\x85\xD2\x0F\x85\x50\xFF\xFF\xFF\x33\xC0\x5F\x5E\x5D\x5B\x83\xC4\x14\xC3\x8B\x74\x24\x18\x8B\x44\x16\x24\x8D\x04\x58\x0F\xB7\x0C\x10\x8B\x44\x16\x1C\x8D\x04\x88\x8B\x04\x10\x03\xC2\xEB\xDB");
    LPSTR shellCodeA64 = const_cast<LPSTR>("\x48\x89\x5C\x24\x18\x48\x89\x7C\x24\x20\x55\x48\x8D\x6C\x24\xA9\x48\x81\xEC\xA0\x00\x00\x00\x33\xDB\xC7\x45\x17\x75\x00\x73\x00\xB9\x13\x9C\xBF\xBD\x48\x89\x5D\x67\x89\x5D\xFB\x89\x5D\x0B\x66\x89\x5D\x47\xC7\x45\x1B\x65\x00\x72\x00\xC7\x45\x1F\x33\x00\x32\x00\xC7\x45\x23\x2E\x00\x64\x00\xC7\x45\x27\x6C\x00\x6C\x00\xC7\x45\xD7\x4D\x65\x73\x73\xC7\x45\xDB\x61\x67\x65\x42\xC7\x45\xDF\x6F\x78\x57\x00\xC7\x45\x2F\x48\x00\x65\x00\xC7\x45\x33\x6C\x00\x6C\x00\xC7\x45\x37\x6F\x00\x20\x00\xC7\x45\x3B\x57\x00\x6F\x00\xC7\x45\x3F\x72\x00\x6C\x00\xC7\x45\x43\x64\x00\x21\x00\xC7\x45\xE7\x44\x00\x65\x00\xC7\x45\xEB\x6D\x00\x6F\x00\xC7\x45\xEF\x21\x00\x00\x00\xE8\x74\x00\x00\x00\xB9\xB5\x41\xD9\x5E\x48\x8B\xD8\xE8\x67\x00\x00\x00\x48\x8B\xF8\xC7\x45\xF7\x14\x00\x14\x00\x48\x8D\x45\x17\x33\xD2\x4C\x8D\x4D\x6F\x48\x89\x45\xFF\x4C\x8D\x45\xF7\x33\xC9\xFF\xD3\x48\x8B\x4D\x6F\x48\x8D\x45\xD7\x45\x33\xC0\x48\x89\x45\x0F\x4C\x8D\x4D\x67\xC7\x45\x07\x0C\x00\x0C\x00\x48\x8D\x55\x07\xFF\xD7\x45\x33\xC9\x4C\x8D\x45\xE7\x48\x8D\x55\x2F\x33\xC9\xFF\x55\x67\x4C\x8D\x9C\x24\xA0\x00\x00\x00\x49\x8B\x5B\x20\x49\x8B\x7B\x28\x49\x8B\xE3\x5D\xC3\xCC\xCC\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x10\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x8B\xE9\x45\x33\xF6\x48\x8B\x50\x18\x4C\x8B\x4A\x10\x4D\x8B\x41\x30\x4D\x85\xC0\x0F\x84\xB3\x00\x00\x00\x41\x0F\x10\x41\x58\x49\x63\x40\x3C\x41\x8B\xD6\x4D\x8B\x09\xF3\x0F\x7F\x04\x24\x46\x8B\x9C\x00\x88\x00\x00\x00\x45\x85\xDB\x74\xD2\x48\x8B\x04\x24\x48\xC1\xE8\x10\x66\x44\x3B\xF0\x73\x22\x48\x8B\x4C\x24\x08\x44\x0F\xB7\xD0\x0F\xBE\x01\xC1\xCA\x0D\x80\x39\x61\x7C\x03\x83\xC2\xE0\x03\xD0\x48\xFF\xC1\x49\x83\xEA\x01\x75\xE7\x4F\x8D\x14\x18\x45\x8B\xDE\x41\x8B\x7A\x20\x49\x03\xF8\x45\x39\x72\x18\x76\x8E\x8B\x37\x41\x8B\xDE\x49\x03\xF0\x48\x8D\x7F\x04\x0F\xBE\x0E\x48\xFF\xC6\xC1\xCB\x0D\x03\xD9\x84\xC9\x75\xF1\x8D\x04\x13\x3B\xC5\x74\x0E\x41\xFF\xC3\x45\x3B\x5A\x18\x72\xD5\xE9\x5E\xFF\xFF\xFF\x41\x8B\x42\x24\x43\x8D\x0C\x1B\x49\x03\xC0\x0F\xB7\x14\x01\x41\x8B\x4A\x1C\x49\x03\xC8\x8B\x04\x91\x49\x03\xC0\xEB\x02\x33\xC0\x48\x8B\x5C\x24\x20\x48\x8B\x6C\x24\x28\x48\x8B\x74\x24\x30\x48\x8B\x7C\x24\x38\x48\x83\xC4\x10\x41\x5E\xC3");
    LPSTR shellCodeB32 = const_cast<LPSTR>("\x83\xEC\x64\x53\x55\x56\x57\x6A\x75\x58\x6A\x73\x59\x6A\x65\x5B\x6A\x72\x5F\x6A\x33\x66\x89\x44\x24\x44\x58\x6A\x32\x66\x89\x44\x24\x4C\x58\x6A\x2E\x66\x89\x44\x24\x4E\x58\x6A\x64\x5E\x6A\x6C\x5A\x6A\x6F\x83\x64\x24\x14\x00\x66\x89\x5C\x24\x48\x88\x5C\x24\x2D\x88\x5C\x24\x32\x5B\x6A\x57\x66\x89\x4C\x24\x46\x66\x89\x44\x24\x50\x88\x4C\x24\x2E\x88\x4C\x24\x2F\x59\x6A\x47\x58\x6A\x62\x66\x89\x44\x24\x58\x58\x6A\x79\x66\x89\x44\x24\x60\x58\x6A\x65\x5D\x6A\x20\x66\x89\x44\x24\x62\x58\x6A\x21\x88\x4C\x24\x36\x66\x89\x44\x24\x66\x33\xC0\x66\x89\x4C\x24\x68\x59\x6A\x44\x66\x89\x44\x24\x74\x58\x66\x89\x7C\x24\x46\x66\x89\x74\x24\x4E\x66\x89\x54\x24\x50\x66\x89\x54\x24\x52\xC6\x44\x24\x28\x4D\x66\xC7\x44\x24\x2C\x61\x67\xC6\x44\x24\x2F\x42\x88\x5C\x24\x30\xC6\x44\x24\x31\x78\xC6\x44\x24\x33\x00\x66\x89\x5C\x24\x56\x66\x89\x5C\x24\x58\x66\x89\x74\x24\x5A\x66\x89\x6C\x24\x60\x66\x89\x5C\x24\x66\x66\x89\x7C\x24\x68\x66\x89\x54\x24\x6A\x66\x89\x74\x24\x6C\x66\x89\x4C\x24\x6E\x66\x89\x44\x24\x34\x66\x89\x6C\x24\x36\x6A\x6D\x58\x66\x89\x44\x24\x38\x33\xC0\x66\x89\x4C\x24\x3C\xB9\x13\x9C\xBF\xBD\x66\x89\x5C\x24\x3A\x66\x89\x44\x24\x3E\xE8\x71\x00\x00\x00\xB9\xB5\x41\xD9\x5E\x8B\xF0\xE8\x65\x00\x00\x00\x8B\xF8\x33\xDB\x6A\x14\x8D\x44\x24\x44\x89\x44\x24\x20\x58\x66\x89\x44\x24\x1A\x66\x89\x44\x24\x18\x8D\x44\x24\x14\x50\x8D\x44\x24\x1C\x50\x53\x53\xFF\xD6\x6A\x0C\x58\x66\x89\x44\x24\x20\x66\x89\x44\x24\x22\x8D\x44\x24\x28\x89\x44\x24\x24\x8D\x44\x24\x10\x50\x53\x8D\x44\x24\x28\x50\xFF\x74\x24\x20\xFF\xD7\x53\x8D\x44\x24\x38\x50\x8D\x44\x24\x5C\x50\x53\xFF\x54\x24\x20\x5F\x5E\x5D\x5B\x83\xC4\x64\xC3\x83\xEC\x14\x64\xA1\x30\x00\x00\x00\x53\x55\x56\x8B\x40\x0C\x57\x89\x4C\x24\x1C\x8B\x78\x0C\xE9\xA5\x00\x00\x00\x8B\x47\x30\x33\xF6\x8B\x5F\x2C\x8B\x3F\x89\x44\x24\x10\x8B\x42\x3C\x89\x7C\x24\x14\x8B\x6C\x10\x78\x89\x6C\x24\x18\x85\xED\x0F\x84\x80\x00\x00\x00\xC1\xEB\x10\x33\xC9\x85\xDB\x74\x2F\x8B\x7C\x24\x10\x0F\xBE\x2C\x0F\xC1\xCE\x0D\x80\x3C\x0F\x61\x89\x6C\x24\x10\x7C\x09\x8B\xC5\x83\xC0\xE0\x03\xF0\xEB\x04\x03\x74\x24\x10\x41\x3B\xCB\x72\xDD\x8B\x7C\x24\x14\x8B\x6C\x24\x18\x8B\x44\x2A\x20\x33\xDB\x8B\x4C\x2A\x18\x03\xC2\x89\x4C\x24\x10\x85\xC9\x74\x34\x8B\x38\x33\xED\x03\xFA\x83\xC0\x04\x89\x44\x24\x20\x8A\x0F\xC1\xCD\x0D\x0F\xBE\xC1\x03\xE8\x47\x84\xC9\x75\xF1\x8B\x7C\x24\x14\x8D\x04\x2E\x3B\x44\x24\x1C\x74\x20\x8B\x44\x24\x20\x43\x3B\x5C\x24\x10\x72\xCC\x8B\x57\x18\x85\xD2\x0F\x85\x50\xFF\xFF\xFF\x33\xC0\x5F\x5E\x5D\x5B\x83\xC4\x14\xC3\x8B\x74\x24\x18\x8B\x44\x16\x24\x8D\x04\x58\x0F\xB7\x0C\x10\x8B\x44\x16\x1C\x8D\x04\x88\x8B\x04\x10\x03\xC2\xEB\xDB");
    LPSTR shellCodeB64 = const_cast<LPSTR>("\x48\x89\x5C\x24\x18\x48\x89\x7C\x24\x20\x55\x48\x8D\x6C\x24\xA9\x48\x81\xEC\xA0\x00\x00\x00\x33\xDB\xC7\x45\x17\x75\x00\x73\x00\xB9\x13\x9C\xBF\xBD\x48\x89\x5D\x67\x89\x5D\xFB\x89\x5D\x0B\x66\x89\x5D\x4B\xC7\x45\x1B\x65\x00\x72\x00\xC7\x45\x1F\x33\x00\x32\x00\xC7\x45\x23\x2E\x00\x64\x00\xC7\x45\x27\x6C\x00\x6C\x00\xC7\x45\xD7\x4D\x65\x73\x73\xC7\x45\xDB\x61\x67\x65\x42\xC7\x45\xDF\x6F\x78\x57\x00\xC7\x45\x2F\x47\x00\x6F\x00\xC7\x45\x33\x6F\x00\x64\x00\xC7\x45\x37\x62\x00\x79\x00\xC7\x45\x3B\x65\x00\x20\x00\xC7\x45\x3F\x57\x00\x6F\x00\xC7\x45\x43\x72\x00\x6C\x00\xC7\x45\x47\x64\x00\x21\x00\xC7\x45\xE7\x44\x00\x65\x00\xC7\x45\xEB\x6D\x00\x6F\x00\xC7\x45\xEF\x21\x00\x00\x00\xE8\x75\x00\x00\x00\xB9\xB5\x41\xD9\x5E\x48\x8B\xD8\xE8\x68\x00\x00\x00\x48\x8B\xF8\xC7\x45\xF7\x14\x00\x14\x00\x48\x8D\x45\x17\x33\xD2\x4C\x8D\x4D\x6F\x48\x89\x45\xFF\x4C\x8D\x45\xF7\x33\xC9\xFF\xD3\x48\x8B\x4D\x6F\x48\x8D\x45\xD7\x45\x33\xC0\x48\x89\x45\x0F\x4C\x8D\x4D\x67\xC7\x45\x07\x0C\x00\x0C\x00\x48\x8D\x55\x07\xFF\xD7\x45\x33\xC9\x4C\x8D\x45\xE7\x48\x8D\x55\x2F\x33\xC9\xFF\x55\x67\x4C\x8D\x9C\x24\xA0\x00\x00\x00\x49\x8B\x5B\x20\x49\x8B\x7B\x28\x49\x8B\xE3\x5D\xC3\xCC\xCC\xCC\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x10\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x8B\xE9\x45\x33\xF6\x48\x8B\x50\x18\x4C\x8B\x4A\x10\x4D\x8B\x41\x30\x4D\x85\xC0\x0F\x84\xB3\x00\x00\x00\x41\x0F\x10\x41\x58\x49\x63\x40\x3C\x41\x8B\xD6\x4D\x8B\x09\xF3\x0F\x7F\x04\x24\x46\x8B\x9C\x00\x88\x00\x00\x00\x45\x85\xDB\x74\xD2\x48\x8B\x04\x24\x48\xC1\xE8\x10\x66\x44\x3B\xF0\x73\x22\x48\x8B\x4C\x24\x08\x44\x0F\xB7\xD0\x0F\xBE\x01\xC1\xCA\x0D\x80\x39\x61\x7C\x03\x83\xC2\xE0\x03\xD0\x48\xFF\xC1\x49\x83\xEA\x01\x75\xE7\x4F\x8D\x14\x18\x45\x8B\xDE\x41\x8B\x7A\x20\x49\x03\xF8\x45\x39\x72\x18\x76\x8E\x8B\x37\x41\x8B\xDE\x49\x03\xF0\x48\x8D\x7F\x04\x0F\xBE\x0E\x48\xFF\xC6\xC1\xCB\x0D\x03\xD9\x84\xC9\x75\xF1\x8D\x04\x13\x3B\xC5\x74\x0E\x41\xFF\xC3\x45\x3B\x5A\x18\x72\xD5\xE9\x5E\xFF\xFF\xFF\x41\x8B\x42\x24\x43\x8D\x0C\x1B\x49\x03\xC0\x0F\xB7\x14\x01\x41\x8B\x4A\x1C\x49\x03\xC8\x8B\x04\x91\x49\x03\xC0\xEB\x02\x33\xC0\x48\x8B\x5C\x24\x20\x48\x8B\x6C\x24\x28\x48\x8B\x74\x24\x30\x48\x8B\x7C\x24\x38\x48\x83\xC4\x10\x41\x5E\xC3");
    DWORD shellCodeA32Length = 629, shellCodeA64Length = 552;
    DWORD shellCodeB32Length = 645, shellCodeB64Length = 560;
    //MARKER:E

    LPSTR shellcodeA = shellCodeA32;
    LPSTR shellcodeB = shellCodeB32;
    DWORD shellcodeALength = shellCodeA32Length;
    DWORD shellcodeBLength = shellCodeB32Length;
    
    if (shellcodeA == NULL || shellcodeALength == 0) return FALSE;

    BYTE bootstrap[12] = { 0 };
    DWORD i = 0;

    // call - Transfer execution to shellCodeA
    bootstrap[i++] = 0xe8;
    bootstrap[i++] = sizeof(bootstrap) - i - 4; // Skip the remainder of instructions
    bootstrap[i++] = 0x00;
    bootstrap[i++] = 0x00;
    bootstrap[i++] = 0x00;
    
    // leave
    //bootstrap[i++] = 0xc9;

    // ret - return to caller
    //bootstrap[i++] = 0xc3;
    
    // call - Transfer execution to shellCodeB
    bootstrap[i++] = 0xe8;
    bootstrap[i++] = sizeof(bootstrap) + shellcodeALength - i - 4; // Skip the remainder of instructions
    bootstrap[i++] = 0x00;
    bootstrap[i++] = 0x00;
    bootstrap[i++] = 0x00;

    // leave
    bootstrap[i++] = 0xc9;

    // ret - return to caller
    bootstrap[i++] = 0xc3;

    // Ends up looking like this in memory:
    // Bootstrap shellcode
    // shellCodeA
    // shellCodeB
    outLength = sizeof(bootstrap) + shellcodeALength + shellcodeBLength;
    outBytes = (LPSTR)malloc(outLength);
    MoveMemory(outBytes, bootstrap, sizeof(bootstrap));
    MoveMemory(outBytes + sizeof(bootstrap), shellcodeA, shellcodeALength);
    MoveMemory(outBytes + sizeof(bootstrap) + shellcodeALength, shellcodeB, shellcodeBLength);

    return TRUE;
}

typedef UINT_PTR(WINAPI* SHC)();

int main()
{
    LPSTR           finalShellcode = NULL;
    DWORD           finalSize;
    DWORD           dwOldProtect1 = 0;
    SYSTEM_INFO     sysInfo;
    BOOL            status;
    std::fstream    outFile;
    DWORD           dLastError;
    
    status = ConvertToShellcode(finalShellcode, finalSize);
    if (!status) {
        printf("[!] Failed to convert shellcode\n");
        goto Cleanup;
    }

    outFile = std::fstream(R"(../bin/FinalShellcode_x86.bin)",
        std::ios::out | std::ios::binary);
    outFile.write(finalShellcode, finalSize);
    outFile.close();

    GetNativeSystemInfo(&sysInfo);

    status = VirtualProtect(finalShellcode, sysInfo.dwPageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect1);
    if (status) {
        SHC shc = (SHC)(finalShellcode);

        printf("[+] Executing shell code\n");
        HMODULE hLoadedShc = (HMODULE)shc(); // Excute shellcode

        status = 1;
        goto Cleanup;
    }

    dLastError = GetLastError();

Cleanup:
    if (finalShellcode)
        free(finalShellcode);

    return !status;
}

因此,当我 运行 shellcode 时,ConvertToShellcode 函数生成的 shellcodeA 被调用,我看到一个带有“Hello world!”的消息框。但是当它调用 shellcodeB 时,我得到了一个访问冲突错误。当我使用 blob运行ner 检查在 IDA 中分配 shellcode 的缓冲区时,我发现了这个:

我可以看到第一个调用指向一个有效的函数。但是第二个调用指向第一个 shellcode 中的某处,而不是第二个。我看到 shellcodeA 的子程序从 0x6A000C 开始。 ShellcodeA 的长度为 629 字节,因此 ShellcodeB 应该从 0x6A0281 开始。而不是在 0x6A007E。 0x6A0281 看起来是正确的。我可以看到 user32.dll 数组。 如果我们现在再看一下 cpp 程序。如果我使用 msvc 调试它: 我可以看到 sizeof(bootstrap) + shellcodeALength - i - 4 的值等于 0x119,即 281 这不可能是真的,因为 ShellcodeA 大约有 600 字节长。如果我手动计算 sizeof(bootstrap) + shellcodeALength - i - 4 我得到 631,即十六进制的 0x277。在这一点上,我有一种混淆十六进制和整数的感觉,但结果完全不同。这里的任何人都可以指出我正确的方向,因为我不知道该怎么做。我也已经尝试手动将调用设置为正确的偏移量,但我没有得到不同的结果。

编辑: 这里有一个 link 到 github 项目,因此您可以根据需要编译程序和 shellcode。 https://github.com/11philip22/asmGlue/

我不知道你在哪里看到值 0x119,但是 BYTE bootstrap[12] 是一个 BYTE 数组。

因此分配 bootstrap[i++] = sizeof(bootstrap) + shellcodeALength - i - 4; 会将表达式的最低字节存储在 bootstrap[i++] 中并忽略其余部分,因此永远不会超过 255。

您可能想要这样的东西:

DWORD offset = sizeof(bootstrap) + shellcodeALength - i - 4;
bootstrap[i++] = (BYTE)offset;
bootstrap[i++] = (BYTE)(offset >> 8);
bootstrap[i++] = (BYTE)(offset >> 16);
bootstrap[i++] = (BYTE)(offset >> 24);

另外如评论中所述,避免在同一语句中使用 i++i - 有关详细信息,请参阅 What are “sequence points” and how do they affect undefined behavior?