Jump to content
Tuts 4 You

Bug When Fixing Dump


waliedassar

Recommended Posts

Posted (edited)

It seems that Scylla has a bug when trying to fix a dump with an unusual SizeOfOptionalHeader value.

For example (with Scylla 0.6):

If the PE has the "SizeOfOptionalHeader" field set to 0x148 and the "NumberOfRvaAndSizes" field set to 0x1D, Scylla sets the "NumberOfRvaAndSizes" to 0x10 but leave the "SizeOfOptionalHeader" field as it is and this is why the fixed dumped is rejected by PE loader.

Scylla 0.7 beta:

If the PE has the "SizeOfOptionalHeader" field set to 0x148 and the "NumberOfRvaAndSizes" field set to 0x1D, Scylla moves the section table just after the 16th data directory without modifying the "SizeOfOptionalHeader" field.

It should do the reverse, set the "SizeOfOptionalHeader" field to 0xE0 and leave "NumberOfRvaAndSizes" untouched.

Or it should just follow this for 32-bit PE's:

SizeOfOptionalHeader = (NumberOfRvaAndSizes*0x8)+0x60

Edited by waliedassar
Posted

NumberOfRvaAndSizes is hardcoded to 0x10.

Havent checked the rest yet.

Posted (edited)

yes, that is correct.

SizeOfOptionalHeader is just the size of the optional header, which includes an array of 16 DataDirectories, consisting of 1 RVA + int32 for size (==> 2*4=8 bytes on x86 and x64).

Above calculation is correct for x86 PE32 files:

SizeOfOptionalHeader = (NumberOfRvaAndSizes*0x8)+0x60

=>

SizeOfOptionalHeader = 0x10*0x08+0x60 = 0xE0.

Hence, SizeOfOptionalHeader should always be 0xE0 for x86 PE32 files.

in the windows header files:

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16

and in the IMAGE_OPTIONAL_HEADER definition:

 IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

(used both for the x64 and the x86 definitions)

THe x64 IMAGE_OPTIONAL_HEADE has some fields expanded to 64 bits, so its overall size is 0xF0.

edit:

going back to the original problem:

If the PE has the "SizeOfOptionalHeader" field set to 0x148 and the "NumberOfRvaAndSizes" field set to 0x1D, Scylla moves the section table just after the 16th data directory without modifying the "SizeOfOptionalHeader" field.

It should do the reverse, set the "SizeOfOptionalHeader" field to 0xE0 and leave "NumberOfRvaAndSizes" untouched.

Imo, i shouldnt touch the section table, but change the two fields to 0xE0 and 0x10, respectively.

Edited by deepzero
Posted (edited)

I think this is the only valid solution:

NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;

SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);

I like constants more than some weird calculations.

Thanks for your help.

Edited by Aguila
Posted (edited)

I think this is the only valid solution:

NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;

SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);

I like constants more than some weird calculations.

Thanks for your help.

No, sir. Let me save you some time.

The "SizeOfOptionalHeader" field is used by the PE loader to locate the section table. So, changing the "NumberOfRvaAndSizes" field to 0x10 and leaving the "SizeOfOptionalHeader" field unchanged causes the PE loader to get a different section table ;).

On the other side, the "NumberOfRvaAndSizes" field is used by the PE loader e.g. the ntdll "RtlImageDirectoryEntryToData" function when checking/parsing a specific data directory.

If the requested data directory index < NumberOfRvaAndSizes, then it is okay and continue checking/parsing.

else, return an error and don't parse that data directory.

Imagine a PE with the "NumberOfRvaAndSizes" field set to 0xA and data directories number 0xA, 0xB, 0xC, 0xD, 0xE, and 0xF are filled with garbage values.

1) If you only set the "NumberOfRvaAndSizes" field to 0x10, then PE loader gets a wrong section table.

2) If you set the "SizeOfOptionalHeader" and "NumberOfRvaAndSizes" fields to 0xE0 and 0x10, then any attempt by the PE loader to get IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 0xA will result in the garbage values being read and the PE will be rejected.

The solution should be:

1) Leaving "NumberOfRvaAndSizes" field unchanged and setting the "SizeOfOptionalHeader" field to 0xE0.

2) Setting the "NumberOfRvaAndSizes" field to 0x10, the "SizeOfOptionalHeader" field to 0xE0, and filling the space in between with zeros.

I remember that OllyDbg v1.10 has some issue with the "SizeOfOptionalHeader" and "NumberOfRvaAndSizes" fields. This is why i used this weird calculation to bypass that issue.

Edited by waliedassar
Posted

I disagree. :)

field unchanged causes the PE loader to get a different section table ;).

no. the NumberOfRvaAndSizes isnt actually used here, you can set it to -1, too.

Only SizeOfOptHeader is used to get the section header table.

will result in the garbage values being read and the PE will be rejected.

precisely so, it`s an invalid PE file.

As i said above, the optional header contains a field of hardcoded 16 DataDirectories. If you dont use one of these directories, it should be set to zero.

Else it is seen as "registered".

1) Leaving "NumberOfRvaAndSizes" field unchanged and setting the "SizeOfOptionalHeader" field to 0xE0.

No.

I was wrong when i said the SizeOfOptHeader is hardcoded. It`s not, although it should be in a "perfect" PE file.

SizeOfOPtionalHeader is NOT sizeof(SizeOfOPtionalHeader)!

Rather, it is the offset of the section header table relative to the PE header.

As such, it has to include potentially additional space that someone may have inserted additionally to the actual OptionalHeader.

(althouhg that someone really shouldnt have done that....)

2) Setting the "NumberOfRvaAndSizes" field to 0x10, the "SizeOfOptionalHeader" field to 0xE0, and filling the space in between with zeros.

no.

in that case, the space should be physically removed from the file to get the offsets right.

The non-used DataDirecotires should be zero already.

Lastly, although the NumberOfRvaAndSizes is hardocded to 16, the pe loader of WinXpSp3 uses the actual value from the pe file to check whether a directory access is in-range or not.

So one could use >=0x10...although the definitions guarantee that there should be 16 directories.

here`s the actual data from the winapis:

check on OptHeaderSizeOf:

7C910300 81FA 00000010 CMP EDX,10000000

Check on NumberOfRvaAndSizes of pe file:

7C91039B 3B48 74 CMP ECX,DWORD PTR DS:[EAX+74]

a data entry is valid if non-zero:

7C9103A4 8B54C8 78 MOV EDX,DWORD PTR DS:[EAX+ECX*8+78]

7C9103A8 85D2 TEST EDX,EDX

7C9103AA 0F84 EC030000 JE 7C91079C

Posted

I disagree. :)

no. the NumberOfRvaAndSizes isnt actually used here, you can set it to -1, too.

Only SizeOfOptHeader is used to get the section header table.

You misunderstood it.

Rephrasing it again.

If you go for placing the section table after the sixteenth data directory, setting the "NumberOfRvaAndSizes" field to 0x10, and leaving the "SizeOfOptionalHeader" field unchanged, then you get a different section table. (This happens with Scylla v0.6).

Posted (edited)

no.

in that case, the space should be physically removed from the file to get the offsets right.

The non-used DataDirecotires should be zero already.

With the "Space in between", i mean space starting from the first unused data directory to just before the first section header.

Also, i forgot the "OR"

The solution should be:

1) Leaving "NumberOfRvaAndSizes" field unchanged and setting the "SizeOfOptionalHeader" field to 0xE0.

OR

2) Setting the "NumberOfRvaAndSizes" field to 0x10, the "SizeOfOptionalHeader" field to 0xE0, and filling the space in between with zeros.

Edited by waliedassar
Posted (edited)

If you go for placing the section table after the sixteenth data directory, setting the "NumberOfRvaAndSizes" field to 0x10, and leaving the "SizeOfOptionalHeader" field unchanged, then you get a different section table. (This happens with Scylla v0.6).

true. you cant move the section table around freely.

But the NumberOfRvaAndSIzes has nothing to do with that (s.a.), just the SizeOfOptionalHeader.

In your first post, both v0.6 and v0.7 should produce invalid dumps, due to an invalid start of the section table.

You are right, if you delete/overwrite data that was placed right after the optional header (ie "after the 16th DD") then you can use sizeof(ImageOPtionalHeader).

But this might have unwanted side effects. (in theory, you could e.g. place a DD there).

As for 1), i would argue that NumberOfRvaAndSIzes is fixed to 16 for Pe32 and PE32+, any other value indicates wired custom modifications or a new derivative of the PE file format.

(although windows internally uses the actual value from the header for some reason, s.a.)

As for 2), i agree (although unused directories should be zeroed, i suppose it s good for rebuilding purposes).

BUT, you have to take into account potential space inserted additionally to the ImageOptionalHeader.

Scylla does no do that right now.

d. :)

Edited by deepzero

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
×
×
  • Create New...