Jump to content

Structure of an executable


Recommended Posts

Not really, the file could have any number of resources, so byte x to byte y would need to be calculated on the fly.

Except that the resources come after the code sections I believe.

Oh by the way, here's a copy of the latest specification via Microsoft. http://msdn.microsoft.com/en-us/windows/hardware/gg463119.aspx

Would probably be a good place to start.

Edited by Richard Robertson
Link to comment
Share on other sites

I've not gotten very far with this, but I'd appreciate hints whether I'm on the right path before I even move on.

int _tmain(int argc, _TCHAR* argv[]){

    HANDLE hFile = CreateFile(
        L"snatch.exe",              //LPWCTSTR lpFileName
        GENERIC_READ,               //DWORD dwDesiredAccess
        FILE_SHARE_READ,            //DWORD dwShareMode
        nullptr,                    //LPSECURITY_ATTRIBUTES lpSecurityAttributes
        OPEN_EXISTING,              //DWORD dwCreationDisposition
        FILE_ATTRIBUTE_NORMAL,      //DWORD dwFlagsAndAttributes
        nullptr                     //HANDLE hTemplateFile
        );
    if ( hFile == INVALID_HANDLE_VALUE ){
        printf("Failed with CreateFile\n");
        return -1; 
    }

    HANDLE hFileMapping = CreateFileMapping(
        hFile,                                  //HANDLE hFile
        nullptr,                                //LPSECURITY_ATTRIBUTES lpAttributes
        PAGE_READONLY,                          //DWORD flProtect
        0,                                      //DWORD dwMaximumSizeHigh
        0,                                      //DWORD dwMaximumSizeLow
        nullptr                                 //LPCTSTR lpName    
        );
    if (!hFileMapping){
        CloseHandle(hFile);
        printf("Failed with CreateFileMapping\n");
        return -2;
    }

    LPVOID lpBaseAddress = MapViewOfFile(
        hFileMapping,                       //HANDLE hFileMappingObject
        FILE_MAP_READ,                      //DWORD dwDesiredAccess
        0,                                  //DWORD dwFileOffsetHigh
        0,                                  //DWORD dwFileOffsetLow
        0                                   //SIZE_T dwNumberOfBytesToMap
        );
    if (!lpBaseAddress){
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        printf("Failed with MapViewOfFile\n");
        return -3;
    }

    PIMAGE_DOS_HEADER dosHeader = static_cast<PIMAGE_DOS_HEADER>(lpBaseAddress);
    if (!dosHeader->e_magic == IMAGE_DOS_SIGNATURE){
        printf("Incorrect File Type\n");
        CloseHandle(hFileMapping);
        CloseHandle(hFile);
        return -4;
    }



    CloseHandle(hFileMapping);
    CloseHandle(hFile);
    return 0;
}

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Well I thought (for some reason) that the location of resources section could be found in dosHeader IMAGE_DOS_HEADER structure, which it seems it is not.

Also is this method valid to get where I am in the above code.

HMODULE hModule = GetModuleHandle(L"snatch.exe");
if(!hModule){
    return -1;
}
PIMAGE_DOS_HEADER dosHeader = static_cast<PIMAGE_DOS_HEADER>(hModule);

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

It's not DOS executable, PE format just has DOS stub.

The first few hundred bytes of the typical PE file are taken up by the MS-DOS stub. This stub is a tiny program that prints out something to the effect of "This program cannot be run in MS-DOS mode." So if you run a Win32-based program in an environment that doesn't support Win32, you'll get this informative error message. When the Win32 loader memory maps a PE file, the first byte of the mapped file corresponds to the first byte of the MS-DOS stub. That's right. With every Win32-based program you start up, you get an MS-DOS-based program loaded for free!

 

http://msdn.microsoft.com/en-us/magazine/ms809762.aspx

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Seeing as how both the target and updating executable's will always be built by myself, is there some sort of easier method I can use via commandline or something, in which the target will give up the address offset and size of its own resource area?

Only wondering if I'm trying to go around the world to the shop up the road.

EDIT:

Ok I think I got my head around that question, which I'd already answered with the code in post #25.

If I use that code on self by calling GetModuleHandle(NULL): It'd be the quick way to where I am now in current code..

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I'm a little closer, very close infact, I can almost taste it.

PIMAGE_NT_HEADERS pNTHeader = MakePtr(PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew);
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
    printf("Not PE file\n");
    CloseHandle(hFileMapping);
    CloseHandle(hFile);
    return -5;
}

PIMAGE_SECTION_HEADER pImageSectionHeader = MakePtr(PIMAGE_SECTION_HEADER, pNTHeader, sizeof(IMAGE_NT_HEADERS));

std::cout << pImageSectionHeader->SizeOfRawData << std::endl;
std::cout << pImageSectionHeader->VirtualAddress << std::endl;

So is SizeOfRawData the actual file size in bytes?

and is VirtualAddress some sort of base address offset?

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

So I believe I have all the info I need to move to the next stage of project (well when I get my head round how to do the maths, which I'm also poor at)

(That's a delicate whimper for help bu the way)

for ( int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, pImageSectionHeader++ ){

    std::cout << "Name:\t" << pImageSectionHeader->Name << std::endl;
    std::cout << "Size:\t" << pImageSectionHeader->SizeOfRawData << std::endl;
    std::cout << "VAddr:\t" << pImageSectionHeader->VirtualAddress << std::endl << std::endl;
}

Have to say that this tut although assembly examples, helped me a lot to get this far.

EDIT:

The output is this by the way.

Name:   .text
Size:   17920
VAddr:  4096

Name:   .rdata
Size:   9216
VAddr:  24576

Name:   .data
Size:   3072
VAddr:  36864

Name:   .rsrc
Size:   1536
VAddr:  45056

Name:   .reloc
Size:   2048
VAddr:  49152

EDIT2:

See now, I'd have expected Size 17920 + VAddr 4096 of .text to equal VAddr 24576 of .rdata  :unsure:

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

So I believe I have all the info I need to move to the next stage of project (well when I get my head round how to do the maths, which I'm also poor at)

(That's a delicate whimper for help bu the way)

for ( int i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, pImageSectionHeader++ ){

    std::cout << "Name:\t" << pImageSectionHeader->Name << std::endl;
    std::cout << "Size:\t" << pImageSectionHeader->SizeOfRawData << std::endl;
    std::cout << "VAddr:\t" << pImageSectionHeader->VirtualAddress << std::endl << std::endl;
}

Have to say that this tut although assembly examples, helped me a lot to get this far.

EDIT:

The output is this by the way.

Name:   .text
Size:   17920
VAddr:  4096

Name:   .rdata
Size:   9216
VAddr:  24576

Name:   .data
Size:   3072
VAddr:  36864

Name:   .rsrc
Size:   1536
VAddr:  45056

Name:   .reloc
Size:   2048
VAddr:  49152

EDIT2:

See now, I'd have expected Size 17920 + VAddr 4096 of .text to equal VAddr 24576 of .rdata  :unsure:

You are forgetting alignment. When you add 4096 to 17920 and then align that result on specified value (IMAGE_OPTIONAL_HEADER.SectionAlignment) you should get 24576. Try it.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I'm having trouble discovering what exactly "align that result on specified value " entails.

The value seemingly being 4096 also.

It means that if the result is 400 it's actually 4096, if it's 5000 then it's 8192 (4096 * 2), etc. I'm sure English speaking programmer will use better terms. I can give you exact Croatian definition if it would help.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I think I get it now, has to be for example...

$addr = 4096
$size = 17920
$align = 4096
$pad = Mod($addr + $size, $align)
$nextaddr = ($addr + $size) + ($align - $pad)
MsgBox(0,0,$nextaddr)

Is that correct?

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I think I get it now, has to be for example...

$addr = 4096
$size = 17920
$align = 4096
$pad = Mod($addr + $size, $align)
$nextaddr = ($addr + $size) + ($align - $pad)
MsgBox(0,0,$nextaddr)

Is that correct?

Yes something like that. But it can also be any other value larger than that if it's mulitple of alignment value, the condition would still be satisfied - you see that, right?

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I think I'm beginning to.

I'll have another go in AU3

$addr = 4096
$size = 17920
$align = 4096
$pad = Mod($addr + $size, $align)

If $pad Then
    $nextaddr = ($addr + $size) + ($align - $pad)
Else
    $nextaddr = $addr + $size
EndIf

MsgBox(0, 0, $nextaddr)
Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Well there were a number of sources I was reading, I suppose when I said convoluted, I really meant "Way over my head"  :blink:

 

Well hmm, yeah it's all complicated. Some of MSDN does seem unnecessarily convoluted though. I've looked at MIDI functions over and over again and IMO it's very difficult to defend the choice of language used. If only they would use magic numbers instead, then I would have something to chew on. All I encounter is apparently meaningless and convoluted terminology. Ah but that's another story. :whistle:

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...