Variables & Assignments

Description of variables and assignments

Registers Assignment

By using a simple lvalue register assignment, the user is able to change the value of registers.

syntax

@register = expression;

Example 1

@rax = 0x55;

Example 2

@r15 = poi(@rcx);

Example 3

if ( @rcx == 0x55) {
    @rcx = @rdx + @rax + 12;
}

Local Variables Assignment

In HyperDbg's script engine, all the variables are defined without Type, and all of them are considered unsigned 64-bit integers. You can save results of functions and boolean expressions or results of mathematical calculations alongside 64-bit addresses to the variables.

The variables can be used as an input to other functions or might be used in conditional statements or loops.

If you want to assign a symbol name (e.g., address of a Windows function or a Windows global variable) to a script engine variable, you should specify the module name along with a bang '!' character; otherwise, it's interpreted as a variable name. For example, x = ExAllocatePoolWithTag; is equal to assigning the a script engine variable named ExAllocatePoolWithTag to a variable named x. However, x = nt!ExAllocatePoolWithTag; means assigning the function address from the nt module to the x variable.

The following example shows the assigning 0 to a variable named my_variable.

You can also assign registers or pseudo-registers to the variables.

Also, you can assign the results of functions to the variables.

Or, you can decrement or increment variables by one.

Local variables won't be changed in the case of a core's context, which means you can save the variable and expect to reread it next time you access the variable from the same core. But of course, the local variables are not available in other cores.

Global Variables Assignment

Like local variables, all global variables are defined without type, and all of them are considered unsigned 64-bit integers.

The variables can be used as an input to other functions or might be used in conditional statements or loops.

You can also use global variables as volatile variables to the spinlocks or interlocked functions.

The difference between local variables and global variables is that the global variables start with a . DOT.

The following example shows the assigning 0 to a global variable named .my_variable.

You can also assign registers or pseudo-registers to the global variables.

Also, you can assign the results of functions to the global variables.

Or, you can decrement or increment variables by one.

Using global variables on multi-core systems

You should not write to a global variable simultaneously from different cores. It's clear that other cores might trigger the same event and use the global variable or modify that variable.

To solve this problem, you can use spinlock functions. If you want to perform mathematical calculations on different global variables, you should use interlocked functions instead of performing them using regular math operators.

As another example, assume that we want to count the number of times a function is called. For this purpose, we need a global variable to hold this number. You can safely use interlocked_increment for this purpose, and for other mathematical operations or atomic exchange operations, you can use other interlocked functions.

If you are running HyperDbg on a single-core machine, there is no need to use a spinlock or use interlocked functions for calculations; you can directly modify them without any problem.

Both global variables and local variables are initialized with NULL.

Compound Assignment

The following compound assignments are supported.

Operator
Description
Equivalent Expression
Meaning

+=

Addition assignment

a += ba = a + b

Adds the value of b to a and stores the result in a.

-=

Subtraction assignment

a -= ba = a - b

Subtracts the value of b from a and stores the result in a.

*=

Multiplication assignment

a *= ba = a * b

Multiplies a by b and stores the result in a.

/=

Division assignment

a /= ba = a / b

Divides a by b and stores the quotient in a.

%=

Modulus assignment

a %= ba = a % b

Stores the remainder of a divided by b in a.

<<=

Left shift assignment

a <<= ba = a << b

Shifts the bits of a left by b positions and stores the result in a.

>>=

Right shift assignment

a >>= ba = a >> b

Shifts the bits of a right by b positions and stores the result in a.

&=

Bitwise AND assignment

a &= ba = a & b

Performs a bitwise AND between a and b, storing the result in a.

^=

Bitwise XOR assignment

a ^= ba = a ^ b

Performs a bitwise XOR between a and b, storing the result in a.

|=

Bitwise OR assignment

a |= ba = a | b

Performs a bitwise OR between a and b, storing the result in a.

Here is an example for the compound assignment.

Multiple Assignment

Multiple assignments are described as follows.

For local variables:

Similarly, for global variables:

Arrays

HyperDbg also supports arrays within scripts.

Initializing Array

The following statements are used for initializing arrays.

Array Assignment

The following example shows how to assign constant values to an array.

You can also assign variables to an array.

Reading Array Elements

There are two ways you can read each array item: first, by using its index, or by dereferencing it directly from memory.

By using its index:

By directly reading it from memory:

Multidimensional Array

Multidimensional arrays are defined as follows.

or another example with more dimensions:

Modify Memory

Modifying memory is possible using 'eb, ed, eq' functions.

eb modifies a single byte.

ed modifies a dwrod.

eq modifies a qword value.

The following code edits memory (quad-word) at fffff8031d44fde0 and change it to 0x12345678deadbeef.

The following code changes a byte to 0x90 at the location that the @rcx register is pointing to, then adds 0x8 to it.

Last updated