Skip to content

Instantly share code, notes, and snippets.

@aaaddress1
Last active May 3, 2024 22:12
Show Gist options
  • Save aaaddress1/23055dcf73959b72f670fc594576f78c to your computer and use it in GitHub Desktop.
Save aaaddress1/23055dcf73959b72f670fc594576f78c to your computer and use it in GitHub Desktop.
get 64 bit windows API address in pure 32 bit mode
// 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;
}
@aaaddress1
Copy link
Author

截圖 2021-04-22 15 53 48

@aaaddress1
Copy link
Author

/**
*

  • WOW64Ext Library
  • Copyright (c) 2014 ReWolf
  • http://blog.rewolf.pl/
  • This program is free software: you can redistribute it and/or modify
  • it under the terms of the GNU Lesser General Public License as published
  • by the Free Software Foundation, either version 3 of the License, or
  • (at your option) any later version.
  • This program is distributed in the hope that it will be useful,
  • but WITHOUT ANY WARRANTY; without even the implied warranty of
  • MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  • GNU Lesser General Public License for more details.
  • You should have received a copy of the GNU Lesser General Public License
  • along with this program. If not, see http://www.gnu.org/licenses/.

*/
#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);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment