#include <windows.h>

// aka GetModuleHandle(NULL)
HMODULE __declspec(naked) GetImageBaseAddress()
{
	__asm{
		mov eax,fs:[0x00000018]	// TEB's Self-Referencing Linear address	
		mov eax,[eax+0x30]		// PEB (Process Environment Block)
		mov eax,[eax+0x08]		// ImageBaseAddress
		ret
	}
}

/**** GetModuleBase proc *********************************************\ 
* (a NO API version of GetModuleHandle)
* Description: Walk the PEB to get the base address of specified module
* the process should be suspended so the PEB can't change while in use
* (todo: figure out PEB locking in-case of CreateRemoteThread or something)
*
* Arguments:
*	wchar_t * BaseDllName: 
*		CASE SENSATIVE UNICODE name of module to find (No Path)
*
* Returns: HINSTANCE of Module or NULL if not found
\*********************************************************************/	
HMODULE __declspec(naked) __stdcall GetModuleBase(wchar_t * ModuleName)
{
	__asm{
		pop eax					// return address
		pop edx					// arg1: the module name to find
		push eax				// return address

		mov eax,fs:[0x00000018]	// TEB's Self-Referencing Linear address	
		mov eax,[eax+0x30]		// PEB (Process Environment Block)
		mov eax,[eax+0x0C]		// PEB_LDR_DATA LoaderData	
		add eax,0x1C			// LIST_ENTRY InInitializationOrderLinks

		cld						// clear direction flag
		xor ecx,ecx				// zero out high byte of counter
	  NextDllEntry:				// step next dll list entry
		mov eax,[eax]			// the current LDR_DATA_TABLE_ENTRY
		mov cx,[eax+0x1C]		// LDR_DATA_TABLE_ENTRY->BaseDllName.Length
		mov esi,[eax+0x20]		// LDR_DATA_TABLE_ENTRY->BaseDllName.Buffer
		mov edi,edx				// wchar_t *BaseDllName			
		repe cmpsb				// compare strings
		jecxz GetModuleBaseEnd	// if end of list or match found 
		jmp NextDllEntry		// else get next dll entry
								
	  GetModuleBaseEnd:
		mov eax,[eax+0x08]		// LDR_DATA_TABLE_ENTRY->DllBase
		ret
	}
}

/***
 ( NO API GetProcAddress, not hardend )
 Walk the Portable Executable (PE) Header
 Goto the the Export Directory
 return a pointer to the function or -1 if error
***/
DWORD GetExportAddress( HMODULE hLibModule, char * lpProcName)
{
	PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER) hLibModule;
	if(dos->e_magic != IMAGE_DOS_SIGNATURE)return -1;

	PIMAGE_NT_HEADERS pe = (PIMAGE_NT_HEADERS)( (ULONG)hLibModule + dos->e_lfanew );
	if(pe->Signature != IMAGE_NT_SIGNATURE)return -1;
	if(!pe->FileHeader.SizeOfOptionalHeader)return -1;

	PIMAGE_DATA_DIRECTORY expdir = (PIMAGE_DATA_DIRECTORY) 
		( pe->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT );
	if(!expdir->Size)return -1; // if module has no exports

	PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY)
		( (ULONG)hLibModule + expdir->VirtualAddress );

	PULONG functions   =(PULONG)((ULONG) hLibModule + exports->AddressOfFunctions);
	PSHORT ordinals    =(PSHORT)((ULONG) hLibModule + exports->AddressOfNameOrdinals);
	PULONG names       =(PULONG)((ULONG) hLibModule + exports->AddressOfNames);
	ULONG  max_name    =exports->NumberOfNames;

	ULONG i;
	// step thru the export names
	for (i = 0; i < max_name; i++)
	{
		// look for lpProcName 
		if(!strcmp(lpProcName,(PCHAR)((ULONG)hLibModule + names[i])))
		{
			// found lpProcName
			// ( don't add the BaseOrdinal?? ...sighs... )
			return (ULONG)hLibModule + functions[ ordinals[i] ];
		}
	}
	// lpProcName not found
	return -1;
}