原始函数是这样的
kernel32!CreateProcessInternalW:
00000000`7738e750 4c8bdc mov r11,rsp
00000000`7738e753 53 push rbx
00000000`7738e754 56 push rsi
00000000`7738e755 57 push rdi
00000000`7738e756 4154 push r12
00000000`7738e758 4155 push r13
00000000`7738e75a 4156 push r14
00000000`7738e75c 4157 push r15
00000000`7738e75e 4881ec400b0000 sub rsp,0B40h
00000000`7738e765 488b0564cc0e00 mov rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]
跟32位一样,在函数入口写入跳转指令,跟32不一样的是,不能再用之前的E9 xx xx xx xx这样的指令了,E9不支持64位地址跳转,最大只能支持到32位,
直接用E9大部分情况下会出错.所以我们换一种方法.
mov rax,0x1122334455667788
jmp rax
机器码是48 b8 8877665544332211 ffe0总共占了12个字节,不是我们之前用E9跳转的5字节了.
最前面的48叫REX Prefix,大家可以GOOGLE下,4是固定的,8表示使用64位寄存器.
如果没有前面的48就变成了mov eax, 0x1122334455667788了,使用32位寄存器.
我们需要把函数前面12字节改成跳转指令,正好
00000000`7738e750 4c8bdc mov r11,rsp
00000000`7738e753 53 push rbx
00000000`7738e754 56 push rsi
00000000`7738e755 57 push rdi
00000000`7738e756 4154 push r12
00000000`7738e758 4155 push r13
00000000`7738e75a 4156 push r14
这12个字节是完整的7条指令,写入12字节指令,不会破坏后面的指令.
写入跳转指令后
kernel32!CreateProcessInternalW:
00000000`7738e750 48b8001055fbfe070000 mov rax,offset x64dll!FakeCreateProcessInternal (000007fe`fb551000)
00000000`7738e75a ffe0 jmp rax
00000000`7738e75c 4157 push r15
00000000`7738e75e 4881ec400b0000 sub rsp,0B40h
00000000`7738e765 488b0564cc0e00 mov rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]
00000000`7738e76c 4833c4 xor rax,rsp
00000000`7738e76f 48898424300b0000 mov qword ptr [rsp+0B30h],rax
00000000`7738e777 4889a42438050000 mov qword ptr [rsp+538h],rsp
完整代码如下.
少NTDLL.h的朋友可以去搜索下载,也可以把RtlAdjustPrivilege替换成AdjustTokenPrivileges,效果样的,只是代码多几行而已.
声明:本人很菜,水平有限,汇编功底也是相当的水,如发现有误人子弟之处,敬请指正.若您有更好的方法也请多多指教.
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <shlwapi.h>
#include <ntdll.h>
#pragma comment(lib, "shlwapi.lib")
#define CODE_LEN 12
TCHAR ModuleFile[MAX_PATH];
DWORD dwOldProtect;
BYTE OldCode[CODE_LEN] = {0x90};
typedef HANDLE (WINAPI *__CreateProcessInternal)(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken);
__CreateProcessInternal pfnCreateProcess = 0;
HANDLE WINAPI FakeCreateProcessInternal(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken)
{
MessageBox(NULL, lpCommandLine, lpApplicationName, MB_ICONASTERISK);
return pfnCreateProcess(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
::DisableThreadLibraryCalls(hinstDLL);
GetModuleFileName(NULL, ModuleFile, _countof(ModuleFile));
if (StrRStrI(ModuleFile, 0, TEXT("explorer.exe")))
{
pfnCreateProcess = (__CreateProcessInternal)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW");
::VirtualProtect(pfnCreateProcess, CODE_LEN, PAGE_EXECUTE_READWRITE, &dwOldProtect);
memcpy(OldCode, pfnCreateProcess, CODE_LEN);
memset(pfnCreateProcess, 0x90, CODE_LEN);
/*
mov rax, FakeCreateProcessInternal
jmp rax
*/
*(LPWORD)pfnCreateProcess = 0xb848;
*(INT64*)((INT64)pfnCreateProcess+2) = (INT64)FakeCreateProcessInternal;
*(LPWORD)((INT64)pfnCreateProcess+10) = 0xe0ff;
::VirtualProtect(pfnCreateProcess, CODE_LEN, dwOldProtect, NULL);
pfnCreateProcess = (__CreateProcessInternal)VirtualAlloc(NULL, CODE_LEN+12, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(pfnCreateProcess, OldCode, CODE_LEN);
/*
mov rax, CreateProcessInternalW + CODE_LEN
jmp rax
*/
*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN) = 0xb848;
*(INT64*)((INT64)pfnCreateProcess+CODE_LEN+2) = (INT64)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW")+CODE_LEN;
*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN+10) = 0xe0ff;
}
else if (StrRStrI(ModuleFile, 0, TEXT("Rundll32.exe")))
{
DWORD dwProcessId = 0;
HANDLE hProcess = 0;
HWND hwndDeskTop;
hwndDeskTop = FindWindow(TEXT("ProgMan"), NULL);
GetModuleFileName(hinstDLL, ModuleFile, _countof(ModuleFile));
GetWindowThreadProcessId(hwndDeskTop, &dwProcessId);
BOOLEAN bEnable;
::RtlAdjustPrivilege(0x13, 1, 0, &bEnable);
if (dwProcessId)
{
hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, NULL, dwProcessId);
}
LPVOID Param = VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, Param, (LPVOID)ModuleFile, 256, NULL);
HANDLE hThread = CreateRemoteThread(hProcess,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadLibraryW,
Param,
NULL,
NULL);
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
}
VirtualFreeEx(hProcess, Param , 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int _stdcall Setup(void)
{
return 1;
}
编译成DLL后,在运行里执行rundll32.exe X64Dll.dll,Setup,DLL会自动注入到explorer.exe进程.
完全工程及编译好的文件点击打开链接