[C++ PoC] Calling GetProcAddress using "the hard way"

Xpeedo

Member
Joined
Jul 21, 2015
Messages
15
Reaction score
8
Location
Los Santos
Tested on Windows 10 Pro x64 and Windows 8.1 x64.
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;
}
 

_Safa

Well-known member
Joined
Sep 22, 2019
Messages
295
Reaction score
100
Location
UGBASE
"The hard way" You mean the retard way? LMAOOO
 

88resu

Active member
Joined
Oct 1, 2019
Messages
110
Reaction score
46
Location
Uganda
Instead of hating him, appreciate that some ppl are interested to Share their knowledges in that dead section


U are the retarded one. "Moderator"
U have any knowledge about real coding or only shitty prefunctioned Cleo? Dont shoot against others when u cant even understand a single line of thus code
 

Xpeedo

Member
Joined
Jul 21, 2015
Messages
15
Reaction score
8
Location
Los Santos
"The hard way" You mean the retard way? LMAOOO
you must be the "retarded" marketing guy from ascensioncheats. if you still tryin' to sell yourself for $100 lifetime, play another game, you may have luck with that.
 
Top