Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 02-25-2011, 08:52
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Question Get APi from the address

we always do this to get the API addresss

GetAPIAddress = GetProcAddress(GetModuleHandle("Kernel.dll),FunctionName)

to get the Address of the API .
but what the programmatic way to get the API of the address .
like if we have this :
Quote:
2FEB1344 >7611FC28 (��v kernel32.LockFile
if I have 2FEB1344 how I could know for which API it relative too !!

( I need the reverse way of GetProcAddress )
Thanks in adv
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #2  
Old 02-25-2011, 14:55
Nacho_dj's Avatar
Nacho_dj Nacho_dj is offline
Lo*eXeTools*rd
 
Join Date: Mar 2005
Posts: 211
Rept. Given: 16
Rept. Rcvd 179 Times in 34 Posts
Thanks Given: 44
Thanks Rcvd at 137 Times in 41 Posts
Nacho_dj Reputation: 100-199 Nacho_dj Reputation: 100-199
Since it is a handle in memory and it is linked to the imagebase of its module loaded by the system, you need:
- Getting all processes loaded in memory, thus retrieving their imagebase and size, their module name, and so on...
- Determining which process the handle belongs to, getting in this way the module that is exporting it.
- Go analyzing export table of that module to find the handle (in RVA), and then get the function name, if this exists in the functions names table. Ordinal can always be retrieved.
- If there is forwarding, you should try to find which is the module that is the origin of forward, to get the function name inside it.

Cheers

Nacho_dj
__________________
http://arteam.accessroot.com
Reply With Quote
  #3  
Old 02-25-2011, 19:35
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Thanks Nacho_dj ....
This idea have come to my mind . but I note that it could make this process take a lot of time ..
I have check "Import REConstructor" and "CHimpREC"
and I have note that "Import REConstructor" didn't take the time which "CHimpREC" take it .
it is more faster .
so is there fast way to get this or it will depended on the algorithm of the code it self !!
Thanks for replay
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #4  
Old 02-25-2011, 20:19
Nacho_dj's Avatar
Nacho_dj Nacho_dj is offline
Lo*eXeTools*rd
 
Join Date: Mar 2005
Posts: 211
Rept. Given: 16
Rept. Rcvd 179 Times in 34 Posts
Thanks Given: 44
Thanks Rcvd at 137 Times in 41 Posts
Nacho_dj Reputation: 100-199 Nacho_dj Reputation: 100-199
Yeah, it depends strongly of the algo used and the way of accessing files.

I have checked that, for instance, some tools load in memory the content of an entire file, whilst other just load the section of the file needed, so it will get much faster because of managing less memory space.

If you need more detailed data I could post it here...

Cheers

Nacho_dj
__________________
http://arteam.accessroot.com
Reply With Quote
The Following User Gave Reputation+1 to Nacho_dj For This Useful Post:
ahmadmansoor (02-25-2011)
  #5  
Old 02-25-2011, 20:44
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Quote:
If you need more detailed data I could post it here...
yes pls .....
many thanks
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #6  
Old 02-26-2011, 03:36
Nacho_dj's Avatar
Nacho_dj Nacho_dj is offline
Lo*eXeTools*rd
 
Join Date: Mar 2005
Posts: 211
Rept. Given: 16
Rept. Rcvd 179 Times in 34 Posts
Thanks Given: 44
Thanks Rcvd at 137 Times in 41 Posts
Nacho_dj Reputation: 100-199 Nacho_dj Reputation: 100-199
How to retrieve every function name in a loaded application (executable or dll) - Part I

I have used Delphi code to implement this, so pseudocode will be near to Delphi...

1. Create an instance of tagMODULEENTRY32:

tagMODULEENTRY32.dwSize := SizeOf(MODULEENTRY32);

2. Get process information inside the sanapshot:
hSnapShot := CreateToolHelp32SnapShot(TH32CS_SNAPMODULE,lpProcessInformation.dwProcessId);

3. Retrieve first module loaded in your process:
Module32First(hSnapShot,tagMODULEENTRY32)

If the function succeeds, you have got some module information, like this:
tagMODULEENTRY32.modBaseAddr
tagMODULEENTRY32.modBaseSize

Store it in an struct inside an array, and then, start a loop to get the others processes info:
Module32Next(hSnapShot,tagMODULEENTRY32)
If the function succeeds, you have got several module information, like this:
tagMODULEENTRY32.modBaseAddr
tagMODULEENTRY32.modBaseSize

The loop ends when the previous function doesn't succeed.

4. For everyone of the modules previously stored in your array, get the export table. This will be used later.
You just need to read PE header, and get the export table rva & size from data directories.

Get the IMAGE_EXPORT_DIRECTORY structure and store it in an array for every process loaded.

5. Get the import table addresses minimum and maximum bounds. There could be several methods to do it. I prefer reading the entire code section and get all references to imported functions by analyzing every opcode like this table shows:
Code:
FF35 | PUSH [virtual address]
A1   | MOV EAX,[virtual address]
8B0D | MOV ECX,[virtual address]
8B15 | MOV EDX,[virtual address]
8B1D | MOV EBX,[virtual address]
8B25 | MOV ESP,[virtual address]
8B2D | MOV EBP,[virtual address]
8B35 | MOV ESI,[virtual address]
8B3D | MOV EDI,[virtual address]
FF15 | CALL [virtual address]
FF25 | JMP [virtual address]
For everyone of the addresses, validate that it is inside memory of your main process, then get the handle, and then try to find its function name or ordinal, as follows. If you succeed, it belongs to IAT. Get with a clever algo this:
Mimimum IAT address RVA
Maximum IAT address RVA

For every iteration, you only need to validate that a handle is valid if the RVA of the handle is out of minimum and maximum RVA previosly computed.


To find a valid handle for imported function, first check in a loop that it belongs to any of the processes loaded:

Code:
for i := 0 to Length(TableProcess) - 1 do
        if (hndFunc > TableProcess[i].modBaseAddr) AND
          (hndFunc < (TableProcess[i].modBaseAddr + TableProcess[i].modBaseSize)) then
begin
  GetFunctionNameAndOrdinal(...)
end;
To be continued...

Nacho_dj
__________________
http://arteam.accessroot.com
Reply With Quote
The Following 3 Users Gave Reputation+1 to Nacho_dj For This Useful Post:
ahmadmansoor (02-26-2011), chessgod101 (02-26-2011)
  #7  
Old 02-26-2011, 04:32
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Thanks Nacho_dj ,,, very nice explanation .
I will wait the continue .
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #8  
Old 02-26-2011, 09:18
D-Jester's Avatar
D-Jester D-Jester is offline
VIP
 
Join Date: Nov 2003
Location: Ohio, USA
Posts: 269
Rept. Given: 39
Rept. Rcvd 61 Times in 41 Posts
Thanks Given: 0
Thanks Rcvd at 4 Times in 4 Posts
D-Jester Reputation: 61
This might be useful

http://www.masm32.com/board/index.php?topic=5996.0
__________________
Even as darkness envelops and consumes us, wrapping around our personal worlds like the hand that grips around our necks and suffocates us, we must realize that life really is beautiful and the shadows of despair will scurry away like the fleeting roaches before the light.
Reply With Quote
The Following 2 Users Gave Reputation+1 to D-Jester For This Useful Post:
chessgod101 (02-26-2011)
  #9  
Old 02-26-2011, 09:34
Fyyre's Avatar
Fyyre Fyyre is offline
Fyyre
 
Join Date: Dec 2009
Location: 0°N 0°E / 0°N 0°E / 0; 0
Posts: 295
Rept. Given: 106
Rept. Rcvd 93 Times in 44 Posts
Thanks Given: 203
Thanks Rcvd at 397 Times in 130 Posts
Fyyre Reputation: 93
You want custom GetProcAddress?

Code:
PVOID FastGetProcAddress(PCHAR DllBase, PCHAR RoutineName)
{
	USHORT OrdinalNumber;
	PULONG NameTableBase;
	PUSHORT NameOrdinalTableBase;
	PULONG Addr;
	ULONG High;
	ULONG Low;
	ULONG Middle;
	LONG Result;
	ULONG ExportSize;
	PVOID FunctionAddress;
	PIMAGE_EXPORT_DIRECTORY ExportDirectory;


	ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)
		RtlImageDirectoryEntryToData(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportSize);
	NameTableBase = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfNames);
	NameOrdinalTableBase = (PUSHORT)(DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
	Low = 0;
	High = ExportDirectory->NumberOfNames - 1;
	while (High >= Low)
	{
		Middle = (Low + High) >> 1;
		Result = strcmp(RoutineName,
						(PCHAR)(DllBase + NameTableBase[Middle]));
		if (Result < 0)
		{
			High = Middle - 1;
		}
		else if (Result > 0)
		{
			Low = Middle + 1;
		}
		else
		{
			break;
		};
	};
	if (High < Low)
	{
		return NULL;
	};
	OrdinalNumber = NameOrdinalTableBase[Middle];
	if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions)
	{
		return NULL;
	};
	Addr = (PULONG)(DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
	FunctionAddress = (PVOID)(DllBase + Addr[OrdinalNumber]);
	return FunctionAddress;
};
Quote:
Originally Posted by ahmadmansoor View Post
we always do this to get the API addresss

GetAPIAddress = GetProcAddress(GetModuleHandle("Kernel.dll),FunctionName)

to get the Address of the API .
but what the programmatic way to get the API of the address .
like if we have this :


if I have 2FEB1344 how I could know for which API it relative too !!

( I need the reverse way of GetProcAddress )
Thanks in adv
Reply With Quote
  #10  
Old 02-27-2011, 20:53
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Thanks D-Jester and Fyyre ...
but what i mean that I have the address memory , and I want to know which API related to this address memory .
that what I mean .
@ Fyyre : thanks for nice code ... easy and can be useful .
in ur code it need this too
Quote:
PVOID NTAPI RtlImageDirectoryEntryToData ( PVOID BaseAddress,
BOOLEAN MappedAsImage,
USHORT Directory,
PULONG Size
) ;
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #11  
Old 02-28-2011, 03:31
dila dila is offline
Friend
 
Join Date: Jan 2010
Posts: 60
Rept. Given: 12
Rept. Rcvd 32 Times in 14 Posts
Thanks Given: 35
Thanks Rcvd at 74 Times in 20 Posts
dila Reputation: 32
It sounds like he wants reverse GetProcAddress. Like the sort of code "analysis" you find next to CALL instructions in OllyDbg.

I've been looking at doing this for adding details to beaengine output and it goes like this:
  • Subtract the CALL RVA back to the image base.
  • Then subtract it back to the import library FirstThunk base address (remember there are two IAT arrays for each module, the file one and the one that is fixed up at runtime). Divide by the sizeof each element (DWORD) to make it into a 0...N index into the IAT array.
  • Use that index to get the import name out of the library names array.
  • Then the code builds an OllyDbg style "Library.Func" or "Library.#Ordinal" string for asm comment.

Code:
QString importFromRva( const PeFile *peFile, uint64_t addr )
{
    if ( addr )
    {
        addr -= peFile->imageBase();
        addr = addr;

        for ( uint32_t lib = 0; lib < peFile->importLibraryCount(); ++lib )
        {
            PeFile::ImportLibrary library;
            if ( !peFile->importLibrary(&library,lib) )
            {
                continue;
            }

            uint32_t offset = addr - library.;

            offset /= sizeof(DWORD);

            if ( offset < peFile->importAddressCount(&library) )
            {
                PeFile::ImportAddress address;
                if ( peFile->importAddress(&address,&library,offset) )
                {
                    if ( address.name )
                    {
                        return QString(library.name).toUpper() + QString(".") + QString(address.name);
                    }
                    else // by ordinal
                    {
                        return QString(library.name).toUpper() + QString(".#") + QString::number(address.ordinal,16);
                    }
                }
            }
        }

    }

    return QString();
}
Reply With Quote
The Following User Gave Reputation+1 to dila For This Useful Post:
ahmadmansoor (02-28-2011)
  #12  
Old 02-28-2011, 03:49
dila dila is offline
Friend
 
Join Date: Jan 2010
Posts: 60
Rept. Given: 12
Rept. Rcvd 32 Times in 14 Posts
Thanks Given: 35
Thanks Rcvd at 74 Times in 20 Posts
dila Reputation: 32
see attached: proof of concept screenshot
Attached Images
File Type: png reverse_getprocaddress.png (26.7 KB, 26 views)
Reply With Quote
The Following User Gave Reputation+1 to dila For This Useful Post:
ahmadmansoor (02-28-2011)
  #13  
Old 02-28-2011, 08:33
ahmadmansoor's Avatar
ahmadmansoor ahmadmansoor is offline
Coder
 
Join Date: Feb 2006
Location: Syria
Posts: 1,047
Rept. Given: 517
Rept. Rcvd 374 Times in 142 Posts
Thanks Given: 380
Thanks Rcvd at 416 Times in 119 Posts
ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399 ahmadmansoor Reputation: 300-399
Thanks dila .... I will try it .
and I will back with result .
Thanks in adv ..
__________________
Ur Best Friend Ahmadmansoor
Always My Best Friend: Aaron & JMI & ZeNiX
Reply With Quote
  #14  
Old 02-28-2011, 14:38
BoB's Avatar
BoB BoB is offline
Lo*eXeTools*rd
 
Join Date: Jun 2009
Location: England
Posts: 85
Rept. Given: 88
Rept. Rcvd 56 Times in 24 Posts
Thanks Given: 2
Thanks Rcvd at 2 Times in 2 Posts
BoB Reputation: 56
Cool

Ah but Dila, that only works if the Imports.OrigFirstThunk array is valid

Code:
//-----------------------------------------------------------------------//
// Get Api Name from address ..  (Reverse GetProcAddress)

Function  GetProcAddressName(Const ApiAddress : DWord) : String;
Var
  I,
  Base,                         // Module base address ..
  Rva : DWord;                  // Rva of Api ..
  FA,                           // Pointer to Functions Array ..
  NA  : PDWord;                 // Pointer to Names Array ..
  Exp : PImageExportDirectory;  // Export Table ..
  Dos : PImageDosHeader;        // Dos Header ..
  Nt  : PImageNtHeaders;        // Nt Headers ..
Begin
  Result := 'Error';

  // Calc module base address from API address ..
  Base := ApiAddress;
  Repeat
    NT := Nil;
    Dec(Base);
    Base := Base And $FFFFF000;  // Align to page size ..
    If (Not IsBadReadPtr(Pointer(Base), 4)) Then Begin
      Dos := Pointer(Base);
      If (Dos^.Magic = IMAGE_DOS_SIGNATURE) Then Nt := Pointer(Base + Dos^.OffsetPE);
    End;
  Until (Not IsBadReadPtr(NT, 4)) And (NT^.Signature = IMAGE_NT_SIGNATURE);

  // Search for the Rva in the Function Array of the export table ..
  Exp := Pointer(Base + NT^.OptionalHeader.DataDirectory[0].Rva);
  Rva := ApiAddress - Base;
  FA  := Pointer(Base + Exp^.RvaOfFunctions);
  NA  := Pointer(Base + Exp^.RvaOfNames);
  For I := 0 To Exp^.NumberOfFunctions-1 Do Begin
    If (Rva = FA^) Then Begin
      // Return name or ordinal string ..
      Result := PAnsiChar(Base + Exp^.Name) + '!';
      If (I < Exp^.NumberOfNames) Then Result := Result + PAnsiChar(Base + NA^)
      Else Result := Result + '#' + IntToStr(Exp^.Base + I);
      Break;
    End;
    Inc(FA);
    Inc(NA);
  End;
End;
Simple usage like this:
Code:
  Api := DWord(GetProcAddress(KernelBase, 'HeapCreate'));
  MessageBox(0, PChar(GetProcAddressName(Api)), Nil, MB_OK);
Would show:
Code:
KERNEL32.dll!HeapCreate
Ahmadmansoor: If you want it rewriting in Asm or anything let me know.

Excuse any weird code, it's 6:30 am and I need to sleep
BoB

Last edited by BoB; 02-28-2011 at 14:44.
Reply With Quote
The Following 2 Users Gave Reputation+1 to BoB For This Useful Post:
ahmadmansoor (02-28-2011)
  #15  
Old 02-28-2011, 22:02
V0ldemAr
 
Posts: n/a
My implementation in CPP, Use VirtualQuery to get module base and check if it's really module then parse export table and get api name or ordinal. PS: Code is old and may contain bugs was fastly coded few years ago
Attached Files
File Type: txt addr2apiname.cpp.txt (3.1 KB, 33 views)
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
fake mac address theGate General Discussion 16 08-13-2022 10:12
Get real address of api not nt version Mahmoudnia General Discussion 18 05-23-2018 00:44
Finding API Address britedream General Discussion 5 10-05-2006 21:28
how to get the address of the entry point in an API Warren General Discussion 6 08-30-2005 16:18


All times are GMT +8. The time now is 07:52.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( Since 1998 )