An alternative to using encoders or encryptors to hide our stager on
disk is to figure out which signatures are being used by antivirus and
attempt to modify the stager's shellcode.
While this technique is not very generic,
since not all antivirus solutions will use the same signatures,
it does have the added benefit of obfuscating the stager in
memory once it has been de‑obfuscated,
and well protected from certain types of in‑memory scans,
it is also more complex and time consuming than simply
passing in a ‑e flag to MSFvenom,
since it will require a very good understanding of
the assembly programming language.
Let's now take a look at how we can modify our stager in an
attempt to break signature‑based detections.
To do so, we can open the reverse_http_x64.rb file.
I have already opened two copies of the file.
On the left‑hand side is my modified version,
and on the right, we have the original file.
As explained in the Meterpreter Deep Dive module,
this file contains the Ruby code which generates the stager.
At this point,
there are a couple of options we can choose from to modify the
code without altering its functionality.
One technique is to add bogus instructions inside
the stager at different locations.
A good way of identifying where we can do this is to look for
xor instructions involving a single register.
When a register is xor'd with itself, the instruction will null out the register.
We can take advantage of this and perform random operations with
the register just after the xor instruction,
as long as we remember to null out the register once we
have finished adding the bogus code.
Another technique which we can leverage is to compute the
parameters which get passed to the APIs at runtime to avoid
hard‑coded artifacts in our stager.
Here is an example where instead of hard‑coding the
WinINet string in the stager, I subtracted the value,
ffff, from the hexadecimal values, which make up the WinINet ASCII string,
and hard‑coded this value instead.
At runtime, the stager will add the value,
ffff, to the obfuscated WinINet string.
This technique is obviously not as generic as using an encoder,
but it does have the added benefit of protecting the stager
from certain types of in‑memory scans.
Finally, we can attempt to modify the pre‑computed ROT13 hashes,
which are used to locate APIs.
This can be done in the block_api.rb file.
I chose to use the value 16 instead of 13.
We also need to modify this value in the asm_block_api function,
which we discussed in the Meterpreter Deep Dive module.
This can be done in the block_api.x64.graphml file by
changing some of the bytes corresponding to the ror r9d
0x0D instruction with the value 10,
which is the hexadecimal equivalent of 16 in decimal.
At this point, if we generate a new stager,
it will no longer have the well‑known ROT13 hash values,
which are commonly used by antivirus to detect Meterpreter stages.
We can confirm this by generating a raw stager,
which we can disassemble using metasm,
as we did in the Meterpreter Deep Dive module.
If we now grep to the LoadLibraryA ROT13 hash,
you will notice that it is no longer found.