//
// This little program returns the addresses of LoadLibraryA(),
// GetProcAddress(), and "jmp ESP" on your Windows.
//
// If your compiler cannot use SEH,
// please comment out "#define USE_SEH"
//
#include <stdio.h>

//===================================================================//
// a general routine, search in memory
#include <windows.h>
#include <psapi.h>

#define USE_SEH

//---------- data for search address ------------
const unsigned char *DllList[]={
    "kernel32.dll",// do not edit kernel32.dll
    "user32.dll",
    "gdi32.dll",
    "advapi.dll",
    "imm32.dll",
    "winmm.dll",
    "ole32.dll",
    "netapi32.dll"
};

#define DllCount (sizeof(DllList)/sizeof(unsigned char *))

const unsigned char *JmpESPList[3]={
    "\xFF\xD4",
    "\xFF\xE4",
    "\x54\xC3"
};

int isAddrAvailableChar(unsigned long IN_addr)
{
    // exclude 0x0000,0xffff,0x002f,0x003e,0x0040,0x0025
    return(
        (IN_addr & 0x0000ffff)
        && (IN_addr & 0xffff0000)
        && ((IN_addr & 0x0000ffff) != 0x0000ffff)
        && ((IN_addr & 0xffff0000) != 0xffff0000)
        && ((IN_addr & 0x0000ffff) != 0x0000002f)
        && ((IN_addr & 0xffff0000) != 0x002f0000)
        && ((IN_addr & 0x0000ffff) != 0x00000022)
        && ((IN_addr & 0xffff0000) != 0x00220000)
        && ((IN_addr & 0x0000ffff) != 0x0000003e)
        && ((IN_addr & 0xffff0000) != 0x003e0000)
        && ((IN_addr & 0x0000ffff) != 0x00000040)
        && ((IN_addr & 0xffff0000) != 0x00400000)
        && ((IN_addr & 0x0000ffff) != 0x00000025)
        && ((IN_addr & 0xffff0000) != 0x00250000)
    );
}

unsigned char * searchInMem(unsigned char *IN_start,int IN_size, const unsigned char *IN_data, int IN_data_size)
{
    unsigned char *cur_pos = IN_start + IN_size - IN_data_size;

#ifdef USE_SEH
    __try
    {
#endif
        while (cur_pos >= IN_start)
        {
            if ( 0 == memcmp(cur_pos, IN_data, IN_data_size)
                && isAddrAvailableChar((unsigned long)cur_pos) )
                return cur_pos;
            --cur_pos;
        }
#ifdef USE_SEH
    }
    __except((STATUS_ACCESS_VIOLATION == GetExceptionCode())
        ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
    {
    }
#endif

    return 0;
}

int getAddress(unsigned long *OUT_jmp,unsigned long *OUT_loadlib,unsigned long *OUT_getproc)
{
    int i,j;
    HMODULE hlist[DllCount];
    OSVERSIONINFO info;

    info.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
    GetVersionEx(&info);

    memset(hlist,0,sizeof(hlist));
    if (info.dwPlatformId==VER_PLATFORM_WIN32_NT)
    {
        // NT
        MODULEINFO minfo;
        HMODULE psapi = LoadLibrary("psapi.dll");
        BOOL (WINAPI *fp_GetModuleInformation)(HANDLE,HMODULE,LPMODULEINFO,DWORD);

        fp_GetModuleInformation = (void*)GetProcAddress(psapi,"GetModuleInformation");
        for (i=0;i<DllCount;++i)
        {
            hlist[i] = LoadLibrary(DllList[i]);
            if (hlist[i])
            {
                fp_GetModuleInformation(GetCurrentProcess(),hlist[i],&minfo,sizeof(MODULEINFO));

                for (j=0;j<3 && !(*OUT_jmp = (unsigned long)searchInMem((void*)hlist[i],minfo.SizeOfImage,JmpESPList[j],2));++j);
                if (*OUT_jmp)
                {
                    break;
                }
            }
        }
        FreeLibrary(psapi);
    }
    else
    {
        // 9x
        MEMORY_BASIC_INFORMATION minfo;
        for (i=0;i<DllCount;++i)
        {
            hlist[i] = LoadLibrary(DllList[i]);
            if (hlist[i])
            {
                VirtualQuery(hlist[i],&minfo,sizeof(MEMORY_BASIC_INFORMATION));

                for (j=0;j<3 && !(*OUT_jmp = (unsigned long)searchInMem((void*)hlist[i],minfo.RegionSize,JmpESPList[j],2));++j);
                if (*OUT_jmp)
                {
                    break;
                }
            }
        }
    }
    // kernel32.dll
    *OUT_loadlib = (unsigned long)GetProcAddress(hlist[0],"LoadLibraryA");
    *OUT_getproc = (unsigned long)GetProcAddress(hlist[0],"GetProcAddress");

    for (i=0;i<DllCount;++i)
        if (0 != hlist[i])
            FreeLibrary(hlist[i]);

    return (*OUT_jmp && *OUT_loadlib && *OUT_getproc) ? 1 : 0;
}

//----------------------------------------------------

int main()
{
    unsigned long jmpesp,loadlib,getproc;
    if (!getAddress(&jmpesp,&loadlib,&getproc))
        return -1;

    printf("0x%X,0x%X,0x%X",jmpesp,loadlib,getproc);
    return 0;
}
