#include <windows.h>
#include <string>
#include <list>
#include <iostream>
#include <algorithm>

using namespace std;

IMAGE_DOS_HEADER dos;
IMAGE_NT_HEADERS nt;
IMAGE_SECTION_HEADER sect;

list<IMAGE_SECTION_HEADER>  sects;


int VAtoFileOffset(int va){
	
	int vBase, vSize, vMax;
	IMAGE_SECTION_HEADER s;

	int rva =  va - nt.OptionalHeader.ImageBase  ;

	if(rva < 0) return -1;

	for( list<IMAGE_SECTION_HEADER>::iterator it = sects.begin(); it!=sects.end();it++){
		
	   s = *it;		
	   vBase = s.VirtualAddress ;
       vSize =  s.SizeOfRawData > s.Misc.VirtualSize ? s.SizeOfRawData : s.Misc.VirtualSize;     
       
       vMax = vBase + vSize;
       
       if( rva >= vBase && rva < vMax ){
            rva = rva - vBase;
            rva = rva + s.PointerToRawData;
            return rva;
       }
	
	}
	 
	return -1;

}

void main(void){

	
	OFSTRUCT o;
	DWORD l;
	int va;
	char filename[MAX_PATH];
	
	cout << "Enter filename to PE File:  ";
	cin >> filename;
	cout << endl << endl;

	HANDLE h =  (HANDLE)OpenFile(filename, &o , OF_READ);
	
	if( (int)h  < 1 ){
		cout << "Could not open file...";
		return;
	}

	ReadFile(h, &dos , sizeof(dos) ,&l,0);

	if(dos.e_lfanew < 1){
		cout << "invalid pointer to nt header\n";
		return;
	}

	SetFilePointer(h, dos.e_lfanew , 0, FILE_BEGIN);
	 
	ReadFile(h, &nt , sizeof(nt) ,&l,0);

	int sectionStart = dos.e_lfanew + 
                       nt.FileHeader.SizeOfOptionalHeader +  
                       sizeof(nt.FileHeader) + 
					   sizeof(nt.Signature) ;
	
	SetFilePointer(h, sectionStart , 0, FILE_BEGIN);

	ReadFile(h, &sect , sizeof(sect) ,&l,0);
	sects.push_back(sect); 

	for(int i = 1; i < nt.FileHeader.NumberOfSections; i++){
		 ReadFile(h, &sect , sizeof(sect) ,&l,0);
	 	 sects.push_back(sect);
	}
	
	CloseHandle(h);

	va = nt.OptionalHeader.ImageBase + nt.OptionalHeader.AddressOfEntryPoint;

	printf("Imagebase:          %x\n", nt.OptionalHeader.ImageBase );
	printf("EntryPoint VA:      %x\n", va);
	printf("EntryPoint RVA:     %x\n", nt.OptionalHeader.AddressOfEntryPoint );
	printf("EntryPoint FOffset: %x\n\n", VAtoFileOffset(va) ) ;
	
	printf("Name    ROffset   RawSize   VOffset   VSize\n");
	printf("-----------------------------------------------\n");

    for( list<IMAGE_SECTION_HEADER>::iterator it = sects.begin(); it!=sects.end();it++){
		sect = *it;
		printf("%s%8x%10x%10x%10x\n", sect.Name, sect.PointerToRawData, sect.SizeOfRawData, sect.VirtualAddress, sect.Misc.VirtualSize    );
	}
		
	cin.flags(ios_base::hex);
	cin.clear();  
    cin.ignore(80, '\n'); //cin is so gay
	 
	cout <<  "\nEnter VA Address to calc file offset for:  ";
	cin >> va;
	 
	va = VAtoFileOffset(va);
	if(va < 0){
		cout << "Doh..invalid VA address\n\n";
	}
	else{
		printf("\nSurvey Says: %x\n\n", va);
	}
	
	return;

}
