Flag: Tornado! Hurricane!

 Forums >>  IDA Pro  >>  # new PE loader bug and new crack-me

Topic created on: December 1, 2008 19:31 CST by nezumi .

Hi all!
I found a bug in PE-loader allows to hide code/data inside EXE/DLL/SYS files, so IDA-Pro shows nothing. ok, this is not a bug, this is a documented feature, but PE-specification does not explain it well, so most of disassembler-writers missed the point.

to demonstrate this I created a simple proof-of-concept. plz, check it out.

try to reverse/debug this stuff. it bypasses IDA-Pro, HIEW, OllyDbg, Soft-Ice, Syser, DUMPBIN, etc. proc. dumpers don't work too.

I tested my crack-me under W2K, S2K3, XP, Vista and it works fine.
(if you have Vista under your hands, plz, run it and tell me if it works or not)

P.S. explanations will follow...

  nulldevice     December 2, 2008 01:07.51 CST
SizeOfRawdata is 1 for  data & text sections. Doing some guesswork, loader uses defaults to load such executable where as disasms/debuggers will not. Changing SizeOfRawData for above sections fixes the executable. At least for IDA. The TLSCallBack is pretty clear in IDA after this fixup but it does not  work for some other tiny exes where I tried to modify the SizeOfRawData to 1.

  nezumi     December 2, 2008 07:33.06 CST
ulldevice
> SizeOfRawdata is 1 for  data & text sections.
> Doing some guesswork, loader uses defaults
> to load such executable where as disasms/debuggers will not.
not exactly. the point is:
OS loads ALIGN_UP(SizeOfRawdata, FileAlignment) bytes, where IDA-Pro, HIEW, DUMPBIN - only SizeOfRawdata, thus if ALIGN_UP(SizeOfRawdata, FileAlignment) > SizeOfRawdata - IDA-Pro misses "ALIGN_UP(SizeOfRawdata, FileAlignment) - SizeOfRawdata" bytes, so it's possible to hide code/data in any section.

see another example.  this program calls two message boxes with two different strings, but IDA-Pro shows only one! malware might use it to hide malicious code, so always use IDA-Pro 5.3 and manual load.

> Changing SizeOfRawData for above sections fixes the executable.
yes, it does.

> The TLSCallBack is pretty clear in IDA
there is a couple anti-debugger tricks:
1) TLSCallback checks if *EntryPoint == CCh (INT 03) and executes infinitive loop to abuse OllyDbg and some other debuggers. however, we can pause the debugger (F12), set _hardware_ breakpoint at TLS callback and restart the process (CTRL-F2) - enjoy!

2) I use MOV EAX, EAX/MOV EAX, [EAX] instead of RETN and it works great. no custom SEH handlers are installed, but Windows suppresses exceptions raised inside TLS callbacks;

3) since TLS Callback is called more than once and I don't want to see the same message box  over and over, I use IsDebuggerPresent PEB field as a counter;

> it does not work for some other tiny exes
> where I tried to modify the SizeOfRawData to 1.
it should work for any exe/dll/sys regardless of its size, if you set SizeOfRawData to 1 - FileAlignment bytes will be loaded.

  PeterFerrie     December 2, 2008 11:59.44 CST
The SizeOfRawData technique is known and in use already by some packers.  Also, if you use Atli Gudmindsson's pe_sections.idc, then all data will be shown.
nulldevice is correct that the technique does not work for small files - if you use SectionAlignment < 4kb, then it will fail.

  nezumi     December 2, 2008 13:18.05 CST
PeterFerrie:
yeah, it's a known trick. I'm developing an interactive unpacker and testing a lot of different packers/protectors. the unpacker has an independent engine and interfaces to IDA-Pro and OllyDbg.

the problem was - a few malware samples fail to unpack with IDA-Pro, coz IDA-Pro loads only SizeOfRawData bytes, while OllyDbg uses System Loader and loads them all.

Manual Loading solves this problem and IDA-Pro 5.3 works well even without custom scripts.

I'm not the first who has found this, I just want to point out: dealing with malware always use manual load or check section size to be sure it has no hidden code/data. hope this advice will be useful. um, maybe not. ok, never mind.

  zarulshahrin     December 2, 2008 21:35.32 CST
just something to share:

http://opcode0x90.wordpress.com/2007/04/22/windows-loader-does-it-differently/

  nezumi     December 3, 2008 07:42.43 CST
Zarul, thanks for sharing!

# Windows loader does it differently
> Loader will map 0x1D33 bytes of section data
> into memory and ignores the SizeOfRawData.
not exactly, but close. according to MS PE specification:

# SizeOfRawData
...Because the SizeOfRawData field is rounded
but the VirtualSize field is not, it is possible for
SizeOfRawData to be greater than VirtualSize


System Loader works like this:
if (SizeOfRawData > VirtualSize)
       LOAD(SizeOfRawData);
else
       LOAD(VirtualSize);


of course, the real life is more complicated and like PeterFerrie mentioned above, it's possible to create a file with SectionAlignment < 4kb.

if SectionAlignment < 4kb,  File Alignment must be the same as Section Alignment and can take any value equal to a power of two (for example, 20h).

the virtual and physical addresses of all sections must match, meaning that the memory image must correspond to disk image. there are, however, exceptions to any rule, and the virtual size of sections can be smaller than their physical size. this difference cannot be greater than Section Alignment - 1 bytes though

btw,
I just checked the example described in the link above.

* IDA 4.7 - crashes, IDA 5.2+ works well;
* OllyDbg 1.10 displays the warning, but works well (no crash);

P.S. the crack-me has been updated, Vista incompatibly is fixed now (Vista doesn't allow us to call USER32!MessageBox from TLS-callback, MS warned us not to do this, but it worked before)

  zarulshahrin     December 3, 2008 16:26.18 CST
The link above was really meant to show that this stuff has already been around for quite some times now... :)

  detlef   June 18, 2009 05:58.51 CDT
hi,
I've got another question concerning PE loading.

The file comes with section alignment as well as file alignment of 0x1000.
Hence, I think, that the PointerToRawData and the VirtualAddress of each section has to be aligned to this value (0x1000).

Unfortunately, I found counter samples.

They are loaded by the PE loader and the PointerToRawData is rounded down to fit to the next alignment.

In a sample having the first section unaligned the Olly puts the sections together in one section.

I also have a sample with an unaligned 3rd section. In this case the data from this PointerToRawData is loaded to the VirutalAddress. But in this case the PointerToRawData has not been aligned before.

Does someone of you know under which circumstances the sections are allowed to be unaligned iff the Sectionalignment is not below 4KB?

thank you for your help.

  neoxfx     June 18, 2009 07:19.41 CDT
windows loader uses mask = ~(SectAlign > 0x200 ? 0x1ff : SectAlign-1) with section->PointertoRawData when loading.

it is not necessary to be aligned with value 0x1000, so in your case alignment mask is 0x1ff and not 0x1000.

  neoxfx     June 18, 2009 07:21.45 CDT
> In a sample having the first section unaligned the Olly puts the sections together in one section.
>
> I also have a sample with an unaligned 3rd section. In this case the data from this PointerToRawData is loaded to the VirutalAddress. But in this case the PointerToRawData has not been aligned before.
>


I dont think i follow your question, can you explain it? or share the samples?

  detlef   June 18, 2009 08:35.58 CDT
> neoxfx: windows loader uses mask = ~(SectAlign > 0x200 ? 0x1ff : SectAlign-1) with section->PointertoRawData when loading.
>
> it is not necessary to be aligned with value 0x1000, so in your case alignment mask is 0x1ff and not 0x1000.

I just send you an email with two samples.

The masking you mentioned works fine for some samples. But not for all.
Is the file alignment thus never taken into consideration?
I expected it to be verified. Or is it just used for the purpose of size alignment?


I'll give you more details: (sample1)

file- and section-alignment = 0x1000
Section:

v. offset : 0x9a000
v. size:    0x20000
f. offset:  0x26600
f. size:    0x00df2

Apparently, the masking you proposed handles the section loading.
If I change f. offset being 0x26600 to be 0x26601 the file is not loadable any more.
Why?


(sample2)
file-alignment = 0x200
section-alignment = 0x1000

v. offset : 0x1000
v. size:    0x9000
f. offset:  0x0401
f. size:    0x4e00

In this case, the loading works fine. I can even modify the file offset and the mask you mentioned (~0x1ff) will handle the loading. But in contrast to the first sample above, the sections are loadable


In which cases is the mask used to detect an invalid PE file and when is it used to just load the data?

Do you know why these different behaviors occur?
I mean, I do not only want to load a given file, but also distinguish between valid and invalid ones.

  neoxfx     June 18, 2009 10:48.50 CDT
load error occurred because you only did partial modification.

you modified last section raw-offset from 0x26600 to 0x26601, which is ok, as long as you've modified the physical size in accordance. i.e., from 0xdf2 to 0xdf1. that way file will not be smaller than the size that PE header mentions.

hope this helps

  detlef   June 18, 2009 10:51.36 CDT
> neoxfx: > hope this helps

you're right!

thank you

Note: Registration is required to post to the forums.

There are 31,313 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit