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?。
我用 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 数组。
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?。