Flag: Tornado! Hurricane!

 Forums >>  Debuggers  >>  # a new(?) bug in Olly

Topic created on: April 22, 2008 20:11 CDT by nezumi .

I've found a bug in Olly leads 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 handled
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).

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!

  PeterFerrie     April 23, 2008 09:55.33 CDT
The not a problem in OllyDbg, it's a Windows behaviour.
Try it without any debuggers and you will see the same thing.  I found the same while researching my new paper.

  nezumi     April 23, 2008 12:14.37 CDT
you got it all wrong, man. no debugger - no crash, and even under debugger there is no crash if we don't trace mov eax, [eax]. Windows behavior? as a matter of fact, yes! Windows acts itself like this and there is nothing to do. we have to live with it. about 10 years ago I played with Windows Debugging API, to understand it I wrote kind of a debugger (very simple and experimental). it worked fine, but had the same problem. the solution was - never pass INT 01h to the program unless we're absolute sure this exception belongs to it.

btw, soft-ice, ms visual studio, ms windbg don't have this bug. so, I don't think that we have to blame Windows, while something is wrong with Olly.

  nezumi     April 24, 2008 03:12.50 CDT
Olly-creator admitted the bug and said:

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

  PeterFerrie     April 24, 2008 11:44.41 CDT
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 behaviour, 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 behaviour.  If something else set the flag, you'd still see the behaviour.

  nezumi     April 25, 2008 00:04.01 CDT
let me disagree with you. under any debugger (ms visual studio embedded, ms windbg, olly) I catch "access violation exception" first ("live" CPU P-III, W2K SP4, going to test this on XP and S2K3, however, I'm sure, they're the same).
this is _CPU_ behavior! single step exception generates _after_ executing mov eax,[eax], while access violation exception generates _during_ executing mov eax,[eax] and follows by single step exception. there is no way single step exception generates first! of course, single step exception generates after mov eax,eax, but Olly catches it and doesn't pass it back to the program.
write your own debugger (well, not a debugger, actually, just create a debug process and catch exceptions, you'll see how windows and CPU works)

btw, if you claim that single step exception generates first this means that "mov eax,[eax]" is executed somehow, but how? we all know, that single step exception generates _after_ an instruction is executed, and you really think there is a way to execute "mov eax,[eax]"?! it's impossible. access violation exception generates and everything we can do is - skip "mov eax,[eax]" (adding 2 bytes to EIP) or change eax and re-execute "mov eax,[eax]". anyway this has nothing to do with Olly bug.

  nezumi     May 8, 2008 22:05.26 CDT
PeterFerrie convicted me that this is not only the Olly bug. 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 the registry context. after that, kernel cleans TF-bit and calls ntdll!KiUserExceptionDispatcher,  ntdll!KiUserExceptionDispatcher finds and calls SEH-handler(s) and calls ntdll!NtRaiseException, passing registry context (where TF-bit is set!!) as an argument. ntdll!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 ntdll!KiUserExceptionDispatcher again, keeping TF-bit unchanged (setting up), so, CPU executes the first machine command of ntdll!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 ntdll!KiUserExceptionDispatcher, passes it exception record, where context.Eip = (ntdll!KiUserExceptionDispatcher + 1). why plus one? due to single step exception is a trap, not a fault.

and how ntdll!KiUserExceptionDispatcher is supposed to handle this?! well, it just tries 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 is 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... that time I just cleaned TF-bit in 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 describe this subj in details on my blog souriz's internals

Note: Registration is required to post to the forums.

There are 31,312 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