
        what it is.

    a tracer is normally used to single step some stream of instructions and
    because of this it is able to intervene at any point and act accordingly.
    in our case, this tracer engine runs under win9x, and traces win32 threads
    as long as they execute in their natural environment (ring-3 protected
    mode).

    the primary goal was to create an engine that determines the original entry
    point of PE executables that have been wrapped by some compression and/or
    protection layer. the end result is a bit more powerful since it can serve
    many other purposes by simple changes to the engine.


        how it works.

    the engine is implemented as a VxD and is currently part of icedump,
    although technically it could be a standalone product. user interface
    and other issues made this integration a natural choice though.

    the basic idea behind the whole scheme is that each traced thread is
    attached a state machine which is tracking various state changes of the
    thread and makes sure that the thread perceives an execution environment
    as if it was not traced at all (hence making the tracer undetectable).

    this includes emulating all instructions that read/write EFLAGS.T, DR6.BS
    and some other stuff specific to win9x/win32: SIDT, GetTickCount, RDTSC,
    GetLocalTime, timeGetTime and NT win32 selectors (latter is optional, will
    make selectors appear in the GDT when loaded into a general purpose
    register). this list is of course far from being complete (not everything
    is implemented of it in fact in the current version), but proved to be
    enough for tracing most known PE protections and compressors.

    once a thread is traced, the engine will get the first chance to respond
    to various exceptions (most importantly the debug one of course) that occur
    in the given thread. the responses depend on the state of the thread, e.g.
    after a PUSHFD the engine clears EFLAGS.T on the thread's stack if the
    thread was not tracing itself (and hence expects a cleared state). also
    depending on the state of the thread and the nature of the exception the
    engine may call down the original exception handler chain to let the win32
    specific Structured Exception handling mechanism carry out its work.

    other smaller details have to do with various ways a thread's context can
    be read/written and which the tracer must take care of (same emulation job
    as with the x86 instructions). this is accomplished by a few hooks into
    VWIN32.


        what it can do.

    in its current implementation the engine is able to trace win32 threads
    (i.e. no V86 mode support, mainly due to some lazyness in emulating 16 bit
    instructions ;-) as long as they run in ring-3. on normal ring transitions
    the engine will remain in control of EFLAGS.T, on illegal ring transitions
    it is at the mercy of the illegal handler (supporting this would pretty
    much amount to writing a full instruction decoder and an emulator, neither
    of which was my goal. also, some schemes simply do more damage than what's
    worth the effort to support them, think of C-Dilla/Safedisc blindly
    OVERWRITING the System VM's divide error handler with its own... talk about
    competent programmers).

    the engine will trace into Structured Exception handlers as well and follow
    execution flow just as if the thread itself was executing them (which is
    what win9x itself does as some reverse engineering of kernel32/vwin32
    reveals it).

    since the engine was designed as a thread based state machine (i.e. state
    info maintained on a per thread basis, object oriented design? ;-), it is
    able to trace any number of threads simultaneously. right now it can
    automatically start tracing a newly created thread if there is at least one
    traced thread already in the same process or in the parent process (there
    already are some schemes that use multiple threads as an anti-debugging
    measure).

    the engine stops tracing a thread when it dies (only a message is logged
    in winice) or when EIP reaches a user defined range. in this latter case
    winice will break in and the user can do whatever he wants (e.g. try to
    dump the process to a PE file).


        how to use it.

    the engine is controlled from icedump/winice via 2 commands: TRACE and
    TRACEX. as usual, the latter handles the current thread and exits winice,
    otherwise they do (almost) the same job. these commands are described in
    the main doc in full detail.

    the behaviour of the engine also depends on a few flags which determine how
    much trace info to log and what should happen when a new thread is detected
    in a process (note that these flags by no way reflect what can be done,
    they're only what i found useful during my experiments).

    for logging there are 3 choices: all executed instructions, those that can
    change the flow of execution (branches, calls, etc) and finally the last
    but one traced instruction before winice breaks in (the idea being that one
    could go back and see where the original entry point was reached from).

    the log information contains CS:EIP, SS:ESP and R0TCB, but again, this can
    be easily enhanced/fine-tuned by changing the engine code.

    new-born threads can be handled in 3 basic ways (after they become eligible
    for tracing at all, see previous section on what the conditions are in the
    current version): let them run without further tracing, trace them
    automatically without bothering the user (in this case the EIP range will
    be simply inherited) or have winice break in right at the beginning of the
    new thread and give the user the choice to start tracing it via TRACEX.
