如何创建我可以在不指定入口点的情况下使用 rundll32.exe 运行的本机 C++ DLL

问题描述

我将如何创建可以使用 rundll32.exe 执行的本机 dll 而无需指定入口点:

示例:

C: \> rundll32.exe mydll.dll

我在 Visual Studio 上创建了一个 DLL 项目,但我不知道将代码放在哪里:

  • 由 Visual Studio 生成的 DLL 项目模板
// dllmain.cpp : Définit le point d'entrée de l'application DLL.
#include "pch.h"

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
  • 我想与 dll 一起运行的代码:
#include <stdio.h>
#include <stdlib.h>

// enable cross compiling
#ifdef __linux__
#include <sys/mman.h>
#elif _WIN32 || _MINGW_
#include <windows.h>
#endif


void main()
{
    const char shellcode[] = "\x48\x83\xec\x48\x48\x83\xe4\xf0\x4c\x8d\x44\x24\x28\x48\x8d\x15\xda\x01\x00\x00\x48\x8d\x0d\xc6\x01\x00\x00\xe8\x64\x00\x00\x00\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x30\x48\x8d\x15\xca\x01\x00\x00\x48\x8d\x0d\xa9\x01\x00\x00\xe8\x47\x00\x00\x00\x48\x8d\x0d\xc3\x01\x00\x00\xff\x54\x24\x28\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x38\x48\x8d\x15\xb9\x01\x00\x00\x48\x8d\x0d\xa7\x01\x00\x00\xe8\x1f\x00\x00\x00\x4d\x31\xc9\x4c\x8d\x05\xcb\x01\x00\x00\x48\x8d\x15\xa8\x01\x00\x00\x48\x31\xc9\xff\x54\x24\x38\x48\x31\xc9\xff\x54\x24\x30\x48\x81\xec\x68\x01\x00\x00\x48\x89\x5c\x24\x28\x48\x89\x6c\x24\x30\x48\x89\x7c\x24\x38\x48\x89\x74\x24\x40\x4c\x89\x64\x24\x48\x4c\x89\x6c\x24\x50\x4c\x89\x74\x24\x58\x4c\x89\x7c\x24\x60\x65\x4c\x8b\x1c\x25\x60\x00\x00\x00\x4d\x8b\x5b\x18\x4d\x8d\x5b\x10\x4d\x89\xdf\x4d\x8b\x1b\xfc\x49\x8b\x7b\x60\x48\x89\xce\xac\x84\xc0\x74\x26\x8a\x27\x80\xfc\x61\x7c\x03\x80\xec\x20\x38\xc4\x75\x08\x48\xff\xc7\x48\xff\xc7\xeb\xe5\x4d\x8b\x1b\x4d\x39\xfb\x75\xd6\x48\x31\xc0\xe9\xb1\x00\x00\x00\x49\x8b\x5b\x30\x44\x8b\x63\x3c\x49\x01\xdc\x49\x81\xc4\x88\x00\x00\x00\x45\x8b\x2c\x24\x4d\x85\xed\x75\x08\x48\x31\xc0\xe9\x8e\x00\x00\x00\x4e\x8d\x1c\x2b\x45\x8b\x74\x24\x04\x4d\x01\xee\x41\x8b\x4b\x18\x45\x8b\x53\x20\x49\x01\xda\xff\xc9\x4d\x8d\x24\x8a\x41\x8b\x3c\x24\x48\x01\xdf\x48\x89\xd6\xa6\x75\x08\x8a\x06\x84\xc0\x74\x09\xeb\xf5\xe2\xe5\x48\x31\xc0\xeb\x55\x45\x8b\x63\x24\x49\x01\xdc\x66\x41\x8b\x0c\x4c\x45\x8b\x63\x1c\x49\x01\xdc\x41\x8b\x04\x8c\x4c\x39\xe8\x7c\x36\x4c\x39\xf0\x73\x31\x48\x8d\x34\x18\x48\x8d\x7c\x24\x68\xa4\x80\x3e\x2e\x75\xfa\xa4\xc7\x07\x44\x4c\x4c\x00\x4d\x89\xc6\x48\x8d\x4c\x24\x68\x41\xff\xd1\x4d\x89\xf0\x48\x8d\x4c\x24\x68\x48\x89\xf2\xe9\x08\xff\xff\xff\x48\x01\xd8\x49\x89\x00\x48\x8b\x5c\x24\x28\x48\x8b\x6c\x24\x30\x48\x8b\x7c\x24\x38\x48\x8b\x74\x24\x40\x4c\x8b\x64\x24\x48\x4c\x8b\x6c\x24\x50\x4c\x8b\x74\x24\x58\x4c\x8b\x7c\x24\x60\x48\x81\xc4\x68\x01\x00\x00\xc3\x4b\x45\x52\x4e\x45\x4c\x33\x32\x2e\x44\x4c\x4c\x00\x4c\x6f\x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00\x55\x53\x45\x52\x33\x32\x2e\x44\x4c\x4c\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x00\x48\x69\x20\x66\x72\x6f\x6d\x20\x69\x6e\x6a\x65\x63\x74\x65\x64\x20\x73\x68\x65\x6c\x6c\x63\x6f\x64\x65\x21\x00\x53\x68\x65\x6c\x6c\x63\x6f\x64\x65\x54\x6f\x4a\x53\x63\x72\x69\x70\x74\x20\x50\x6f\x43\x20\x00";
    PVOID shellcode_exec = VirtualAlloc(0,sizeof shellcode,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    RtlCopyMemory(shellcode_exec,shellcode,sizeof shellcode);
    DWORD threadID;
    HANDLE hThread = CreateThread(NULL,(PTHREAD_START_ROUTINE)shellcode_exec,NULL,&threadID);
    WaitForSingleObject(hThread,INFINITE);
}

解决方法

rundll32 的入口点参数非可选,必须指定入口点,否则rundll32 不知道调用哪个函数。没有“默认”入口点。

要被 rundll32 调用,您必须导出具有以下签名之一的函数:

void CALLBACK EntryPoint(HWND hwnd,HINSTANCE hinst,LPSTR pszCmdLine,int nCmdShow)
void CALLBACK EntryPointA(HWND hwnd,int nCmdShow)
void CALLBACK EntryPointW(HWND hwnd,LPWSTR pszCmdLine,int nCmdShow)

例如:

#include "pch.h"

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

__declspec(dllexport) void CALLBACK myFunc(HWND,HINSTANCE,LPSTR,int)
{
    const char shellcode[] = "\x48\x83\xec\x48\x48\x83\xe4\xf0\x4c\x8d\x44\x24\x28\x48\x8d\x15\xda\x01\x00\x00\x48\x8d\x0d\xc6\x01\x00\x00\xe8\x64\x00\x00\x00\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x30\x48\x8d\x15\xca\x01\x00\x00\x48\x8d\x0d\xa9\x01\x00\x00\xe8\x47\x00\x00\x00\x48\x8d\x0d\xc3\x01\x00\x00\xff\x54\x24\x28\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x38\x48\x8d\x15\xb9\x01\x00\x00\x48\x8d\x0d\xa7\x01\x00\x00\xe8\x1f\x00\x00\x00\x4d\x31\xc9\x4c\x8d\x05\xcb\x01\x00\x00\x48\x8d\x15\xa8\x01\x00\x00\x48\x31\xc9\xff\x54\x24\x38\x48\x31\xc9\xff\x54\x24\x30\x48\x81\xec\x68\x01\x00\x00\x48\x89\x5c\x24\x28\x48\x89\x6c\x24\x30\x48\x89\x7c\x24\x38\x48\x89\x74\x24\x40\x4c\x89\x64\x24\x48\x4c\x89\x6c\x24\x50\x4c\x89\x74\x24\x58\x4c\x89\x7c\x24\x60\x65\x4c\x8b\x1c\x25\x60\x00\x00\x00\x4d\x8b\x5b\x18\x4d\x8d\x5b\x10\x4d\x89\xdf\x4d\x8b\x1b\xfc\x49\x8b\x7b\x60\x48\x89\xce\xac\x84\xc0\x74\x26\x8a\x27\x80\xfc\x61\x7c\x03\x80\xec\x20\x38\xc4\x75\x08\x48\xff\xc7\x48\xff\xc7\xeb\xe5\x4d\x8b\x1b\x4d\x39\xfb\x75\xd6\x48\x31\xc0\xe9\xb1\x00\x00\x00\x49\x8b\x5b\x30\x44\x8b\x63\x3c\x49\x01\xdc\x49\x81\xc4\x88\x00\x00\x00\x45\x8b\x2c\x24\x4d\x85\xed\x75\x08\x48\x31\xc0\xe9\x8e\x00\x00\x00\x4e\x8d\x1c\x2b\x45\x8b\x74\x24\x04\x4d\x01\xee\x41\x8b\x4b\x18\x45\x8b\x53\x20\x49\x01\xda\xff\xc9\x4d\x8d\x24\x8a\x41\x8b\x3c\x24\x48\x01\xdf\x48\x89\xd6\xa6\x75\x08\x8a\x06\x84\xc0\x74\x09\xeb\xf5\xe2\xe5\x48\x31\xc0\xeb\x55\x45\x8b\x63\x24\x49\x01\xdc\x66\x41\x8b\x0c\x4c\x45\x8b\x63\x1c\x49\x01\xdc\x41\x8b\x04\x8c\x4c\x39\xe8\x7c\x36\x4c\x39\xf0\x73\x31\x48\x8d\x34\x18\x48\x8d\x7c\x24\x68\xa4\x80\x3e\x2e\x75\xfa\xa4\xc7\x07\x44\x4c\x4c\x00\x4d\x89\xc6\x48\x8d\x4c\x24\x68\x41\xff\xd1\x4d\x89\xf0\x48\x8d\x4c\x24\x68\x48\x89\xf2\xe9\x08\xff\xff\xff\x48\x01\xd8\x49\x89\x00\x48\x8b\x5c\x24\x28\x48\x8b\x6c\x24\x30\x48\x8b\x7c\x24\x38\x48\x8b\x74\x24\x40\x4c\x8b\x64\x24\x48\x4c\x8b\x6c\x24\x50\x4c\x8b\x74\x24\x58\x4c\x8b\x7c\x24\x60\x48\x81\xc4\x68\x01\x00\x00\xc3\x4b\x45\x52\x4e\x45\x4c\x33\x32\x2e\x44\x4c\x4c\x00\x4c\x6f\x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00\x55\x53\x45\x52\x33\x32\x2e\x44\x4c\x4c\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x00\x48\x69\x20\x66\x72\x6f\x6d\x20\x69\x6e\x6a\x65\x63\x74\x65\x64\x20\x73\x68\x65\x6c\x6c\x63\x6f\x64\x65\x21\x00\x53\x68\x65\x6c\x6c\x63\x6f\x64\x65\x54\x6f\x4a\x53\x63\x72\x69\x70\x74\x20\x50\x6f\x43\x20\x00";
    PVOID shellcode_exec = VirtualAlloc(0,sizeof shellcode,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
    if (shellcode_exec) {
        RtlCopyMemory(shellcode_exec,shellcode,sizeof shellcode);
        DWORD dwOldProtect;
        if (VirtualProtect(shellcode_exec,PAGE_EXECUTE,&dwOldProtect)) {
            FlushInstructionCache(GetCurrentProcess(),shellcode_exec,sizeof shellcode);
            DWORD threadID;
            HANDLE hThread = CreateThread(NULL,(PTHREAD_START_ROUTINE)shellcode_exec,NULL,&threadID);
            if (hThread) {
                WaitForSingleObject(hThread,INFINITE);
                CloseHandle(hThread);
            }
        }
        VirtualFree(shellcode_exec,MEM_RELEASE);
    }
}
C: \> rundll32.exe mydll.dll,myFunc <optional parameters here>

仅供参考,您实际上根本不需要工作线程,您可以像执行任何其他函数一样直接执行 shell 代码:

__declspec(dllexport) void CALLBACK myFunc(HWND hwnd,int nCmdShow)
{
    const char shellcode[] = "\x48\x83\xec\x48\x48\x83\xe4\xf0\x4c\x8d\x44\x24\x28\x48\x8d\x15\xda\x01\x00\x00\x48\x8d\x0d\xc6\x01\x00\x00\xe8\x64\x00\x00\x00\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x30\x48\x8d\x15\xca\x01\x00\x00\x48\x8d\x0d\xa9\x01\x00\x00\xe8\x47\x00\x00\x00\x48\x8d\x0d\xc3\x01\x00\x00\xff\x54\x24\x28\x4c\x8b\x4c\x24\x28\x4c\x8d\x44\x24\x38\x48\x8d\x15\xb9\x01\x00\x00\x48\x8d\x0d\xa7\x01\x00\x00\xe8\x1f\x00\x00\x00\x4d\x31\xc9\x4c\x8d\x05\xcb\x01\x00\x00\x48\x8d\x15\xa8\x01\x00\x00\x48\x31\xc9\xff\x54\x24\x38\x48\x31\xc9\xff\x54\x24\x30\x48\x81\xec\x68\x01\x00\x00\x48\x89\x5c\x24\x28\x48\x89\x6c\x24\x30\x48\x89\x7c\x24\x38\x48\x89\x74\x24\x40\x4c\x89\x64\x24\x48\x4c\x89\x6c\x24\x50\x4c\x89\x74\x24\x58\x4c\x89\x7c\x24\x60\x65\x4c\x8b\x1c\x25\x60\x00\x00\x00\x4d\x8b\x5b\x18\x4d\x8d\x5b\x10\x4d\x89\xdf\x4d\x8b\x1b\xfc\x49\x8b\x7b\x60\x48\x89\xce\xac\x84\xc0\x74\x26\x8a\x27\x80\xfc\x61\x7c\x03\x80\xec\x20\x38\xc4\x75\x08\x48\xff\xc7\x48\xff\xc7\xeb\xe5\x4d\x8b\x1b\x4d\x39\xfb\x75\xd6\x48\x31\xc0\xe9\xb1\x00\x00\x00\x49\x8b\x5b\x30\x44\x8b\x63\x3c\x49\x01\xdc\x49\x81\xc4\x88\x00\x00\x00\x45\x8b\x2c\x24\x4d\x85\xed\x75\x08\x48\x31\xc0\xe9\x8e\x00\x00\x00\x4e\x8d\x1c\x2b\x45\x8b\x74\x24\x04\x4d\x01\xee\x41\x8b\x4b\x18\x45\x8b\x53\x20\x49\x01\xda\xff\xc9\x4d\x8d\x24\x8a\x41\x8b\x3c\x24\x48\x01\xdf\x48\x89\xd6\xa6\x75\x08\x8a\x06\x84\xc0\x74\x09\xeb\xf5\xe2\xe5\x48\x31\xc0\xeb\x55\x45\x8b\x63\x24\x49\x01\xdc\x66\x41\x8b\x0c\x4c\x45\x8b\x63\x1c\x49\x01\xdc\x41\x8b\x04\x8c\x4c\x39\xe8\x7c\x36\x4c\x39\xf0\x73\x31\x48\x8d\x34\x18\x48\x8d\x7c\x24\x68\xa4\x80\x3e\x2e\x75\xfa\xa4\xc7\x07\x44\x4c\x4c\x00\x4d\x89\xc6\x48\x8d\x4c\x24\x68\x41\xff\xd1\x4d\x89\xf0\x48\x8d\x4c\x24\x68\x48\x89\xf2\xe9\x08\xff\xff\xff\x48\x01\xd8\x49\x89\x00\x48\x8b\x5c\x24\x28\x48\x8b\x6c\x24\x30\x48\x8b\x7c\x24\x38\x48\x8b\x74\x24\x40\x4c\x8b\x64\x24\x48\x4c\x8b\x6c\x24\x50\x4c\x8b\x74\x24\x58\x4c\x8b\x7c\x24\x60\x48\x81\xc4\x68\x01\x00\x00\xc3\x4b\x45\x52\x4e\x45\x4c\x33\x32\x2e\x44\x4c\x4c\x00\x4c\x6f\x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00\x55\x53\x45\x52\x33\x32\x2e\x44\x4c\x4c\x00\x4d\x65\x73\x73\x61\x67\x65\x42\x6f\x78\x41\x00\x48\x69\x20\x66\x72\x6f\x6d\x20\x69\x6e\x6a\x65\x63\x74\x65\x64\x20\x73\x68\x65\x6c\x6c\x63\x6f\x64\x65\x21\x00\x53\x68\x65\x6c\x6c\x63\x6f\x64\x65\x54\x6f\x4a\x53\x63\x72\x69\x70\x74\x20\x50\x6f\x43\x20\x00";
    PVOID shellcode_exec = VirtualAlloc(0,&dwOldProtect)) {
            PTHREAD_START_ROUTINE proc = (PTHREAD_START_ROUTINE) shellcode_exec;
            proc(NULL);
        }
        VirtualFree(shellcode_exec,MEM_RELEASE);
    }
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...