Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1

Processes


A process is a fundamental building block in Windows. A process is many
things, but it is predominantly an isolated memory address space. This
address space can be used for running a program, and address spaces are cre-
ated for every program in order to make sure that each program runs in its
own address space. Inside a process’s address space the system can load code
modules, but in order to actually run a program, a process must have at least
one thread running.

Threads


A thread is a primitive code execution unit. At any given moment, each proces-
sor in the system is running one thread, which effectively means that it’s just
running a piece of code; this can be either program or operating system code,
it doesn’t matter. The idea with threads is that instead of continuing to run a
single piece of code until it is completed, Windows can decide to interrupt a
running thread at any given moment and switch to another thread. This
process is at the very heart of Windows’ ability to achieve concurrency.
It might make it easier to understand what threads are if you consider how
they are implemented by the system. Internally, a thread is nothing but a data
structure that has a CONTEXTdata structure telling the system the state of the
processor when the thread last ran, combined with one or two memory blocks
that are used for stack space. When you think about it, a thread is like a little
virtual processor that has its own context and its own stack. The real physical
processor switches between multiple virtual processors and always starts exe-
cution from the thread’s current context information and using the thread’s
stack.
The reason a thread can have two stacks is that in Windows threads alternate
between running user-mode code and kernel-mode code. For instance, a typi-
cal application thread runs in user mode, but it can call into system APIs that
are implemented in kernel mode. In such cases the system API code runs in
kernel mode from within the calling thread! Because the thread can run in both
user mode and kernel mode it must have two stacks: one for when it’s running
in user mode and one for when it’s running in kernel mode. Separating the
stacks is a basic security and robustness requirement. If user-mode code had
access to kernel stacks the system would be vulnerable to a variety of mali-
cious attacks and its stability could be compromised by application bugs that
could overwrite parts of a kernel stack.
The components that manage threads in Windows are the schedulerand the
dispatcher, which are together responsible for deciding which thread gets to
run for how long, and for performing the actual context switchwhen its time to
change the currently running thread.

84 Chapter 3

Free download pdf