[C++]Sections in einem PE File auflisten

07/21/2010 11:32 Tyrar#1
vorweg:
das ist ein tut für erfahrene user, und auch kein copy & paste tut ;)
die vorraussetzungen hierfür sind:
grundkenntnisse über den aufbau des PE formats (wobei ich darauf nochmal kurz eingehe)
filemapping (auf bestimmte adressen zugreifen) ODER kompliziertes normales file handling.
etwas methematik wissen ;)

was ihr besitzen solltet:
einen pc :p
eine gute IDE
windows.h, winnt.h
und eine test.exe

die theorie:
in der theorie ist alles wie immer ganz einfach.
man öffnet die datei, liest die wichtigen header ein (DOS, PE), und dann liest man die section header.
das wars sogar schon mit der theorie o.O

die praxis:
in der praxis ist es in diesem fall genau so einfach wie in der theorie.
als erstes muss die datei via CreateFile geöffnet, via CreateFileMapping gemappt, und mit MapViewOfFile der pointer geholt werden.
zum start der datei steht der MZ (DOS) header. den liest man ganz einfach mit
Code:
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)ptr;
ein. (ptr = MapViewOfFile ;))
um zu prüfen ob das überhaupt eine "echte" datei ist, muss e_magic im header überprüft werden. (abgleich mit IMAGE_DOS_SIGNATURE)
am offset 0x3C steht ein DWORD mit dem offset des PE headers. (oder einfach nur e_lfanew aus dem dos header)
mit
Code:
PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)(ptr+dos->e_lfanew);
kommt man auch gleich an den pe header.
dieser wird ebenfalls überprüft. (nt->Signature==IMAGE_NT_SIGNATURE)
von nun an wird alles ganz einfach: es gibt ein macro, mit dem man den header der ersten section bekommt:
Code:
PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)IMAGE_FIRST_SECTION(nt);
sobals man den hat, muss man nurnoch eine schleife starten, die alle sections abarbeitet. in nt->FileHeader.NumberOfSections steht die anzahl der sections.
mit pSection++ kann man direkt auf die nächste section zugreifen ;)
pSection->Name ist ein 8 byte array mit dem namen der section ;)

hoffe mal dass es wenigstens einer von euch versteht, und es auch geholfen hat XD
07/22/2010 10:31 BestOfElite#2
Hmm ma gucken nur leider kann ich kein c++ xD
07/24/2010 11:47 Jay Niize#3
naja.. hab ich zwar nicht verstanden, sieht aber nützlich aus, für die die C++ können :D

#Added to list
08/11/2010 19:41 Mr0x90#4
so erfahren muss man dafür nun wirklich auch nicht sein, das tutorial ist ohne kontext komplett sinnlos und anscheinend hast du auch gerade erst angefangen dich mit dem pe-header zu befassen
10/13/2010 20:28 yihaaa#5
Sehr schön erklärt. Aber ich habe eine Frage, wie komme ich den die Infos her, wo ein JMP oder ein NOP in der Datei steht? Ich habe bis jetz erst den Entry Point herausgefunden.

Code:
	IMAGE_DOS_HEADER* DOSHeader = (IMAGE_DOS_HEADER*)myFile;

	IMAGE_NT_HEADERS* NTHeader = (IMAGE_NT_HEADERS*)(myFile + DOSHeader->e_lfanew);

	IMAGE_OPTIONAL_HEADER Header = NTHeader->OptionalHeader;

	DWORD MyEntryPoint = Header.AddressOfEntryPoint;

	DWORD MyImageBase = Header.ImageBase;

	DWORD MyEntry = MyImageBase + MyEntryPoint;

	cout << "Entry Point ist bei: " << hex << MyEntry << endl;
Ich hoffe mir kann jemand weiterhelfen.
10/14/2010 10:43 mydoom#6
Quote:
Originally Posted by yihaaa View Post
[...] wo ein JMP oder ein NOP in der Datei steht?
NOP (No Operation) - 0x90
JMP (Jump) - {0xE9 || 0xEB || 0xFF}
10/14/2010 11:26 yihaaa#7
Ja das weiß ich, ich meite wie findet man das heraus, wo welcher befehl steht, wenn man die Datei wenn ich das einlese.
10/14/2010 16:12 mydoom#8
Ja du hast die Datei doch binär eingelesen oder nicht. Dann kannste doch auch auf die einzelnen Bytes selbiger zugreifen?!
10/14/2010 17:34 yihaaa#9
Muss man das nicht auch wie mit den Headern machen?
So ist mein Code im Moment.
Code:
	char* Path = "C:\\test.exe";
	LARGE_INTEGER largefilesize;

	HANDLE hwnd = CreateFile(Path, FILE_SHARE_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL);

	GetFileSizeEx(hwnd, &largefilesize);

	DWORD dwSize;
	dwSize = (DWORD)largefilesize.QuadPart;

	BYTE* myFile = new BYTE[ dwSize ];

	DWORD dwBytesRead;
	if(ReadFile(hwnd, (LPVOID)myFile, dwSize, &dwBytesRead, NULL) == TRUE)
	{
		cout << "Datei konnte gelesen werden!" << endl;
	}
	else
	{
		cout << "Fehler beim lesen der Datei!" << endl;
		return -1;
	}

	IMAGE_DOS_HEADER* DOSHeader = (IMAGE_DOS_HEADER*)myFile;

	IMAGE_NT_HEADERS* NTHeader = (IMAGE_NT_HEADERS*)(myFile + DOSHeader->e_lfanew);

	IMAGE_OPTIONAL_HEADER Header = NTHeader->OptionalHeader;

	DWORD MyEntryPoint = Header.AddressOfEntryPoint;

	DWORD MyImageBase = Header.ImageBase;

	DWORD MyEntry = MyImageBase + MyEntryPoint;

	cout << "Entry Point ist bei: " << hex << MyEntry << endl;

	IMAGE_SECTION_HEADER* sectionTable = (IMAGE_SECTION_HEADER*)((BYTE*)&NTHeader->OptionalHeader + NTHeader->FileHeader.SizeOfOptionalHeader);


	/*for (int i = 0; i < 10; i++)
	{
		cout << &sectionTable[ i ] << endl;
	}*/

	return 0;
Aber wie komme ich den jetz an den Code?