티스토리 뷰

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 0×10 bytes. When it is less than 0×10 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: 0×010B (HDR32_MAGIC)
MajorLinkerVersion: 0×06
MinorLinkerVersion: 0×00 -> 6.00
SizeOfCode: 0×00002000
SizeOfInitializedData: 0×00004000
SizeOfUninitializedData: 0×00000000
AddressOfEntryPoint: 0×000028DE
BaseOfCode: 0×00001000
BaseOfData: 0×00003000
ImageBase: 0×00400000
SectionAlignment: 0×00001000
FileAlignment: 0×00001000
MajorOperatingSystemVersion: 0×0004
MinorOperatingSystemVersion: 0×0000 -> 4.00
MajorImageVersion: 0×0000
MinorImageVersion: 0×0000 -> 0.00
MajorSubsystemVersion: 0×0004
MinorSubsystemVersion: 0×0000 -> 4.00
Win32VersionValue: 0×00000000
SizeOfImage: 0×00006AC8
SizeOfHeaders: 0×00001000
CheckSum: 0×00000000
Subsystem: 0×0002 (WINDOWS_GUI)
DllCharacteristics: 0×0000
SizeOfStackReserve: 0×00100000
SizeOfStackCommit: 0×00001000
SizeOfHeapReserve: 0×00100000
SizeOfHeapCommit: 0×00001000
LoaderFlags: 0×00000000
NumberOfRvaAndSizes: 0×00099999 <- 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: 0×010B (HDR32_MAGIC)
MajorLinkerVersion: 0×06
MinorLinkerVersion: 0×00 -> 6.00
SizeOfCode: 0×00002000
SizeOfInitializedData: 0×00004000
SizeOfUninitializedData: 0×00000000
AddressOfEntryPoint: 0×000028DE
BaseOfCode: 0×00001000
BaseOfData: 0×00003000
ImageBase: 0×00400000
SectionAlignment: 0×00001000
FileAlignment: 0×00001000
MajorOperatingSystemVersion: 0×0004
MinorOperatingSystemVersion: 0×0000 -> 4.00
MajorImageVersion: 0×0000
MinorImageVersion: 0×0000 -> 0.00
MajorSubsystemVersion: 0×0004
MinorSubsystemVersion: 0×0000 -> 4.00
Win32VersionValue: 0×00000000
SizeOfImage: 0×00006AC8
SizeOfHeaders: 0×00001000
CheckSum: 0×00000000
Subsystem: 0×0002 (WINDOWS_GUI)
DllCharacteristics: 0×0000
SizeOfStackReserve: 0×00100000
SizeOfStackCommit: 0×00001000
SizeOfHeapReserve: 0×00100000
SizeOfHeapCommit: 0×00001000
LoaderFlags: 0×00000000
NumberOfRvaAndSizes: 0×00000001 <- some value less than 0×10

Now the loader will see it as

DataDirectory (1) RVA Size
————- ———- ———-
ExportTable 0×00000000 0×00000000

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 0×00000000 0×00000000
ImportTable 0×00003908 0×00000078 (”.rdata”)
Resource 0×00006000 0×00000AC8 (”.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 0×90.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: 0×00001D33
VirtualAddress: 0×00001000
SizeOfRawData: 0×56546346 <- some very big value
PointerToRawData: 0×00001000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×60000020
(CODE, EXECUTE, READ)

Loader will map 0×1D33 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: 0×56546346 <- it wont work
VirtualAddress: 0×00001000
SizeOfRawData: 0×00001D33
PointerToRawData: 0×00001000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×60000020
(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: 0×00001D33
VirtualAddress: 0×00001000
SizeOfRawData: 0×00002000
PointerToRawData: 0×00001000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×60000020
(CODE, EXECUTE, READ)

2. item:
Name: .rdata
VirtualSize: 0×0000118E
VirtualAddress: 0×00003000
SizeOfRawData: 0×00002000
PointerToRawData: 0×00003050
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×40000040
(INITIALIZED_DATA, READ)

3. item:
Name: .data
VirtualSize: 0×0000017C
VirtualAddress: 0×00005000
SizeOfRawData: 0×00001000
PointerToRawData: 0×00005000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0xC0000040
(INITIALIZED_DATA, READ, WRITE)

4. item:
Name: .rsrc
VirtualSize: 0×00000AC8
VirtualAddress: 0×00006000
SizeOfRawData: 0×00767475 <- this will not work
PointerToRawData: 0×00006000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×40000040
(INITIALIZED_DATA, READ)

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

->Section Header Table
1. item:
Name: .text
VirtualSize: 0×00001D33
VirtualAddress: 0×00001000
SizeOfRawData: 0×82174982
PointerToRawData: 0×00001000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×60000020
(CODE, EXECUTE, READ)

2. item:
Name: .rdata
VirtualSize: 0×0000118E
VirtualAddress: 0×00003000
SizeOfRawData: 0×41251234
PointerToRawData: 0×00003000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×40000040
(INITIALIZED_DATA, READ)

3. item:
Name: .data
VirtualSize: 0×0000017C
VirtualAddress: 0×00005000
SizeOfRawData: 0×76457567
PointerToRawData: 0×00005000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0xC0000040
(INITIALIZED_DATA, READ, WRITE)

4. item:
Name: .rsrc
VirtualSize: 0×00000AC8
VirtualAddress: 0×00006000
SizeOfRawData: 0×00001000
PointerToRawData: 0×00006000
PointerToRelocations: 0×00000000
PointerToLinenumbers: 0×00000000
NumberOfRelocations: 0×0000
NumberOfLinenumbers: 0×0000
Characteristics: 0×40000040
(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
Opcode0×90

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

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

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

'보안 > 분석' 카테고리의 다른 글

HijackThis #1  (0) 2008.12.28
Vmware Snapshot Compare 관련  (0) 2008.12.20
Unpacking ASPack 2.12 [from korupt.wordpress.com]  (1) 2008.07.31
An in depth analysis of ASProtect 2.22 [ from CodeBreakers]  (0) 2008.07.31
CreateMutex Function  (2) 2008.07.01
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함