Detailed Overview and Internals of PE File

VN:F [1.9.8_1114]

A win32 portable executable(PE) file consists of: DOS Header, PE Header, Section Table, Sections. Analyzing a PE file gives us a lot of information like the address in memory where the file will be located (ImageBase), address of entry point, imported and exported functions, packed or unpacked etc. Thus this static analysis can indicate whether it’s a malware or not etc.

 

PE File Architecture

DOS MZ header is 64 bytes in size. Its structure, IMAGE_DOS_HEADER, is defined in winnt.h. The important fields present in this are:
e_magic-> contains the value 4Dh, 5Ah (or letters “MZ” for Mark Zbikowsky who designed the MS-DOS);
e_lfanew-> contains the offset of the PE header.


 

The PE header structure IMAGE_NT_HEADERS contains 3 fields: Signature, FileHeader and OptionalHeader.
Signature is a DWORD(4 bytes) containing the value 50h, 45h, 00h, 00h (“PE” followed by two terminating zeroes).
FileHeader (IMAGE_FILE_HEADER) is the next 20 bytes of the PE file and contains info about the physical layout & properties of the file e.g. number of sections.
OptionalHeader (IMAGE_OPTIONAL_HEADERS) is always present and forms the next 224 bytes. It contains info about the logical layout inside the PE file with fields like AddressOfEntryPoint, ImageBase, FileAlignment, SectionAlignment etc. The last 128 bytes contains the Data Directory which is an array of 16 IMAGE_DATA_DIRECTORY structures.

The Section Table contains information about each section present in the pefile. Some of the sections are:
Code section: .text contains the executable instructions
Data Section: .bss –>uninitialized variables; .rdata->read only variables; .data->initialized variables
Export data: .edata->names and addresses of exported functions as well as Export Directory
Import data: .idata-> names and variables of imported functions as well as Import Descriptor and IAT.

 

Swiss Army knife tools

Some of the important and useful tools you may need to explore more details are: PEid, PEview, PE Explorer, PE browse, dependency walker, Resource hacker, Lord PE and Import Reconstructor.

(PE Viewer to view internal details in organized format)

 

Though lots of GUI tools are available for studying a pe-file, you can program your own custom tool in python using the “pefile” module. Let’s study the usage of this module.

To open an executable using pefile:

>>> pe=pefile.PE(‘hello.exe’)  

>>> pe

<pefile.PE instance at 0x0000000002B06248>

 

We can search for individual fields like:

>>> pe.OPTIONAL_HEADER.AddressOfEntryPoint  

4096

>>> pe.OPTIONAL_HEADER.ImageBase

4194304

>>> pe.FILE_HEADER.NumberOfSections

3

 

Let’s check each section in detail:

>>> for section in pe.sections:  

print (section.Name, hex(section.VirtualAddress), hex(section.Misc_VirtualSize), section.SizeOfRawData )

(‘.text\x00\x00\x00′, ’0×1000′, ’0×26′, 512)
(‘.rdata\x00\x00′, ’0×2000′, ’0×92′, 512)
(‘.data\x00\x00\x00′, ’0×3000′, ’0xd’, 512)

 

To dump all the fields of the file, just a single simple command:

>>> print pe.dump_info()
 

———-DOS_HEADER———-

[IMAGE_DOS_HEADER]
0×0        0×0   e_magic:                       0x5A4D
0×2        0×2   e_cblp:                        0×90
0×4        0×4   e_cp:                          0×3
0×6        0×6   e_crlc:                        0×0
0×8        0×8   e_cparhdr:                     0×4
0xA        0xA   e_minalloc:                    0×0
0xC        0xC   e_maxalloc:                    0xFFFF
0xE        0xE   e_ss:                          0×0
0×10       0×10  e_sp:                          0xB8
0×12       0×12  e_csum:                        0×0
0×14       0×14  e_ip:                          0×0
0×16       0×16  e_cs:                          0×0
0×18       0×18  e_lfarlc:                      0×40
0x1A       0x1A  e_ovno:                        0×0
0x1C       0x1C  e_res:
0×24       0×24  e_oemid:                       0×0
0×26       0×26  e_oeminfo:                     0×0
0×28       0×28  e_res2:
0x3C       0x3C  e_lfanew:                      0xB0

———-NT_HEADERS———-

[IMAGE_NT_HEADERS]
0xB0       0×0   Signature:                     0×4550

———-FILE_HEADER———-

[IMAGE_FILE_HEADER]
0xB4       0×0   Machine:                       0x14C
0xB6       0×2   NumberOfSections:              0×3
0xB8       0×4   TimeDateStamp:                 0x52123CCD [Mon Aug 19 15:42:05 2013 UTC]
0xBC       0×8   PointerToSymbolTable:          0×0
0xC0       0xC   NumberOfSymbols:               0×0
0xC4       0×10  SizeOfOptionalHeader:          0xE0
0xC6       0×12  Characteristics:               0x10F

Flags: IMAGE_FILE_LOCAL_SYMS_STRIPPED, IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LINE_NUMS_STRIPPED, IMAGE_FILE_RELOCS_STRIPPED

 

———-OPTIONAL_HEADER———-

[IMAGE_OPTIONAL_HEADER]
0xC8       0×0   Magic:                         0x10B
0xCA       0×2   MajorLinkerVersion:            0×5
0xCB       0×3   MinorLinkerVersion:            0xC
0xCC       0×4   SizeOfCode:                    0×200
0xD0       0×8   SizeOfInitializedData:         0×400
0xD4       0xC   SizeOfUninitializedData:       0×0
0xD8       0×10  AddressOfEntryPoint:           0xFFE
0xDC       0×14  BaseOfCode:                    0×1000
0xE0       0×18  BaseOfData:                    0×2000
0xE4       0x1C  ImageBase:                     0×400000
0xE8       0×20  SectionAlignment:              0×1000
0xEC       0×24  FileAlignment:                 0×200
0xF0       0×28  MajorOperatingSystemVersion:   0×4
0xF2       0x2A  MinorOperatingSystemVersion:   0×0
0xF4       0x2C  MajorImageVersion:             0×0
0xF6       0x2E  MinorImageVersion:             0×0
0xF8       0×30  MajorSubsystemVersion:         0×4
0xFA       0×32  MinorSubsystemVersion:         0×0
0xFC       0×34  Reserved1:                     0×0
0×100      0×38  SizeOfImage:                   0×4000
0×104      0x3C  SizeOfHeaders:                 0×400
0×108      0×40  CheckSum:                      0×0
0x10C      0×44  Subsystem:                     0×2
0x10E      0×46  DllCharacteristics:            0×0
0×110      0×48  SizeOfStackReserve:            0×100000
0×114      0x4C  SizeOfStackCommit:             0×1000
0×118      0×50  SizeOfHeapReserve:             0×100000
0x11C      0×54  SizeOfHeapCommit:              0×1000
0×120      0×58  LoaderFlags:                   0×0
0×124      0x5C  NumberOfRvaAndSizes:           0×10

DllCharacteristics:

———-PE Sections———-

[IMAGE_SECTION_HEADER]
0x1A8      0×0   Name:                          .text
0x1B0      0×8   Misc:                          0×26
0x1B0      0×8   Misc_PhysicalAddress:          0×26
0x1B0      0×8   Misc_VirtualSize:              0×26
0x1B4       0xC   VirtualAddress:                0×1000
0x1B8      0×10  SizeOfRawData:                 0×200
0x1BC      0×14  PointerToRawData:              0×400
0x1C0      0×18  PointerToRelocations:          0×0
0x1C4      0x1C  PointerToLinenumbers:          0×0
0x1C8      0×20  NumberOfRelocations:           0×0
0x1CA      0×22  NumberOfLinenumbers:           0×0
0x1CC      0×24  Characteristics:               0×60000020

Flags: IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ

Entropy: 0.378734 (Min=0.0, Max=8.0)
MD5     hash: 4c606281effe29223bc83ca9145b4f76
SHA-1   hash: bb75af7ac66e4d653896f43a9dff5bad7c14b792
SHA-256 hash: fa0adde4c12513dde5497209d960d3f29c1e47bab9d29025641425ec67c1e286
SHA-512 hash: 8a43e9314e29c38f884f7668ca8c440f37d488d0ef8672db313d643e8e44db871042f7110e72f47fe289c7b2a8831b8b92f093515edb2eae4b5ada7692b118a9

[IMAGE_SECTION_HEADER]
0x1D0      0×0   Name:                          .rdata
0x1D8      0×8   Misc:                          0×92
0x1D8      0×8   Misc_PhysicalAddress:          0×92
0x1D8      0×8   Misc_VirtualSize:              0×92
0x1DC      0xC   VirtualAddress:                0×2000
0x1E0      0×10  SizeOfRawData:                 0×200
0x1E4      0×14  PointerToRawData:              0×600
0x1E8      0×18  PointerToRelocations:          0×0
0x1EC      0x1C  PointerToLinenumbers:          0×0
0x1F0      0×20  NumberOfRelocations:           0×0
0x1F2      0×22  NumberOfLinenumbers:           0×0
0x1F4      0×24  Characteristics:               0×40000040

Flags: IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ
Entropy: 1.144718 (Min=0.0, Max=8.0)
MD5     hash: 768cb8b25733abbd2e7ac650764e7f54
SHA-1   hash: 52710da9fc596d89ac7f0dcb6d038b7ec85f39ec
SHA-256 hash: 6a94c94b9d89b59d3d7e3c3c1829ef55e7bf4dd17ddedbe9ec41a1cdbc9f1728
SHA-512 hash: 5991c9514b027fc5122ec34d3a91e2aa60412953baca52fc537aff2f432c516ea736abb7d302760c6583cacfa8ad667814216aabcb09d8a278ded872efe18933

[IMAGE_SECTION_HEADER]
0x1F8      0×0   Name:                          .data
0×200      0×8   Misc:                          0xD
0×200      0×8   Misc_PhysicalAddress:          0xD
0×200      0×8   Misc_VirtualSize:              0xD
0×204      0xC   VirtualAddress:                0×3000
0×208      0×10  SizeOfRawData:                 0×200
0x20C      0×14  PointerToRawData:              0×800
0×210      0×18  PointerToRelocations:          0×0
0×214      0x1C  PointerToLinenumbers:          0×0
0×218      0×20  NumberOfRelocations:           0×0
0x21A      0×22  NumberOfLinenumbers:           0×0
0x21C      0×24  Characteristics:               0xC0000040

Flags: IMAGE_SCN_MEM_WRITE, IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ

Entropy: 0.231158 (Min=0.0, Max=8.0)
MD5     hash: e48ff2dac59702844e32e3b3275d376e
SHA-1   hash: 39b2d4a38baad338a99e271015b9aa7e5b5c5963
SHA-256 hash: 41f9998ac78561a82e66c9a34ae742e36a0bc4b4b58b44e46743406dfc25fa72
SHA-512 hash: 5b21dc86b36c27180322ebb1b8f98a0d24c9ba34baec013a9aaccd1d349afad678327ed5be2550ed560aa64a09fe606f49a68f4608751647f0a638019a81a756

 

———-Directories———-

[IMAGE_DIRECTORY_ENTRY_EXPORT]
0×128      0×0   VirtualAddress:                0×0
0x12C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_IMPORT]
0×130      0×0   VirtualAddress:                0×2010
0×134      0×4   Size:                          0x3C

[IMAGE_DIRECTORY_ENTRY_RESOURCE]
0×138      0×0   VirtualAddress:                0×0
0x13C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_EXCEPTION]
0×140      0×0   VirtualAddress:                0×0
0×144      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_SECURITY]
0×148      0×0   VirtualAddress:                0×0
0x14C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_BASERELOC]
0×150      0×0   VirtualAddress:                0×0
0×154      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_DEBUG]
0×158      0×0   VirtualAddress:                0×0
0x15C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_COPYRIGHT]
0×160      0×0   VirtualAddress:                0×0
0×164      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_GLOBALPTR]
0×168      0×0   VirtualAddress:                0×0
0x16C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_TLS]
0×170      0×0   VirtualAddress:                0×0
0×174      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG]
0×178      0×0   VirtualAddress:                0×0
0x17C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT]
0×180      0×0   VirtualAddress:                0×0
0×184      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_IAT]
0×188      0×0   VirtualAddress:                0×2000
0x18C      0×4   Size:                          0×10

[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]
0×190      0×0   VirtualAddress:                0×0
0×194      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR]
0×198      0×0   VirtualAddress:                0×0
0x19C      0×4   Size:                          0×0

[IMAGE_DIRECTORY_ENTRY_RESERVED]
0x1A0      0×0   VirtualAddress:                0×0
0x1A4      0×4   Size:                          0×0

 

———-Imported symbols———-

[IMAGE_IMPORT_DESCRIPTOR]
0×610      0×0   OriginalFirstThunk:            0x204C
0×610      0×0   Characteristics:               0x204C
0×614      0×4   TimeDateStamp:                 0×0        [Thu Jan 01 00:00:00 1970 UTC]
0×618      0×8   ForwarderChain:                0×0
0x61C      0xC   Name:                          0x206A
0×620      0×10  FirstThunk:                    0×2000

kernel32.dll.ExitProcess Hint[155]

 

[IMAGE_IMPORT_DESCRIPTOR]
0×624      0×0   OriginalFirstThunk:            0×2054
0×624      0×0   Characteristics:               0×2054
0×628      0×4   TimeDateStamp:                 0×0        [Thu Jan 01 00:00:00 1970 UTC]
0x62C      0×8   ForwarderChain:                0×0
0×630      0xC   Name:                          0×2086
0×634      0×10  FirstThunk:                    0×2008

user32.dll.MessageBoxA Hint[433]

 

 

Sometimes while manually unpacking a packed file, we need to change the Address of Entry Point to OEP.

>>> pe.OPTIONAL_HEADER.AddressOfEntryPoint = 5000 

>>> pe.write(filename=” hello1.exe”)

 

Packed PE files

A file is packed mainly for 3 purposes:
• To hide the behaviour of the malware from AV
• To reduce the size of the exe
• To prevent crackers from cracking the serial key of the software.

 

PEiD is the best tool available to find whether the executable is packed or not. It can detect signatures of almost all packers available.

(A deep scan in PEiD shows that UPX packer was used to pack explorer.exe)

 

Though packing an executable makes it difficult to perform static analysis of a malware, dynamic analysis has no effects because the file ultimately has to be unpacked before executing. Hence, it can only be used to fool a novice user!

 

Above diagram shows comparison of packed and unpacked “putty.exe” files through PE Browse. Packing a file with UPX will compress the various sections present, because these consume the maximum size. Compressed sections are renamed as UPX0, UPX1 and so on. We also see that many imported functions from the various DLLs are missing.

 

The execution of a packed exe starts with the new Address of Entry point. Initially, the register status is saved using PUSHAD instruction. Then unpacking of the packed sections is done followed by resolving the import table of the original exe. Restore the original register status using POPAD instruction and finally jump to the OEP.

 

Once we understand how a packed exe works, it is easy to unpack it manually. Following steps can be followed while unpacking using OllyDbg as mentioned in one of the trainings by SecurityXploded:

  1. Start tracing until you encounter a PUSHAD instruction(generally its the 1st or 2nd instruction).
  2. Put a hardware breakpoint at address stored by ESP in the immediate next instruction.
  3. Press F9 to continue execution. Execution stops at the breakpoint address.
  4. Continue tracing until you encounter a JMP instruction which will jump to OEP.
  5. At OEP, dump the whole program using Ollydump plugin
  6. Fix Address of Entry point of the new executable and resolve the imports using Import Reconstructor (ImpRec).

 

References:

1] Bin Portable Executable File Format-A Reverse Engineer View

2] Manual Unpacking of UPX using OllyDbg

3] pefile module in python

 

Related Posts Plugin for WordPress, Blogger...

No Comments Yet

Leave a Reply

Just Launched – MalwareNet

Follow us on Facebook


Join Mailing List

Get direct access to our expert trainers or mingle with like minded security folks in our mailing list