Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.
// by aaaddress1@chroot.org
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include "wow64ext.h"
using namespace std;
/*
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]
*/
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

This comment has been minimized.

Copy link
Owner Author

@aaaddress1 aaaddress1 commented Apr 22, 2021

截圖 2021-04-22 15 53 48

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