Understanding the Assembly Flow
Before we modify any code, we must first understand how the original code operates.
To do that, we’ll dump the content of AmsiOpenSession with WinDbg.
Let’s unassemble all 0x1A instructions that make up AmsiOpenSession
To force an error, we could just modify the very first bytes to the binary values
that represent the last two instructions.
This way, every call to AmsiOpenSession would fail
even if the supplied arguments are valid.
Instead of completely overwriting instructions, we may also be able to make
more minor modifications that achieve the same goal.
The two first instructions in AmsiOpenSession
are a TEST followed by a conditional jump.
This specific conditional jump is called jump if equal
and depends on a CPU flag, called the zero flag
The conditional jump is controlled by the TEST instruction according to the argument
and is executed if the zero flag is equal to 1.
If we modify the TEST instruction to an XOR instruction,
we can force the Zero flag to be set to 1 and trick the CPU into taking the
conditional jump that leads to the invalid argument return value.
XOR takes two registers as an argument but if we supply the same register
as both the first and second argument,
the operation will zero out the content of the register.
This operation essentially controls the zero flag.
If the result ends up being zero, the zero flag is set.
In summary, we will overwrite TEST RDX, RDX with an XOR RAX,RAX instruction,
forcing the execution flow to the error branch, which will disable AMSI.
There is one additional detail we need to take into account.
When the original TEST RDX,RDX instruction is compiled, it is converted into a
binary value that takes up three bytes so the replacement, XOR RAX,RAX
has to take up the same amount of memory.
Fortunately, when XOR RAX,RAX is compiled into a binary value,
it matches the number of bytes we require.
At this point, we realize that we can disable AMSI by overwriting only
three bytes of memory inside the AmsiOpenSession API.
In the next section, we’ll implement this in PowerShell.