Last active
May 3, 2024 22:12
-
-
Save aaaddress1/23055dcf73959b72f670fc594576f78c to your computer and use it in GitHub Desktop.
get 64 bit windows API address in pure 32 bit mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// get 64 bit Windows API in pure 32 bit mode! | |
// it's necessary to disable all the compiler optimization if you're using MSVC. | |
// more detail check out ReWolf's amazing trick: blog.rewolf.pl/blog/?p=102 | |
// by aaaddress1@chroot.org | |
#include <iostream> | |
#include <stdio.h> | |
#include <windows.h> | |
// ref: raw.githubusercontent.com/rwfpl/rewolf-wow64ext/master/src/wow64ext.h | |
#include "wow64ext.h" | |
using namespace std; | |
/* | |
-- enter 64 bit mode -- | |
0: 6a 33 push 0x33 | |
2: e8 00 00 00 00 call 0x7 | |
7: 83 04 24 05 add DWORD PTR [esp],0x5 | |
b: cb retf | |
-- memcpy for 64 bit -- | |
0: 67 48 8b 7c 24 04 mov rdi,QWORD PTR [esp+0x4] | |
6: 67 48 8b 74 24 0c mov rsi,QWORD PTR [esp+0xc] | |
c: 67 48 8b 4c 24 14 mov rcx,QWORD PTR [esp+0x14] | |
12: f3 a4 rep movs BYTE PTR es:[rdi],BYTE PTR ds:[rsi] | |
-- exit 64 bit mode -- | |
0: e8 00 00 00 00 call 0x5 | |
5: c7 44 24 04 23 00 00 00 mov DWORD PTR [rsp+0x4],0x23 | |
d: 83 04 24 0d add DWORD PTR [rsp],0xd | |
11: cb retf | |
12: c3 ret | |
*/ | |
auto memcpy64 = ((void(cdecl*)(ULONG64, ULONG64, ULONG64))((PCSTR) | |
// enter 64 bit mode | |
"\x6a\x33\xe8\x00\x00\x00\x00\x83\x04\x24\x05\xcb" | |
// memcpy for 64 bit | |
"\x67\x48\x8b\x7c\x24\x04\x67\x48\x8b\x74\x24\x0c\x67\x48\x8b\x4c\x24\x14\xf3\xa4" | |
// exit 64 bit mode | |
"\xe8\x00\x00\x00\x00\xc7\x44\x24\x04\x23\x00\x00\x00\x83\x04\x24\x0d\xcb\xc3" | |
)); | |
PEB64* getPtr_Peb64() { | |
// mov eax,gs:[00000060]; ret | |
return ((PEB64 * (*)()) &"\x65\xA1\x60\x00\x00\x00\xC3")(); | |
} | |
string get64b_CSTR(ULONG64 ptr64bStr) { | |
CHAR szBuf[MAX_PATH]; | |
memcpy64((ULONG64)&szBuf, ptr64bStr, sizeof(szBuf)); | |
return *new string(szBuf); | |
} | |
wstring get64b_WSTR(ULONG64 ptr64bStr) { | |
WCHAR szBuf[MAX_PATH]; | |
memcpy64((ULONG64)&szBuf, ptr64bStr, sizeof(szBuf)); | |
return *new wstring(szBuf); | |
} | |
UINT64 getPtr_Module64(const wchar_t* szDllName) { | |
PEB_LDR_DATA64 ldrNode = {}; | |
LDR_DATA_TABLE_ENTRY64 currNode = {}; | |
// fetch ldr head node | |
memcpy64((ULONG64)&ldrNode, (ULONG64)getPtr_Peb64()->Ldr, sizeof(ldrNode)); | |
// read the first ldr node (should be the current EXE module) | |
for (ULONG64 ptrCurr = ldrNode.InLoadOrderModuleList.Flink;; ptrCurr = currNode.InLoadOrderLinks.Flink) { | |
memcpy64((ULONG64)&currNode, ptrCurr, sizeof(currNode)); | |
if (wcsstr(szDllName, get64b_WSTR(currNode.BaseDllName.Buffer).c_str())) | |
return currNode.DllBase; | |
} | |
return 0; | |
} | |
UINT64 getProcAddr64(PCWCH szModName, PCSTR szApiName) { | |
auto modPtr = getPtr_Module64(szModName); | |
char exeBuf[4096]; | |
memcpy64((ULONG)&exeBuf, modPtr, sizeof(exeBuf)); | |
auto k = PIMAGE_NT_HEADERS64(&exeBuf[0] + PIMAGE_DOS_HEADER(exeBuf)->e_lfanew); | |
auto rvaExportTable = k->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; | |
memcpy64((ULONG)&exeBuf, modPtr + rvaExportTable, sizeof(exeBuf)); | |
auto numOfNames = PIMAGE_EXPORT_DIRECTORY(exeBuf)->NumberOfNames; | |
auto arrOfNames = new UINT32[numOfNames + 1], arrOfFuncs = new UINT32[numOfNames + 1]; | |
auto addrOfNameOrds = new UINT16[numOfNames + 1]; | |
memcpy64((ULONG)arrOfNames, modPtr + PIMAGE_EXPORT_DIRECTORY(exeBuf)->AddressOfNames, sizeof(UINT32) * numOfNames); | |
memcpy64((ULONG)addrOfNameOrds, modPtr + PIMAGE_EXPORT_DIRECTORY(exeBuf)->AddressOfNameOrdinals, sizeof(UINT16) * numOfNames); | |
memcpy64((ULONG)arrOfFuncs, modPtr + PIMAGE_EXPORT_DIRECTORY(exeBuf)->AddressOfFunctions, sizeof(UINT32) * numOfNames); | |
for (size_t i = 0; i < numOfNames; i++) { | |
auto currApiName = get64b_CSTR(modPtr + arrOfNames[i]); | |
if (strstr(szApiName, currApiName.c_str())) | |
return modPtr + arrOfFuncs[addrOfNameOrds[i]]; | |
} | |
return 0; | |
} | |
int main(void) { | |
// looking for Wow64SystemServiceEx, it only appears in WOW64 process | |
// use it as a proof that we can get 64 bit API addr in pure 32 bit mode ;) | |
printf("Wow64SystemServiceEx @ %llx\n", getProcAddr64(L"wow64.dll", "Wow64SystemServiceEx")); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
/**
*
*/
#pragma once
#include <windows.h>
#ifndef STATUS_SUCCESS
define STATUS_SUCCESS 0
#endif
#pragma pack(push)
#pragma pack(1)
template
struct _LIST_ENTRY_T
{
T Flink;
T Blink;
};
template
struct _UNICODE_STRING_T
{
union
{
struct
{
WORD Length;
WORD MaximumLength;
};
T dummy;
};
T Buffer;
};
template
struct _NT_TIB_T
{
T ExceptionList;
T StackBase;
T StackLimit;
T SubSystemTib;
T FiberData;
T ArbitraryUserPointer;
T Self;
};
template
struct _CLIENT_ID
{
T UniqueProcess;
T UniqueThread;
};
template
struct TEB_T
{
_NT_TIB_T NtTib;
T EnvironmentPointer;
_CLIENT_ID ClientId;
T ActiveRpcHandle;
T ThreadLocalStoragePointer;
T ProcessEnvironmentBlock;
DWORD LastErrorValue;
DWORD CountOfOwnedCriticalSections;
T CsrClientThread;
T Win32ThreadInfo;
DWORD User32Reserved[26];
//rest of the structure is not defined for now, as it is not needed
};
template
struct _LDR_DATA_TABLE_ENTRY_T
{
_LIST_ENTRY_T InLoadOrderLinks;
_LIST_ENTRY_T InMemoryOrderLinks;
_LIST_ENTRY_T InInitializationOrderLinks;
T DllBase;
T EntryPoint;
union
{
DWORD SizeOfImage;
T dummy01;
};
_UNICODE_STRING_T FullDllName;
_UNICODE_STRING_T BaseDllName;
DWORD Flags;
WORD LoadCount;
WORD TlsIndex;
union
{
_LIST_ENTRY_T HashLinks;
struct
{
T SectionPointer;
T CheckSum;
};
};
union
{
T LoadedImports;
DWORD TimeDateStamp;
};
T EntryPointActivationContext;
T PatchInformation;
_LIST_ENTRY_T ForwarderLinks;
_LIST_ENTRY_T ServiceTagLinks;
_LIST_ENTRY_T StaticLinks;
T ContextInformation;
T OriginalBase;
_LARGE_INTEGER LoadTime;
};
template
struct _PEB_LDR_DATA_T
{
DWORD Length;
DWORD Initialized;
T SsHandle;
_LIST_ENTRY_T InLoadOrderModuleList;
_LIST_ENTRY_T InMemoryOrderModuleList;
_LIST_ENTRY_T InInitializationOrderModuleList;
T EntryInProgress;
DWORD ShutdownInProgress;
T ShutdownThreadId;
};
template <class T, class NGF, int A>
struct _PEB_T
{
union
{
struct
{
BYTE InheritedAddressSpace;
BYTE ReadImageFileExecOptions;
BYTE BeingDebugged;
BYTE BitField;
};
T dummy01;
};
T Mutant;
T ImageBaseAddress;
T Ldr;
T ProcessParameters;
T SubSystemData;
T ProcessHeap;
T FastPebLock;
T AtlThunkSListPtr;
T IFEOKey;
T CrossProcessFlags;
T UserSharedInfoPtr;
DWORD SystemReserved;
DWORD AtlThunkSListPtr32;
T ApiSetMap;
T TlsExpansionCounter;
T TlsBitmap;
DWORD TlsBitmapBits[2];
T ReadOnlySharedMemoryBase;
T HotpatchInformation;
T ReadOnlyStaticServerData;
T AnsiCodePageData;
T OemCodePageData;
T UnicodeCaseTableData;
DWORD NumberOfProcessors;
union
{
DWORD NtGlobalFlag;
NGF dummy02;
};
LARGE_INTEGER CriticalSectionTimeout;
T HeapSegmentReserve;
T HeapSegmentCommit;
T HeapDeCommitTotalFreeThreshold;
T HeapDeCommitFreeBlockThreshold;
DWORD NumberOfHeaps;
DWORD MaximumNumberOfHeaps;
T ProcessHeaps;
T GdiSharedHandleTable;
T ProcessStarterHelper;
T GdiDCAttributeList;
T LoaderLock;
DWORD OSMajorVersion;
DWORD OSMinorVersion;
WORD OSBuildNumber;
WORD OSCSDVersion;
DWORD OSPlatformId;
DWORD ImageSubsystem;
DWORD ImageSubsystemMajorVersion;
T ImageSubsystemMinorVersion;
T ActiveProcessAffinityMask;
T GdiHandleBuffer[A];
T PostProcessInitRoutine;
T TlsExpansionBitmap;
DWORD TlsExpansionBitmapBits[32];
T SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
T pShimData;
T AppCompatInfo;
_UNICODE_STRING_T CSDVersion;
T ActivationContextData;
T ProcessAssemblyStorageMap;
T SystemDefaultActivationContextData;
T SystemAssemblyStorageMap;
T MinimumStackCommit;
T FlsCallback;
_LIST_ENTRY_T FlsListHead;
T FlsBitmap;
DWORD FlsBitmapBits[4];
T FlsHighIndex;
T WerRegistrationData;
T WerShipAssertPtr;
T pContextData;
T pImageHeaderHash;
T TracingFlags;
};
typedef _LDR_DATA_TABLE_ENTRY_T LDR_DATA_TABLE_ENTRY32;
typedef _LDR_DATA_TABLE_ENTRY_T LDR_DATA_TABLE_ENTRY64;
typedef TEB_T TEB32;
typedef TEB_T TEB64;
typedef _PEB_LDR_DATA_T PEB_LDR_DATA32;
typedef _PEB_LDR_DATA_T PEB_LDR_DATA64;
typedef _PEB_T<DWORD, DWORD64, 34> PEB32;
typedef _PEB_T<DWORD64, DWORD, 30> PEB64;
struct _XSAVE_FORMAT64
{
WORD ControlWord;
WORD StatusWord;
BYTE TagWord;
BYTE Reserved1;
WORD ErrorOpcode;
DWORD ErrorOffset;
WORD ErrorSelector;
WORD Reserved2;
DWORD DataOffset;
WORD DataSelector;
WORD Reserved3;
DWORD MxCsr;
DWORD MxCsr_Mask;
_M128A FloatRegisters[8];
_M128A XmmRegisters[16];
BYTE Reserved4[96];
};
struct _CONTEXT64
{
DWORD64 P1Home;
DWORD64 P2Home;
DWORD64 P3Home;
DWORD64 P4Home;
DWORD64 P5Home;
DWORD64 P6Home;
DWORD ContextFlags;
DWORD MxCsr;
WORD SegCs;
WORD SegDs;
WORD SegEs;
WORD SegFs;
WORD SegGs;
WORD SegSs;
DWORD EFlags;
DWORD64 Dr0;
DWORD64 Dr1;
DWORD64 Dr2;
DWORD64 Dr3;
DWORD64 Dr6;
DWORD64 Dr7;
DWORD64 Rax;
DWORD64 Rcx;
DWORD64 Rdx;
DWORD64 Rbx;
DWORD64 Rsp;
DWORD64 Rbp;
DWORD64 Rsi;
DWORD64 Rdi;
DWORD64 R8;
DWORD64 R9;
DWORD64 R10;
DWORD64 R11;
DWORD64 R12;
DWORD64 R13;
DWORD64 R14;
DWORD64 R15;
DWORD64 Rip;
_XSAVE_FORMAT64 FltSave;
_M128A Header[2];
_M128A Legacy[8];
_M128A Xmm0;
_M128A Xmm1;
_M128A Xmm2;
_M128A Xmm3;
_M128A Xmm4;
_M128A Xmm5;
_M128A Xmm6;
_M128A Xmm7;
_M128A Xmm8;
_M128A Xmm9;
_M128A Xmm10;
_M128A Xmm11;
_M128A Xmm12;
_M128A Xmm13;
_M128A Xmm14;
_M128A Xmm15;
_M128A VectorRegister[26];
DWORD64 VectorControl;
DWORD64 DebugControl;
DWORD64 LastBranchToRip;
DWORD64 LastBranchFromRip;
DWORD64 LastExceptionToRip;
DWORD64 LastExceptionFromRip;
};
// Below defines for .ContextFlags field are taken from WinNT.h
#ifndef CONTEXT_AMD64
#define CONTEXT_AMD64 0x100000
#endif
#define CONTEXT64_CONTROL (CONTEXT_AMD64 | 0x1L)
#define CONTEXT64_INTEGER (CONTEXT_AMD64 | 0x2L)
#define CONTEXT64_SEGMENTS (CONTEXT_AMD64 | 0x4L)
#define CONTEXT64_FLOATING_POINT (CONTEXT_AMD64 | 0x8L)
#define CONTEXT64_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L)
#define CONTEXT64_FULL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_FLOATING_POINT)
#define CONTEXT64_ALL (CONTEXT64_CONTROL | CONTEXT64_INTEGER | CONTEXT64_SEGMENTS | CONTEXT64_FLOATING_POINT | CONTEXT64_DEBUG_REGISTERS)
#define CONTEXT64_XSTATE (CONTEXT_AMD64 | 0x20L)
#pragma pack(pop)
#ifdef WOW64EXT_EXPORTS
define SPEC dllexport
#else
define SPEC dllimport
#endif
extern "C"
{
__declspec(SPEC)DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...);
__declspec(SPEC)DWORD64 __cdecl GetModuleHandle64(wchar_t* lpModuleName);
__declspec(SPEC)DWORD64 __cdecl GetProcAddress64(DWORD64 hModule, char* funcName);
__declspec(SPEC)SIZE_T __cdecl VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);
__declspec(SPEC)DWORD64 __cdecl VirtualAllocEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect);
__declspec(SPEC)BOOL __cdecl VirtualFreeEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD dwFreeType);
__declspec(SPEC)BOOL __cdecl VirtualProtectEx64(HANDLE hProcess, DWORD64 lpAddress, SIZE_T dwSize, DWORD flNewProtect, DWORD* lpflOldProtect);
__declspec(SPEC)BOOL __cdecl ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T lpNumberOfBytesRead);
__declspec(SPEC)BOOL __cdecl WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T lpNumberOfBytesWritten);
__declspec(SPEC)BOOL __cdecl GetThreadContext64(HANDLE hThread, _CONTEXT64 lpContext);
__declspec(SPEC)BOOL __cdecl SetThreadContext64(HANDLE hThread, _CONTEXT64 lpContext);
__declspec(SPEC)VOID __cdecl SetLastErrorFromX64Call(DWORD64 status);
}