Expressions
Evaluation
of expressions is done in two steps. First, OllyDbg compiles
expression into the intermediate binary form. On the second step, it
calculates its value. The evaluation is usually orders of
magnitude faster than compilation.
Expressions
may be roughly divided in two classes: those used to make a decision
(for example, conditional breakpoints) and those used to display data.
In the first case you need only one value. In the second case, user may
want to see multiple values and expressions at once.
Basic
elements Expressions
may include:
Byte
registers AL,
BL, CL, DL, AH, BH, CH, DH
Word
registers AX,
BX, CX, DX, SP, BP, SI, DI
Doubleword
registers EAX,
EBX, ECX, EDX, ESP, EBP, ESI, EDI
Simple
labels, like GetWindowTextA
or userdefinedlabel1
Known
constants, like WM_PAINT
or ERROR_FILE_NOT_FOUND
Labels
with prepended module name, like user32.GetWindowTextA
Immediate
integer numbers, like ABCDEF01, 123, 0x123
(all hexadecimal) or 123.
(decimal)
Immediate
floating point numbers, like 123.456e-33
Immediate
strings, like "String"
Parameters
%A and %B
Thread
identifier %THR
(or alternative form %THREAD)
Ordinal
number of the current thread %ORD(or
alternative form %ORDINAL)
Contents
of memory (requires square brackets [
], see detailed description below)
Elements
are processed in the listed order. Therefore AH is always interpreted
as a 8-bit register and not as a hexadecimal constant 0Ah. For the same
reason, label EBP can't be used in expressions (but mymodule.EBP would
be OK). If there is a label named ABCD, ABCD will be
interpreted
as address of this label and not as the hexadecimal number 0x0000ABCD.
When
OS creates new thread, this thread gets more or less random thread
identifier.
One can use expressions like %THREAD==0x00000172, but they will be
meaningless in the next debugging session. To overcome this
problem, at least partially, OllyDbg assigns each new thread its unique
ordinal number. Main thread gets number 1, next thread created by the
application has ordinal 2 etc. Temporary threads created by OS are not
numbered (their ordinal is 0). If you want that breakpoint pauses
application only in the main thread, you may set condition to %ORD==1.
Signed
vs. unsigned data
By default, all integer variables and constants are unsigned. To
interprete item as signed, prepend it with unary sign ('+' or '-') or with modifier
SIGNED. To
convert signed item to unsigned, use UNSIGNED. Examples:
Unsigned
Signed
0xFFFFFFFF
+0xFFFFFFFF (-1.)
EAX
+EAX
ECX
SIGNED ECX
[DWORD 4F5024]
[SIGNED DWORD 4F5024]
Floating-point items are always signed.
Contents
of memory
To
access memory, take address into the square brackets and optionally
specify type and size of the item. OllyDbg supports following modifiers:
Modifier
How the contents of memory is
interpreted
BYTE
Unsigned 8-bit integer
CHAR
Signed 8-bit integer
WORD
Unsigned 16-bit integer
SHORT
Signed 16-bit integer
DWORD
Unsigned 32-bit integer (default)
INT,
LONG
Signed 32-bit integer
FLOAT
32-bit floating-point number
DOUBLE
64-bit floating-point number
LONG
DOUBLE
80-bit floating-point number
ASCII
Address inside the brackets will be
interpreted as a pointer to ASCII string, but numerical value
of expression remains unchanged
UNICODE
Address inside the brackets will be
interpreted as a pointer to UNICODE string, but numerical value
of expression remains unchanged
Syntax
rules are relatively loose. The following five expressions have the
same meaning:
Multiple
expressions
In the EMOD_MULTI
evaluation mode, expression string may contain several subexpressions
in the form text1=expr1,text2=expr2... Number of subexpressions is
limited to NEXPR.
Optional explanations (text1, text2) are pseudoidentifiers that comment
subexpressions. If explanation is missing, OllyDbg creates one
automatically. Example:
Outermost memory bracket may contain repeat count, like
[DWORD*10 EAX]. Modifier is obligatory, standalone repeat count *10 is
treated as a syntax error. Repeat count tells OllyDbg to display the
specified number of consecutive memory locations. Note that, according
to OllyDbg syntax rules, constant 10 is hexadecimal. If you want
decimal count, append a point: [DWORD*16.
EAX].
Example:
Operations with strings are very limited. You may:
add or subtract integer to the string (C rules apply): [UNICODE EAX]+5
compare
string with immediate string, ignoring case: [ASCII ESI]=="ABC".
Comparison is limited to the length of the immediate string, so
expression is true if ESI points to "ABCDE", "aBc" or "abc---" and
false if ESI points to "AB" or "AABC"
compare pointer (doubleword) with immediate string, ignoring case, first assuming ASCII pointer and then UNICODE: ESI=="ABC"
API
functions:
int
Cexpression(wchar_t
*expression,uchar *cexpr,int nexpr,int *explen,wchar_t *err,ulong mode);
int Exprcount(uchar
*cexpr);
int Eexpression(t_result
*result,wchar_t *expl,uchar *cexpr,int index,uchar *data,ulong
base,ulong size,ulong threadid,ulong a,ulong b,ulong mode);
int Expression(t_result
*result,wchar_t *expression,uchar *data,ulong base,ulong size,ulong
threadid,ulong a,ulong b,ulong mode);
int Fastexpression(t_result
*result,ulong addr,int type,ulong threadid);