Thread: cAddressTable

Results 1 to 5 of 5
  1. #1
    radnomguywfq3's Avatar
    Join Date
    Jan 2007
    Gender
    male
    Location
    J:\E\T\A\M\A\Y.exe
    Posts
    8,858
    Reputation
    381
    Thanks
    1,823
    My Mood
    Sad

    cAddressTable

    Under MIT Licensee

    If there are any tutorials someone wants me to write, please notify me about them. I am open to all ideas, as long as they're not towards specific games. As my computer isn't much of a gaming computer and developing hacks for any game would take years on this piece of crap.

    Because I just wrote a huge ass tutorial on cBreakpoint(which no one read), I'm not doing much for this one. The methods are pretty self explanatory. I'll write on it in an hour or so..

    cAddressTable is a class that enables you to search the IAT, and EAT for exports and imports, or replace them. This hasn't undergone any extensive testing, and if the PE Header of the targeted module is wiped at runtime, this class will not work. Unless you're willing to manually set the table's Import\Export table addresses. This will also not work if the application is encrypted or packed. Unless, like said, you define base addresses yourself.

    Defining Base Addresses yourself
    There are times when your target will completely wipe the PE header, which will prevent cAddressTable::GetAddressTable from returning valid data. Thus you will be required to locate the IAT or EAT manually. There are several REing techniques, and if your target is encrypted or packed, the unpacking stub will have to manage the imports and setting up the IAT itself. Even when the target has been unpacked by the unpacking stub, there is a high chance your target's code, or the unpacking stub will clear the PE header, and thus searching for the IAT using the PE header proves rather difficult. What you can do, is setup the AddressTable struct manually. You do this as done below :

    [php]
    AddressTable* adrTable = new AddressTable();
    adrTable->moduleBase = GetModuleHandle(0);
    adrTable->tableOffset = OFFSET_FROM_MODULE_BASE_IAT;
    adrTable->size = 25; //In bytes.
    adrTable->type = IAT;
    [/php]Then pass that struct pointer to SearchIATForAddress, or whichever method you wish to use. All those members should explain themselfs pretty well. tableOffset is the offset from the base, which when added to the base results in the IAT.
    Searching for an IAT\EAT
    If your target isn't encrypted, or doesn't have a damaged PE header, you're good to go, and you can simply use the method GetAddressTable. How to use the methods is defined below.


    Public Methods
    int SetTable(AddressTable* addrTable)
    Sets the default address table. The first parameter is a pointer to the new default AddressTable. The data in this struct is copied to the class's local private member, m_addrTable.

    Returns:
    1 - Success
    Else - Fail
    unsigned long HookAddress(unsigned long tgtAddr, unsigned long writeAddr, ATHook* hookData)
    Replaces a DWORD of the memory located at
    the address defined in tgtAddr param with the memory defined in writeAddr param. hookData param takes a pointer to a ATHook struct. This function will set the passed struct accordingly. After this struct has been set by this function. It should NOT be altered before the calling of RestoreAddress

    Returns:
    1 - Success
    Else - Fail
    unsigned long SearchIATForAddress(unsigned long impAddress, AddressTable* adrTable = 0)
    Searches the IAT for a defined address and returns where it's located in the IAT. This is not a relative address. The first param is the address to look for, the second in the address table to look in. If this param isn't given, it uses the default address table, set by SetTable.

    Returns:
    Absolute address where address is located in IAT - Success
    0 - Fail


    unsigned long SearchEATForAddress(char* expSymbolName, AddressTable* adrTable)

    First param is the name of the exported symbol to look for, the second is the address table to look in. Returns either the absolute address where the export is located, or 0, which means it failed to locate it.

    int RestoreAddress(ATHook* hookData);
    Restores a breakpoint..

    AddressTable* GetAddressTable(unsigned long module, short type);
    Searches the PE header for the address table. Type can either be IAT, or EAT. Module must be a pointer to the modules base. Use GetModuelHandle to locate the base address of a module. Returns a pointer to a newly created, and set AddressTable struct, with all the members defined accordingly.
    Last edited by radnomguywfq3; 07-13-2009 at 03:04 AM.

  2. The Following 10 Users Say Thank You to radnomguywfq3 For This Useful Post:

    aladinss (10-21-2015),bocayroi1 (06-23-2016),huzx (03-17-2014),I-JlStepper-I (07-09-2010),lus6 (09-10-2012),Marsicano (10-17-2009),rodrigo19091992 (01-21-2014),sph4ck (09-05-2010),uc0fix (06-18-2010),why06 (01-10-2010)

  3. #2
    Dave84311's Avatar
    Join Date
    Dec 2005
    Gender
    male
    Location
    The Wild Wild West
    Posts
    35,837
    Reputation
    5782
    Thanks
    41,292
    My Mood
    Devilish
    GJ LIL FELLAR





    THE EYE OF AN ADMINISTRATOR IS UPON YOU. ANY WRONG YOU DO IM GONNA SEE, WHEN YOU'RE ON MPGH, LOOK BEHIND YOU, 'CAUSE THATS WHERE IM GONNA BE


    "First they ignore you. Then they laugh at you. Then they fight you. Then you lose.” - Dave84311

    HAVING VIRTUAL DETOX

  4. #3
    radnomguywfq3's Avatar
    Join Date
    Jan 2007
    Gender
    male
    Location
    J:\E\T\A\M\A\Y.exe
    Posts
    8,858
    Reputation
    381
    Thanks
    1,823
    My Mood
    Sad
    Added a better doc on the class.

  5. #4
    Zhhot's Avatar
    Join Date
    Aug 2009
    Gender
    male
    Location
    Vancouver
    Posts
    314
    Reputation
    10
    Thanks
    52
    My Mood
    Inspired
    i read ur cBreakpoint tut, although i didnt get it, i like reading stuff

  6. #5
    pushedx's Avatar
    Join Date
    Nov 2009
    Gender
    male
    Posts
    4
    Reputation
    10
    Thanks
    4
    Very nice work, thanks for sharing! I've been looking for some existing code to use to obtain a list of exports from a target and couldn't find any simple and clean code to copy over into a project. I have imports done, but I wrote it many years ago and forgot the logic of how it works so I'd have to rewrite it all to understand it again.

    This works out very nicely and has saved quite a bit of time. I was getting ready to just port Iczelion's Tutorial 7 from ASM to C++, but now I don't have to!

    I also noticed a few things I did not know before. For example, the whole "DbgHelp" header, I was not aware of and have never used it before in my projects. It has some very useful functions, some of which I was coding by hand that should help greatly.

    However, I noticed your code has a few logical errors and does not handle all exports correctly. Here is a small rewrite of the exports gathering code from a base address that should be correct and handle all types of exports (there are two!).

    Code:
    #include <windows.h>
    #include <stdio.h>
    
    #define MakePtr(cast, ptr, addValue) (cast)((DWORD)(ptr)+(DWORD)(addValue))
    
    void GetAllExports(void * moduleBase)
    {
    	PIMAGE_DOS_HEADER dosHeader = 0;
    	PIMAGE_NT_HEADERS peHeader = 0;
    	IMAGE_DATA_DIRECTORY * dataDirectory = 0;
    	DWORD dwModuleBase = 0;
    	DWORD * ptrFuncs = 0;
    	DWORD * ptrNames = 0;
    	DWORD * funcIndexTable = 0;
    	DWORD funcsSize = 0;
    	DWORD namesSize = 0;
    	_IMAGE_EXPORT_DIRECTORY * expDescBuf = 0;
    
    	dwModuleBase = PtrToUlong(moduleBase);
    	dosHeader = (PIMAGE_DOS_HEADER)moduleBase;
    	peHeader = MakePtr(PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew);
    	dataDirectory = &peHeader->OptionalHeader.DataDirectory[0];
    	expDescBuf = (_IMAGE_EXPORT_DIRECTORY*)(dataDirectory->VirtualAddress + dwModuleBase);
    	ptrFuncs = (DWORD*)expDescBuf->AddressOfFunctions;
    	ptrNames = (DWORD*)expDescBuf->AddressOfNames;
    	funcIndexTable = (DWORD*)(expDescBuf->AddressOfNameOrdinals);
    	ptrNames = (DWORD*)((DWORD)ptrNames + dwModuleBase);
    	ptrFuncs = (DWORD*)((DWORD)ptrFuncs + dwModuleBase);
    	funcIndexTable = (DWORD*)((DWORD)funcIndexTable + dwModuleBase);
    	funcsSize = expDescBuf->NumberOfFunctions;
    	namesSize = expDescBuf->NumberOfNames;
    	
    	// Not sure how this would happen, maybe corruption or intention?
    	if(funcsSize != namesSize)
    	{
    		printf("[%s] WARNING: funcsSize(%i) != namesSize(%i)", funcsSize, namesSize);
    	}
    
    	// Loop through all of the named functions
    	for(DWORD index = 0; index < namesSize; ++index)
    	{
    		DWORD ptrFuncAddr = 0;
    		char * name = 0;
    		unsigned long addr = 0;
    
    		// Handle the funcsSize != namesSize case to prevent 
    		// logic errors.
    		if(index < funcsSize)
    		{
    			ptrFuncAddr = (unsigned long)ptrFuncs[index];
    			addr = ptrFuncAddr + dwModuleBase;
    		}
    
    		name = (char*)(ptrNames[index] + dwModuleBase);
    
    		// If this is true, the function is forwarded
    		if( ptrFuncAddr >= dataDirectory->VirtualAddress && 
    			ptrFuncAddr < dataDirectory->VirtualAddress + dataDirectory->Size)
    		{
    			char * forwardExport = (char * )UlongToPtr(addr);
    			size_t len = strlen(forwardExport);
    			char * moduleName = new char[len];
    			char * moduleFunc = new char[len];
    			memset(moduleName, 0, len);
    			memset(moduleFunc, 0, len);
    			for(size_t x = 0; x < len; ++x)
    			{
    				if(forwardExport[x] == '.')
    				{
    					memcpy(moduleName, forwardExport, x);
    					memcpy(moduleFunc, forwardExport + x + 1, len - x - 1);
    					break;
    				}
    			}
    			HMODULE hNewDLL = GetModuleHandleA(moduleName);
    			FARPROC fp = GetProcAddress(hNewDLL, moduleFunc);
    			delete [] moduleName;
    			delete [] moduleFunc;
    			printf("* %s -> %s (%X)\n", name, UlongToPtr(addr), PtrToUlong(fp));
    		}
    
    		// Otherwise, a normal export, or something gone wrong if addr == 0
    		else
    		{
    			printf("%s @ %X\n", name, addr);
    		}
    	}
    }
    
    int main(int argc, char * argv[])
    {
    	HMODULE hDLL = LoadLibraryA("FwdDLL.dll");
    	if(hDLL == 0)
    	{
    		printf("Could not get a handle to the DLL.\n");
    		return 0;
    	}
    	GetAllExports(hDLL);
    	FreeLibrary(hDLL);
    }
    Most notably, your code does not handle 'Forwarded Exports', so that is something I added. Next, the address calculation code for your exported functions is not right either, it has to do with how you are using a WORD when a DWORD should be used instead for the funcIndexTable. You can open a DLL in Olly and check the output of your code that way as well, it's what I first did to notice the problem.

    If you want to make your own DLL that forwards some exports, you can use the following simple code and def file and create an empty DLL project in Visual Studio and compile. If all works out well, you should be able to use Dependency Walker to verify the forward exported function as well as using my code to see them.

    FwdDLL.cpp
    Code:
    extern "C" __declspec(dllexport) void Test1()
    {
    }
    FwdDLL.def
    Code:
    LIBRARY FwdDLL
    EXPORTS
    	Test1
    	Test2 = Kernel32.HeapAlloc
    To link the DEF with the project (in case someone else reading this does not know how) simply go to Project->Properties->Configuration Properties->Linker->Input and type "FwdDLL.def" into the "Module Definition File" edit box. You should then be able to compile and load the DLL into Dependency Walker as previously mentioned.

    Finally, here's an updated version of your code that should be correct. I did simple testing and it worked out well, but nothing too extensive, there might be other issues that have to be worked around, but this is just a start down to having a more flexible function:
    Code:
    unsigned long cAddressTable::SearchEATForAddress(char* expSymbolName, AddressTable* adrTable)
    {
    	AddressTable* selTable = (adrTable == 0 ? &m_addrTable : adrTable);
    
    	DWORD* ptrFuncs;
    	DWORD* ptrNames;
    	DWORD*  funcIndexTable;
    
    	DWORD funcsSize;
    	DWORD namesSize;
    
    	_IMAGE_EXPORT_DIRECTORY* expDescBuf = (_IMAGE_EXPORT_DIRECTORY*)(selTable->tableOffset + selTable->moduleBase);	
    	ptrFuncs       = (DWORD*)expDescBuf->AddressOfFunctions;	
    	ptrNames       = (DWORD*)expDescBuf->AddressOfNames;
    	funcIndexTable = (DWORD*) expDescBuf->AddressOfNameOrdinals;
    
    	ptrNames = (DWORD*)((DWORD)ptrNames + selTable->moduleBase);
    	ptrFuncs = (DWORD*)((DWORD)ptrFuncs + selTable->moduleBase);
    	funcIndexTable = (DWORD*)((DWORD)funcIndexTable + selTable->moduleBase);
    
    	funcsSize = expDescBuf->NumberOfFunctions;
    	namesSize = expDescBuf->NumberOfNames;
    
    	for(DWORD i = 0; (i < namesSize && i < funcsSize); i++)
    	{
    		if(!strcmp(expSymbolName, (char*)(ptrNames[i] + selTable->moduleBase)))
    		{
    			if((unsigned long)ptrFuncs[i] >= adrTable->tableOffset && (unsigned long)ptrFuncs[i] <= adrTable->tableOffset + adrTable->size)
    			{
    				char * forwardExport = (char * )UlongToPtr(ptrFuncs[i] + selTable->moduleBase);
    				size_t len = strlen(forwardExport);
    				char * moduleName = new char[len];
    				char * moduleFunc = new char[len];
    				memset(moduleName, 0, len);
    				memset(moduleFunc, 0, len);
    				for(size_t x = 0; x < len; ++x)
    				{
    					if(forwardExport[x] == '.')
    					{
    						memcpy(moduleName, forwardExport, x);
    						memcpy(moduleFunc, forwardExport + x + 1, len - x - 1);
    						break;
    					}
    				}
    				HMODULE hNewDLL = GetModuleHandleA(moduleName);
    				FARPROC fp = GetProcAddress(hNewDLL, moduleFunc);
    				delete [] moduleName;
    				delete [] moduleFunc;
    				return PtrToUlong(fp);
    			}
    			else
    			{
    				return ptrFuncs[i] + selTable->moduleBase;
    			}
    		}
    	}
    	return 0;
    }
    You should be able to run that on any function and check the address in OllyDbg and it should be correct! Thanks for sharing the original code!

    [Edit] Noticed a small off by one bug:
    Code:
    if( ptrFuncAddr >= dataDirectory->VirtualAddress && ptrFuncAddr <= dataDirectory->VirtualAddress + dataDirectory->Size)
    should be:
    Code:
    if( ptrFuncAddr >= dataDirectory->VirtualAddress && ptrFuncAddr < dataDirectory->VirtualAddress + dataDirectory->Size)
    and has been fixed in the post.
    Last edited by pushedx; 11-05-2009 at 03:35 PM.

Tags for this Thread