A fusion injector that reduce differences between x64, wow64 and x86 processes according to Mr.Rewolf's article.
Keywords: HEADER-ONLY, DLL-FREE, ANY-CALLEE, ANY-CALLER, ANY-WIN-OS, LOCAL-LIKE
- Wow64: Windows-on-Windows 64-bit, which 32-bit process works in.
-
Cross x86 & x64 injection without any external *.dll or even *.lib:
- x86 injector -> x86 process @ 32-bit OS
- wow64 injector -> wow64 process @ 64-bit OS
- wow64 injector -> x64 process @ 64-bit OS
- x64 injector -> wow64 process @ 64-bit OS
- x64 injector -> x64 process @ 64-bit OS
-
In-process call x64 functions / APIs for Wow64 process
-
Local-like remote call of target process
- Remote call multi-params (more than one) windows API of target process
- Remote call windows API that return 64-bit result of target process
-
X64Call
example (Unload dll in remote process)X64Call RtlCreateUserThread("RtlCreateUserThread"); // Validate RtlCreateUserThread if (!RtlCreateUserThread) return 0; X64Call LdrUnloadDll("LdrUnloadDll"); // Validate LdrUnloadDll if (!LdrUnloadDll) return 0; // => local-like call DWORD64 ret = RtlCreateUserThread(hProcess, NULL, FALSE, 0, 0, NULL, LdrUnloadDll, dllBaseAddr, NULL, NULL);
-
Available constructors:
-
Specified module is allowed (
ntdll.dll
as default)X64Call(const char* funcName); X64Call(DWORD64 module, const char* funcName);
-
-
-
YAPICall
example (MessageBox
in remote process)YAPICall MessageBoxA(hProcess, _T("user32.dll"), "MessageBoxA"); // => local-like call MessageBoxA(NULL, "MessageBoxA : Hello World!", "From ez8.co", MB_OK); YAPI(hProcess, _T("user32.dll"), MessageBoxW) (NULL, L"MessageBoxW: Hello World!", L"From ez8.co", MB_OK);
-
Available constructors:
-
Specified module or module name is allowed (
ntdll.dll
as default). -
NOTICE: If failed to fetch 64-bit module, will automatically fetch 32-bit modules in wow64 process under 64-bit OS.
YAPICall(HANDLE hProcess, const char* funcName); YAPICall(HANDLE hProcess, DWORD64 moudle, const char* funcName); YAPICall(HANDLE hProcess, const TCHAR* modName, const char* funcName);
-
-
-
64-bit result example (
GetModuleHandle
ofuser32.dll
under 64-bit OS)YAPICall GetModuleHandle(hProcess, _T("kernel32.dll"), sizeof(TCHAR) == sizeof(char) ? "GetModuleHandleA" : "GetModuleHandleW"); DWORD64 user32Dll = GetModuleHandle.Dw64()(_T("user32.dll"));
-
Timeout
example (GetCurrentProcessId
in 300ms)YAPICall GetCurrentProcessId(hProcess, _T("kernel32.dll"), "GetCurrentProcessId"); DWORD pid = GetCurrentProcessId.Timeout(300)();
-
Timeout
& 64-bit result example (GetModuleHandle
in 300ms)DWORD64 user32Dll = GetModuleHandle.Dw64().Timeout(300)(_T("user32.dll"));
-
Popular
LoadLibrary
exampleYAPICall LoadLibraryA(hProcess, _T("kernel32.dll"), "LoadLibraryA"); DWORD64 x86Dll = LoadLibraryA("D:\\x86.dll"); DWORD64 x64Dll = LoadLibraryA.Dw64()("D:\\x64.dll"); _tprintf(_T("X86: %I64x\nX64: %I64x\n"), x86Dll, x64Dll);
-
API List:
API Name x86 Equivalent Notes GetNtDll64 GetModuleHandle64 GetModuleHandle overloaded version GetProcAddress64 GetProcAddress overloaded version SetLastError64 SetLastError VirtualQueryEx64 VirtualQueryEx VirtualAllocEx64 VirtualAllocEx VirtualFreeEx64 VirtualFreeEx VirtualProtectEx64 VirtualProtectEx ReadProcessMemory64 ReadProcessMemory WriteProcessMemory64 WriteProcessMemory LoadLibrary64 LoadLibrary CreateRemoteThread64 CreateRemoteThread -
Class List:
Class Name 32-bit OS Support 64-bit OS Compatiblity X64Call ✅ NOT READY NOW ProcessWriter ✅ ✅ YAPICall ✅ ✅
-
Nomal x64->x64, x86->x86 injection:
- Use
CreateRemoteThread
/RtlCreateUserThread
- You can change other methods by yourself.
- FYR: fdiskyou/injectAllTheThings
- Use
-
Multi-params windows API:
- Pack function address and params in one structure and use shell code to execute in remote process.
- See
X86/X64Delegator_disassemble
for details in disassemble directory.
-
x64 call for wow64 process:
- Switch to x64 mode
- See references for details.
-
x64 process inject to wow64 process:
- Use trampoline:
CreateRemoteThread
(x64): x64 shell code with x86 mode switch (1 arg: function->x86 shell code with one param, param->packed x86 structure) -> pass packed structure (x86 real to call function address and params) to x86 shell code -> pass params to real function.
- NOTICE: function address(target module) should be valid in target process, but not needed in source injector.
- Use trampoline:
-
64-bit result:
- Add a
DWORD64
result field to package. - Obtain result if needed.
ReadProcessMemory
after remote thread finished.
- Add a
-
Operating systems that have been tested are shown in table below.
Operating System Notes Windows 10 Tested on 64-bit, should also work on 32-bit Windows 8 Should work on both 64-bit and 32-bit Windows 7 Tested on 64-bit, should also work on 32-bit Windows Vista Should work on both 64-bit and 32-bit Windows XP Should work on both 64-bit and 32-bit
- Mixing x86 with x64 code @rewolf
- More simple impl of
X64Call
. - 64-bit OS compatible support of
X64Call
. - Finish shell codes that more than 6 arguments for
YAPICall
. - Support to fetch specified bit module for
YAPICall
(32-bit or 64-bit). - Same function call (mirror call) automatically in remote process.
- Self-defined function call in remote process.
- IAT/inline hook in remote process.
- Support other 7 optional inject methods.
- Please feel free to use yapi.
- Looking forward to your suggestions.