Xpeedo
Member
Tested on Windows 10 Pro x64 and Windows 8.1 x64.
Feel free to use it.
Feel free to use it.
C++:
/*
This "Proof of Concept" shows how a x86 binary can use basic imported functions from kernel32 to do cool things. This snippet may help you or not. It's your choice.
This "pattern scan" may help you to find if GetProcAddress is hooked, so why you don't bypass it by yourself by using a precall (calling only original bytes without jumps)?
~ 4 ugbase.eu
*/
#include <Windows.h>
BYTE* _getProcFuncInternal = nullptr;
BYTE* _getKernel32Module = nullptr;
BYTE* _strLoadLibraryA = nullptr;
BYTE* _strUser32dll = nullptr;
BYTE* _strGetAsyncKeyState = nullptr;
BYTE* _strMessageBoxA = nullptr;
BYTE _reversedGetProcFuncInternal[] = { 0x74, 0x00, 0xAA, 0x74, 0x13, 0x00, 0x8A, 0xFB, 0x00, 0x8A, 0xF3, 0x00, 0x8A, 0xF7, 0x00, 0xEA, 0x21, 0x52, 0x41, 0x10, 0xA2, 0x3D, 0xF7, 0xFF };
BYTE _reversedGetKernel32Module[] = { 0xB2, 0xA5, 0x6F, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFB };
BYTE _reversedLoadLibraryA[] = { 0xB3, 0x90, 0x9E, 0x9B, 0xB3, 0x96, 0x9D, 0x8D, 0x9E, 0x8D, 0x86, 0xBE, 0xFF };
BYTE _reversedUser32dll[] = { 0x8A, 0x8C, 0x9A, 0x8D, 0xCC, 0xCD, 0xD1, 0x9B, 0x93, 0x93, 0xFF };
BYTE _reversedGetAsyncKeyState[] = { 0xB8, 0x9A, 0x8B, 0xBE, 0x8C, 0x86, 0x91, 0x9C, 0xB4, 0x9A, 0x86, 0xAC, 0x8B, 0x9E, 0x8B, 0x9A, 0xFF };
BYTE _reversedMessageBoxA[] = { 0xB2, 0x9A, 0x8C, 0x8C, 0x9E, 0x98, 0x9A, 0xBD, 0x90, 0x87, 0xBE, 0xFF };
typedef HRESULT(__stdcall* __GetProcAddress)(HMODULE hModule, const char* szFuncName);
typedef BOOL(__stdcall* __AllocConsole)();
typedef void*(__cdecl* __freopen)(char const* in, char const* mode, void* out);
typedef BOOL(__stdcall* __SetConsoleTitleA)(const char* szConsoleTitle);
typedef int(__cdecl* __printf)(const char* szFormat, ...);
typedef HMODULE(__stdcall* __LoadLibraryA)(const char* szModuleName);
typedef HMODULE(__stdcall* __GetModuleHandleA)(const char* szModuleName);
typedef SHORT(__stdcall* __GetAsyncKeyState)(int vKey);
typedef int(__stdcall* __MessageBoxA)(HWND hWnd, const char* szMessageText, const char* szTitleText, unsigned int flags);
__GetProcAddress gGetProcAddress = nullptr;
HMODULE hKernel = nullptr;
#define RESOLVE_FUNC(funcName) gGetProcAddress(hKernel, (const char*)funcName)
#define CALL_FUNC(type, funcName, ...) ((type)RESOLVE_FUNC((const char*)funcName))(__VA_ARGS__)
#define CUSTOM_CALL_FUNC(hModule, type, funcName, ...) ((type)gGetProcAddress(hModule, (const char*)funcName))(__VA_ARGS__)
#define CUSTOM_LOADLIRARY(moduleName) CALL_FUNC(__LoadLibraryA, (const char*)_strLoadLibraryA, (const char*)moduleName)
#define SAFE_BYTE_RELEASE(block, size) \
ZeroMemory(block, size); \
delete[] block; \
block = nullptr;
BYTE* reverseBytes(BYTE* content, size_t iSize) // use a better "decryption" runtime algorithm
{
if (!iSize || !content)
return nullptr;
BYTE* hReturn = new BYTE[iSize]();
for (size_t i = 0; i < iSize; i++)
{
hReturn[i] = 0xFF - content[i];
}
return hReturn;
}
void __init(HMODULE hMod)
{
bool bFoundKernelFunc = false;
bool bFoundKernelModule = false;
/*
1. We "decrypt" almost everything in runtime.
TO-DO: Let's do it when we really need it to prevent mass string dumping.
*/
BYTE* tempHandle = nullptr;
tempHandle = _reversedGetProcFuncInternal;
_getProcFuncInternal = reverseBytes(tempHandle, sizeof(_reversedGetProcFuncInternal));
tempHandle = _reversedGetKernel32Module;
_getKernel32Module = reverseBytes(tempHandle, sizeof(_reversedGetKernel32Module));
tempHandle = _reversedLoadLibraryA;
_strLoadLibraryA = reverseBytes(tempHandle, sizeof(_reversedLoadLibraryA));
tempHandle = _reversedUser32dll;
_strUser32dll = reverseBytes(tempHandle, sizeof(_reversedUser32dll));
tempHandle = _reversedGetAsyncKeyState;
_strGetAsyncKeyState = reverseBytes(tempHandle, sizeof(_reversedGetAsyncKeyState));
tempHandle = _reversedMessageBoxA;
_strMessageBoxA = reverseBytes(tempHandle, sizeof(_reversedMessageBoxA));
tempHandle = nullptr;
/*
2. I think this is the best place to get all informations? Yeah I think more informations are available on MSDN.
*/
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hMod + pDosHeader->e_lfanew);
for (size_t func = 0; func < pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size / 4; func++)
{
DWORD* pKernelFun = (DWORD*)((DWORD)hMod + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress);
if (pKernelFun[func])
{
if (0 == memcmp((void*)pKernelFun[func], _getProcFuncInternal, 16) && 0 == memcmp((void*)(pKernelFun[func] + 20), _getProcFuncInternal + 20, 4))
{
gGetProcAddress = (__GetProcAddress)pKernelFun[func];
bFoundKernelFunc = (bool)gGetProcAddress;
break;
}
}
}
SAFE_BYTE_RELEASE(_getProcFuncInternal, sizeof(_reversedGetProcFuncInternal));
/*
3. We have now the GetProcAddress, but now we need the Kernel Module, without calling GetModuleHandle.
*/
size_t iScanOffset = 0;
while (true)
{
hKernel = (HMODULE)gGetProcAddress - iScanOffset;
iScanOffset++;
if (!((DWORD)hKernel << 8 * 2))
{
while (true)
{
if (0 == memcmp(hKernel, _getKernel32Module, sizeof(_reversedGetKernel32Module)))
{
bFoundKernelModule = true;
break;
}
hKernel -= 0x4000;
}
break;
}
if (iScanOffset > 0x20000)
break;
}
iScanOffset = 0;
SAFE_BYTE_RELEASE(_getKernel32Module, sizeof(_reversedGetKernel32Module));
/*
4. Let's see the result.
*/
if (!bFoundKernelModule && !bFoundKernelFunc)
{
return;
}
/*
5. Perfect, now we can play catch the mouse!
*/
HMODULE user32 = CUSTOM_LOADLIRARY(_strUser32dll);
while (true)
{
if (CUSTOM_CALL_FUNC(user32, __GetAsyncKeyState, _strGetAsyncKeyState, VK_F3) & 1)
{
CUSTOM_CALL_FUNC(user32, __MessageBoxA, _strMessageBoxA, 0, "Hello!", "Random Message", 0);
break;
}
}
SAFE_BYTE_RELEASE(_strLoadLibraryA, sizeof(_reversedLoadLibraryA));
SAFE_BYTE_RELEASE(_strUser32dll, sizeof(_reversedUser32dll));
SAFE_BYTE_RELEASE(_strGetAsyncKeyState, sizeof(_reversedGetAsyncKeyState));
SAFE_BYTE_RELEASE(_strMessageBoxA, sizeof(_reversedMessageBoxA));
}
INT __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
__init(hInstance);
return 0;
}