Skip to content

Windows loader does it differently

April 22, 2007

You think what documented on Microsoft website is exactly how the Windows loader works? Think again. In this blog I will crash your disassembler/debugger by modifying some fields in the PE header.

IMAGE_FILE_HEADER.NumberOfRvaAndSizes

In pecoff_v8.doc it says NumberOfRvaAndSizes contains the number of data directories we have. But Windows loader just ignores it when you have a value larger than 0x10 bytes. When it is less than 0x10 bytes Windows loader will just skip over some of the data directories. You can use this trick to strip some bytes out of your executable file.

Let say we have something like this.

->Optional Header
Magic: 0x010B (HDR32_MAGIC)
MajorLinkerVersion: 0x06
MinorLinkerVersion: 0x00 -> 6.00
SizeOfCode: 0x00002000
SizeOfInitializedData: 0x00004000
SizeOfUninitializedData: 0x00000000
AddressOfEntryPoint: 0x000028DE
BaseOfCode: 0x00001000
BaseOfData: 0x00003000
ImageBase: 0x00400000
SectionAlignment: 0x00001000
FileAlignment: 0x00001000
MajorOperatingSystemVersion: 0x0004
MinorOperatingSystemVersion: 0x0000 -> 4.00
MajorImageVersion: 0x0000
MinorImageVersion: 0x0000 -> 0.00
MajorSubsystemVersion: 0x0004
MinorSubsystemVersion: 0x0000 -> 4.00
Win32VersionValue: 0x00000000
SizeOfImage: 0x00006AC8
SizeOfHeaders: 0x00001000
CheckSum: 0x00000000
Subsystem: 0x0002 (WINDOWS_GUI)
DllCharacteristics: 0x0000
SizeOfStackReserve: 0x00100000
SizeOfStackCommit: 0x00001000
SizeOfHeapReserve: 0x00100000
SizeOfHeapCommit: 0x00001000
LoaderFlags: 0x00000000
NumberOfRvaAndSizes: 0x00099999 <- some random value

The executable will run happily even though we dont have 99999 data directories. Now what happens when we have something like this.

->Optional Header
Magic: 0x010B (HDR32_MAGIC)
MajorLinkerVersion: 0x06
MinorLinkerVersion: 0x00 -> 6.00
SizeOfCode: 0x00002000
SizeOfInitializedData: 0x00004000
SizeOfUninitializedData: 0x00000000
AddressOfEntryPoint: 0x000028DE
BaseOfCode: 0x00001000
BaseOfData: 0x00003000
ImageBase: 0x00400000
SectionAlignment: 0x00001000
FileAlignment: 0x00001000
MajorOperatingSystemVersion: 0x0004
MinorOperatingSystemVersion: 0x0000 -> 4.00
MajorImageVersion: 0x0000
MinorImageVersion: 0x0000 -> 0.00
MajorSubsystemVersion: 0x0004
MinorSubsystemVersion: 0x0000 -> 4.00
Win32VersionValue: 0x00000000
SizeOfImage: 0x00006AC8
SizeOfHeaders: 0x00001000
CheckSum: 0x00000000
Subsystem: 0x0002 (WINDOWS_GUI)
DllCharacteristics: 0x0000
SizeOfStackReserve: 0x00100000
SizeOfStackCommit: 0x00001000
SizeOfHeapReserve: 0x00100000
SizeOfHeapCommit: 0x00001000
LoaderFlags: 0x00000000
NumberOfRvaAndSizes: 0x00000001 <- some value less than 0x10

Now the loader will see it as

DataDirectory (1) RVA Size
------------- ---------- ----------
ExportTable 0x00000000 0x00000000

So it cant find the import directory and resource directory and the executable wont load properly. We change NumberOfRvaAndSizes to 3. Now the loader will see them as

DataDirectory (3) RVA Size
------------- ---------- ----------
ExportTable 0x00000000 0x00000000
ImportTable 0x00003908 0x00000078 (".rdata")
Resource 0x00006000 0x00000AC8 (".rsrc")

The executable will fire up.

ollydbg and CFF Explorer cannot handle this value correctly. When you change it to something else, ollydbg will complain the executable as “Bad or unknown format” and unable to break in entry point. CFF Explorer cannot display the data directory correctly.

IMAGE_SECTION_HEADER.SizeOfRawData

A trick I found in sotm33 0x90.exe.

The loader have very interesting way to handle VirtualSize and SizeOfRawData. It will choose whichever is smaller and map the section data into memory according to that size.

Here’s an example.

->Section Header Table
1. item:
Name: .text
VirtualSize: 0x00001D33
VirtualAddress: 0x00001000
SizeOfRawData: 0x56546346 <- some very big value
PointerToRawData: 0x00001000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x60000020
(CODE, EXECUTE, READ)

Loader will map 0x1D33 bytes of section data into memory and ignores the SizeOfRawData. But when you have something like this

->Section Header Table
1. item:
Name: .text
VirtualSize: 0x56546346 <- it wont work
VirtualAddress: 0x00001000
SizeOfRawData: 0x00001D33
PointerToRawData: 0x00001000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x60000020
(CODE, EXECUTE, READ)

Loader will refuse to load the executable. I have no idea why it wont work. If you know why, do reply. 🙂 There’s another catch. When you have something like

->Section Header Table
1. item:
Name: .text
VirtualSize: 0x00001D33
VirtualAddress: 0x00001000
SizeOfRawData: 0x00002000
PointerToRawData: 0x00001000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x60000020
(CODE, EXECUTE, READ)

2. item:
Name: .rdata
VirtualSize: 0x0000118E
VirtualAddress: 0x00003000
SizeOfRawData: 0x00002000
PointerToRawData: 0x00003050
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x40000040
(INITIALIZED_DATA, READ)

3. item:
Name: .data
VirtualSize: 0x0000017C
VirtualAddress: 0x00005000
SizeOfRawData: 0x00001000
PointerToRawData: 0x00005000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0xC0000040
(INITIALIZED_DATA, READ, WRITE)

4. item:
Name: .rsrc
VirtualSize: 0x00000AC8
VirtualAddress: 0x00006000
SizeOfRawData: 0x00767475 <- this will not work
PointerToRawData: 0x00006000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x40000040
(INITIALIZED_DATA, READ)

Windows loader will refuse to load it. But when you have something like

->Section Header Table
1. item:
Name: .text
VirtualSize: 0x00001D33
VirtualAddress: 0x00001000
SizeOfRawData: 0x82174982
PointerToRawData: 0x00001000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x60000020
(CODE, EXECUTE, READ)

2. item:
Name: .rdata
VirtualSize: 0x0000118E
VirtualAddress: 0x00003000
SizeOfRawData: 0x41251234
PointerToRawData: 0x00003000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x40000040
(INITIALIZED_DATA, READ)

3. item:
Name: .data
VirtualSize: 0x0000017C
VirtualAddress: 0x00005000
SizeOfRawData: 0x76457567
PointerToRawData: 0x00005000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0xC0000040
(INITIALIZED_DATA, READ, WRITE)

4. item:
Name: .rsrc
VirtualSize: 0x00000AC8
VirtualAddress: 0x00006000
SizeOfRawData: 0x00001000
PointerToRawData: 0x00006000
PointerToRelocations: 0x00000000
PointerToLinenumbers: 0x00000000
NumberOfRelocations: 0x0000
NumberOfLinenumbers: 0x0000
Characteristics: 0x40000040
(INITIALIZED_DATA, READ)

It works. Strange it may sound, but this crashes most debugger and disassemblers, including ollydbg and IDA. ollydbg will complain “it contains too much data” and cannot display the loaded module list. IDA too will not disassemble the file correctly, in some cases it will crash.

Thats all for now. I may cover some other PE trick in my coming blog, so stay tuned. 😉

Cheers
Opcode0x90

——————————————————————————————-

Scan of the Month 33
http://www.honeynet.org/scans/scan33/

Proof of concept
http://w14.easy-share.com/3759611.html

Advertisements
2 Comments
  1. Well done!
    Nice tricks, thanks

  2. waliedassar permalink

    Windows loader does not ignore the “NumberOfRvaAndSizes” field if it is greater than 0x10. This field is only used when checking validity of indexes used to access the DATA_DIRECTORY array.
    See the ntdll “RtlImageDirectoryEntryToData” function in disassembly.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: