A forum for reverse engineering, OS internals and malware analysis 

Ask your beginner questions here.
 #11851  by Tigzy
 Mon Feb 27, 2012 5:57 pm
Hello

I have a newbie question.
I had a doubt about something :D

Let's assume we have a binary "binary.exe", with some address A on the physical disk.
then, we load this in memory, let's say at memory offset B.

Is it true to say the exported function F which can be found at B+addr_F can also be found on the disk at A+addr_F ?
Sorry if it's obvious for you, but I needed to clarify this :oops:
Last edited by Tigzy on Mon Feb 27, 2012 7:33 pm, edited 1 time in total.
 #11852  by rkhunter
 Mon Feb 27, 2012 6:10 pm
For PE files there are alignment of it sections on disk (raw) and in memory (virtual). These values specified in the PE-header. So, when PE-file stored at disk there are raw offsets correct, else if it in memory - virtual. Look MS PE and COFF Specification or Windows SDK - IMAGE_NT_HEADERS structure.
You need to parse export table?
 #11853  by Tigzy
 Mon Feb 27, 2012 7:36 pm
You need to parse export table?
No. To be honest, I wonder if I can restore inline hooks in ntoskrnl.exe by looking at its physical image on the disk for the concerned function.
 #11857  by everdox
 Tue Feb 28, 2012 1:56 am
hey,

rkhunter covered it well. Check here for good documentation on the PE format:

http://msdn.microsoft.com/en-us/windows ... e/gg463119

when an image is mapped with SEC_IMAGE that format is followed, so where the first section in memory would generally be at header+0x1000, it could be at something like 0x400 within the actual harddisk image.

Also what you mentioned about reading into the harddisk image to overwrite possible hooks I have seen done before, but for other purposes. For instance a piece of malware that would want to evade a breakpoint at the actual location of ntdll!NtWriteVirtualMemory, it could read out the function's syscall index then create it's own wrapper for the call.
 #11873  by Tigzy
 Tue Feb 28, 2012 5:34 pm
Hello

I just read the documentation and began to code a PE parser.
I got the RVA address of Export / Import tables and sections (.text, .rsrc and so on), but it shows address larger that the size of my file on the disk :shock:

These address are used to find the sections on the disk image or in the object image?
 #11875  by rkhunter
 Tue Feb 28, 2012 6:28 pm
Tigzy wrote: I got the RVA address of Export / Import tables and sections (.text, .rsrc and so on), but it shows address larger that the size of my file on the disk :shock:
Probably you're doing something wrong...Show your code.
Tigzy wrote: These address are used to find the sections on the disk image or in the object image?
What is "object image"?
 #11876  by Tigzy
 Tue Feb 28, 2012 6:49 pm
Here's my code :

Code: Select all
// peInfo.cpp : définit le point d'entrée pour l'application console.
//

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>

bool parseFile(TCHAR* filePath);
bool getDosHeader(FILE* f, PIMAGE_DOS_HEADER pDosHeader);
bool getNtHeaders(FILE* f, PIMAGE_NT_HEADERS pNtHeaders, LONG offset);
bool getSections(FILE* f, PIMAGE_SECTION_HEADER pSectionHeaders, int nbSections, LONG offset);

int _tmain(int argc, _TCHAR* argv[])
{
	//parseFile(L"C:\\Documents and Settings\\Tigzy\\Mes documents\\Visual Studio 2010\\Projects\\testSimple\\Debug\\testSimple.exe");
	parseFile(L"C:\\Tools\\ThreatBlaster\\Hook\\Hook\\Debug\\Hook.dll");
	//parseFile(L"C:\\windows\\system32\\ntoskrnl.exe");
	system("PAUSE");
	return 0;
}

bool parseFile(TCHAR* filePath)
{
	FILE *f;	
	BYTE NameSection[IMAGE_SIZEOF_SHORT_NAME+1];
	IMAGE_DOS_HEADER DosHeader;
	IMAGE_NT_HEADERS NtHeaders;
	PIMAGE_SECTION_HEADER pSectionHeaders;

	f = _tfopen(filePath, L"r");
	if (f != NULL)
	{
		// Get dos header
		if (!getDosHeader(f, &DosHeader))
			return false;

		// Get PE header
		if (!getNtHeaders(f, &NtHeaders, DosHeader.e_lfanew))
			return false;

		// allocate space for sections
		pSectionHeaders = (PIMAGE_SECTION_HEADER) malloc(sizeof(IMAGE_SECTION_HEADER) * NtHeaders.FileHeader.NumberOfSections);
		getSections(f, pSectionHeaders, NtHeaders.FileHeader.NumberOfSections, DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS));
		for (int i = 0; i < NtHeaders.FileHeader.NumberOfSections ; i++)
		{
			memset(NameSection, '\0', IMAGE_SIZEOF_SHORT_NAME+1);
			memcpy(NameSection, pSectionHeaders[i].Name, IMAGE_SIZEOF_SHORT_NAME);

			printf ("%s : 0x%x\n", NameSection, pSectionHeaders[i].VirtualAddress);
		}
		free (pSectionHeaders);

		// Import table
		printf ("Import table : 0x%x -- %d\n", NtHeaders.OptionalHeader.DataDirectory[1].VirtualAddress, NtHeaders.OptionalHeader.DataDirectory[1].Size);

		// Export table
		printf ("Export table : 0x%x -- %d\n", NtHeaders.OptionalHeader.DataDirectory[0].VirtualAddress, NtHeaders.OptionalHeader.DataDirectory[0].Size);

		fclose (f);
		return true;
	}

	return false;
}

bool getDosHeader(FILE* f, PIMAGE_DOS_HEADER pDosHeader)
{	
	// beginning
	fseek(f, 0, SEEK_SET);

	// read
	fread(pDosHeader, sizeof(BYTE), sizeof(IMAGE_DOS_HEADER), f);

	// Is valid header
	if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
		return true;
	else return false;
}

bool getNtHeaders(FILE* f, PIMAGE_NT_HEADERS pNtHeaders, LONG offset)
{	
	// at offset getted from dos header
	fseek(f, offset, SEEK_SET);

	// read
	fread(pNtHeaders, sizeof(BYTE), sizeof(IMAGE_NT_HEADERS), f);

	// Is valid header
	if (pNtHeaders->Signature == IMAGE_NT_SIGNATURE)
		return true;
	else return false;
}

bool getSections(FILE* f, PIMAGE_SECTION_HEADER pSectionHeaders, int nbSections, LONG offset)
{	
	// at offset
	fseek(f, offset, SEEK_SET);

	// read
	fread(pSectionHeaders, sizeof(BYTE), sizeof(IMAGE_SECTION_HEADER) * nbSections, f);

	return true;
}

What I got:
Last line of the file : 0x63010
Capture.PNG
Capture.PNG (118.92 KiB) Viewed 436 times
What is "object image"?
I mean Image in RAM
 #11877  by r2nwcnydc
 Tue Feb 28, 2012 8:43 pm
RVAs are the addresses in memory relative to the beginning of the image. If you are parsing the file from disk, you have to look at the raw address, which is the offset from the start of the flie. Download CFF Explorer, or something similar, and compare your results to what it outputs.