Archive for the bugs Category

#773: bug in IDA-Pro [fails to debug zero-based PE]

Posted in bugs on May 14, 2008 by souriz

IDA-Pro embedded debugger doesn’t support PE files with zero image base.

the debugger says (I quote):
“IDA Pro couldn’t automatically determine if the program should be rebased in the database because the database format is too old and doesn’t contain enough information. Create a new database if you want automated rebasing to work properly. Notice you can always manually rebase the program by using the Edit, Segments, Rebase program command”.

I have checked 4.7 (standard) and 5.2 (advanced) versions – they are both buggy.

after pressing F9 debugger loses the control, ignores breakpoints (!!!) allowing to the process running on its own, breaking through the debugger!!! really bad news for malware researchers!

to know your enemy – write a simple “hello, world” application and build it as follows:

# ida-bug-773.c
main()
{
ExitProcess (MessageBox (0, “after one bad thing another follows”, “sudah jatuh, ditimpa tangga”, 0));
}

# building ida-bug-773
cl.exe /c /Ox ida-bug-773.c
link.exe ida-bug-773.obj /FIXED:NO /BASE:0 USER32.LIB

ignore linker warning! (after all, it’s just a warning). the file has zero image base, but works fine, coz windows automatically rebases it to the appropriately place. IDA-Pro does rebases files by default, since she doesn’t reserve lowest part of address space like windows does.

to debug the file with IDA-Pro debugger we have to rebase it before debugging: /Edit/Segments/Rebase program/Target, where Target is 0x40000 or something like that. we can use ms editbin.exe tool (if IDA-Pro is unable to rebase the program, however, if the program checks PE-header, it definitely find out that the file was rebased).

Advertisements

# Syser causes BSOD

Posted in bugs on May 9, 2008 by souriz

a new bug in Syser was found. download this file, unpack it and run make-all-and-run.bat.
under XP SP2 with Syser we have BSOD:

# BugCheck 100000D1, {45b0, ff, 0, f580aa75}
# Probably caused by : Syser.sys ( Syser+aa75 )
# DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)

this is _very_ strange, since the program causes crash – is a user-mode application, or, to be exactly, there are two programs – one traces another to find out NT bug: OS kernel doesn’t zero TF bit on faults (see this post for more detail), leading to crash OllyDbg, but OllyDbg just refuses to debug, while Syser causes BSOD. not good :=( excellent way to defeat Syser, although :=)

note:
the bug was located
rebuild PeterFerrie.exe with following options and forgot about BSOD:

$link.exe PeterFerrie.obj /ENTRY:nezumi /SUBSYSTEM:CONSOLE KERNEL32.LIB

the previous ones were:

$link.exe PeterFerrie.obj /FIXED /ENTRY:nezumi /SUBSYSTEM:CONSOLE /ALIGN:16 /MERGE:.rdata=.text /STUB:stub KERNEL32.LIB

I’m too lazy to check every combination to find out which one triggers BSOD. it might be /ALIGN:16 or section merging or incorrect ms-dos stub (I just truncated file at the end of MZ-header without fixing size of the file – windows doesn’t check it).

I sent my report to Syser team, but got no answer. never mind. it’s probable nothing. however, the bug gives a great opportunity to malware-writers, so it has to be fixed.

# old CD 03 bug in windows

Posted in bugs on May 9, 2008 by souriz

coming soon!

# bug in Olly, Windows behavior and Peter Ferrie

Posted in bugs on May 9, 2008 by souriz

PeterFerrie strongly disagreed with me, pointed out, that this is not only the Olly bug.

https://www.openrce.org/forums/posts/775#2715:
The not a problem in OllyDbg, it’s a Windows behavior. Try it without any debuggers and you will see the same thing. I found the same while researching my new paper.

https://www.openrce.org/forums/posts/775#2720:
If you set the trap flag then cause an access exception, you’ll get a trap exception before the access exception. That’s the Windows behavior, even without a debugger. Interestingly, it doesn’t happen in a VM. OllyDbg is setting the trap flag before the exception occurs. That’s why you see the behavior. If something else set the flag, you’d still see the behavior.

ok, my bad, he won! I admit it.
to make long story short:
in general, TF-bit is zeroed automatically every time single step exception is generated, so to continue tracing you have to set it again. however, if CPU generates access violation exception, illegal instruction exception or any other fault like this, kernel doesn’t clean TF-bit and keeps it in registry context. after that, kernel cleans TF-bit and calls ntdll!KiUserExceptionDispatcher, KiUserExceptionDispatcher finds and calls SEH-handler(s), gets control back and calls ntdll!NtRaiseException, passing registry context (where TF bit is set!!) as an argument. NtRaiseException asks kernel for passing control to the current process. kernel begins to restore registry context, restoring TF-bit _before_ control is passed. as result – kernel generates single step exception and calls KiUserExceptionDispatcher again, keeping TF-bit unchanged (setting), so, CPU executes the first machine command of KiUserExceptionDispatcher and generates single step exception, passing it to kernel. wow! kernel catches single step exception, cleans TF-bit (wow!!! TF-bit finally is cleaned!) and calls KiUserExceptionDispatcher, passes exception record with context.Eip = (ntdll!KiUserExceptionDispatcher + 1). why plus one? due to single step exception is a trap, not a fault.

how KiUserExceptionDispatcher is supposed to handle this?! well, it just try to find SEH-handler(s), ready to accept this exception and passes control to them. since, expectations are reenterable, everything works fine (of course, if SEH handler is able to handle the unexpected exception of ntdll!KiUserExceptionDispatcher, the best strategy – just ignore it)

but Olly is unable to do this!!! try to trace the program we’re talking about with Olly, trace it until ntdll!KiUserExceptionDispatcher –} ntdll!NtRaiseException and… ops!!! Olly tells you that “debugged program was unable to process exception“.

I recalled that I discovered this windows bug years ago, when I was working on my debugger, but… I just cleaned up TF-bit in the EXCEPTION_DEBUG_EVENT handler and totally forgot about it. and besides, any other debugger does the same – take Soft-Ice for example! (btw, right now I’m porting soft-ice to Vista and Server 2008, making a special bit-hacking patch)

P.S. in few day I’m going to publish more detailed post.

# bug in Process Explorer (a gift for malware)

Posted in bugs on May 4, 2008 by souriz

years ago I found a bug in Process Explorer tool, written by Mark Russinovich. well, not a bug, just misfeature :) Process Explorer tries to determine the start address of a thread, but does this wrong and under certain conditions gives us an incorrect result. I sent a report to Mark, but had got no answer and the bug is still unfixed.

to demonstrate this bug (well, not a bug, just misfeature) I wrote a simple program http://nezumi.org.ru/souriz/va_thread.zip), creating two threads:
the first one – is a normal thread, created by CreateThread API call, the second one – is malware-like thread: program allocates memory on the heap, copies malicious code to the allocated block, and calls Create[Remote]Thread. to simplificate things va_thread.c uses CreateThread, creating a malware-like thread inside its own address space.
* * * va_thread.c doesn’t not inject code into any other process! * * *

thus, we have three threads:
1) main process-thread;
2) “fair” thread, created by CreateThread;
3) “malware-like” thread, created by Create[Remote]Thread on the heap;

Process Explorer correctly determines the start addresses of the two first threads, but stumbles over third, claims that the address is: KERNEL32.DLL+B700h, what is definitely wrong! actual start address should look like 003F0000h (the exact address depends on the heap
allocator behavior).

I don’t know how Process Explorer determines the start address of a thread, but I found my own simply and reliable way to do that. I discovered that the start address of any thread is stored at the bottom of the user stack in the second or third dword, followed by lpParameter. this trick works under Windows 2000 and Server 2003, I didn’t check it out under XP yet, but I hope, it’ll be the same (is there someone who wants to check it under XP? plz, tell me what
you’ll get).

I wrote quick-n-dirty utility proc_list.c correctly determines
the start addresses in the most cases and discovers malware, injecting shell-code into process by allocating memory via VirtualAllocEx, or loading malicious dll via creating remote thread and passing address of the LoadLibraryA/W with name of malicious dll in lpParameter.

* if malicious code is on the heap, the start address of the malware-thread belongs to MEM_PRIVATE block (instead of MEM_IMAGE like normal exe/dll does);

* if malicious code is injected via dll, the start address of the malware-thread matches the address of LoadLibraryA/W.

I checked this method on a quite big malware collection and got a good result.

$proc_list.exe > out.txt
* * * PROCESS INFO * * *
—————————————————–
szExeFile : va_thread.exe
cntUsage : 0h
th32ProcessID : 58Ch ; <- we need to know ProcessID
th32DefaultHeapID : 0h
th32ModuleID : 0h
cntThreads : 3h
th32ParentProcessID : 668h
pcPriClassBase : 8h
dwFlags : 0h
–thr————————————————
cntUsage : 0h
th32ThreadID : 6B4h
th32OwnerProcessID : 58Ch ; <- va_thread.exe
tpBasePri : 8h
tpDeltaPri : 0h
dwFlags : 0h
handle : 3D8h
ESP : 0012FF84h
EIP : 77F883A3h
start address : 00401010h ; <- main thread
point to args : 00000000h
type : MEM_IMAGE ; <- normal thread
[0012FFF0h: 00000000 00000000 00401010 00000000]

–thr————————————————
cntUsage : 0h
th32ThreadID : 668h
th32OwnerProcessID : 58Ch ; <- va_thread.exe
tpBasePri : 8h
tpDeltaPri : 0h
dwFlags : 0h
handle : 3D8h
ESP : 003EFF80h
EIP : 77F883A3h
start address : 00401000h ; <- “fair” thread
point to args : 0012FFC8h
type : MEM_IMAGE ; <- normal thread
[003EFFF0h: 00000000 00401000 0012FFC8 00000000]

–thr————————————————
cntUsage : 0h
th32ThreadID : 764h
th32OwnerProcessID : 58Ch ; <- va_thread.exe
tpBasePri : 8h
tpDeltaPri : 0h
dwFlags : 0h
handle : 3D8h
ESP : 0050FF80h
EIP : 77F883A3h
start address : 003F0000h ; <- heap block
point to args : 0012FFC8h
type : MEM_PRIVATE ; <- malware thread
[0050FFF0h: 00000000 003F0000 0012FFC8 00000000]

a new(?) bug in Olly [776]

Posted in bugs on April 23, 2008 by souriz

I’ve found a bug in Olly leading to crash SEH/VEH-based programs during tracing. (an example-pack could be found at: http://nezumi.org.ru/olly-bug-776.zip, it includes two SEH/VEH programs and requests XP or latter to run VEH, while SEH works everywhere).

Load an example into Olly and start tracing [F7] /* we can skip the first call by pressing [F8] (Step Over), since it has nothing interesting for us */

xor eax,eax/mov eax,[eax] generates an exceptions, catching by OS kernel. the kernel saves registry context (including TF-bit, set by Olly to “1”) and passes control to NTDLL.DLL!KiUserExceptionDispatcher function – the first user-land function executes after an exception. it calls SEH/VEH handler (if there is at lest one).

if the handler returns control to the code, where the exception was raised, registry context (including TF-bit) is restored by OS kernel. everything is fine, yes? hell, no!!!

Olly catches NTDLL.DLL!KiUserExceptionDispatcher and offers us to press Shift?F7/F8/F9. Olly allows to trace KiUserExceptionDispatcher, but totally forgets to clean TF-bit. as result – when control is passed the to original code (to the command follows mov eax,[eax] in our case, since handler adds 2 bytes /* size of mov eax,[eax] */ to EIP), TF-bit is set!!! so, a new exception occurs and SEH/VEH handler is called again and over again, coz, Olly passes this exception to the program, coz it forgets who “owns” this exception!!!

since, SEH/VEH handler doesn’t expect to handle trace exaction, we have an undefined behavior (a crash).

1

it’s definitely a bug!!! and how we can to fix it?!
well, it’s very simple. look at the prototype of KiUserExceptionDispatcher(EXCPT_REC *pExcptRec, CONTEXT *pContext). everything we need – is just to take pContext and clear TF-bit manually. pContext is the next DWORD on the stack and EFlags has C0h offset, while TF-bit is the first bit of the next word (1 << 8). just clean it and enjoy! press [F9] to Run the program or do whatever you want!

of course, we can create plug-in, doing it automatically, or set-up a conditional breakpoint on KiUserExceptionDispatcher.

I’ve checked the latest 2.00e version [April 19, 2008] and… the bug is still there, damn it!

I reported about this bug to the Olly creator and he admitted it, writing me back:

# Dear Kris,
# thank you for your bug report. I will try to remove it from v2.0 ASAP.
# Sincerely, Olly