Let's now take a look at some of the modifications which we can make to
the payloads and extensions to make them more evasive.
You may recall from the Meterpreter Deep Dive module that the
Meterpreter payloads and extensions are loaded reflectively.
You may also recall that the reflective loader uses ROT13 hashes to locate APIs,
which it needs to perform reflective DLL injection.
These ROT13 hashes are ideal for developing signatures since they are
hard‑coded values which will always be in memory.
We can modify these hashes,
just as we did when modifying the stager's shellcode
and leverage a ROT16 hash instead.
I have already pre‑calculated the ROT16 hashes and replaced them in the code.
I have also changed the value 13 to 16, since we want to perform a ROT16 hash.
This will ensure that there won't be any traces of
these well‑known values in memory, which may be detected by scans.
Let's now take a look at one of the extensions, which is used by Meterpreter.
The STT API extension provides some of the core
functionality when interacting with the payload.
It is automatically loaded when the Meterpreter session is initializing.
We can attempt to modify some of the code inside this
extension in an attempt to make it more evasive.
I randomly chose to modify the steal_token functionality.
I added a very simple xor encryptor function.
Its job will be to decrypt strings at runtime to avoid
hard‑coding blacklisted strings, which may be frowned upon by antivirus.
I chose the value 9 as the encryption key.
The section of code I chose to modify makes use of
the ImpersonateLoggedOnUser API.
Currently, this API will be added to the extensions import address table.
Therefore, if an antivirus was to scan memory,
it would find the ImpersonateLoggedOnUser string
inside the import address table.
We can get around this using a technique we already covered,
which makes use of the GetProcAddress API and function pointers.
To call GetProcAddress, however, we need a handle to the module,
which involves calling the GetModuleHandle API,
which in turn requires the name of the module.
This is obviously an issue, since we want to avoid hard‑coded strings.
We also encounter the same issue when calling the GetProcAddress API,
which requires the API name.
At this point,
we can make use of the encryption function we saw
previously so that instead of hard‑coding the advapi32.dll
and ImpersonateLoggedOnUser strings, we can hard code their encrypted values,
which can be decrypted at runtime and re‑encrypted if required,
to ensure in‑memory scans will not detect them.
These values can be pre‑calculated using a simple program
or script and embedded inside the code.
We can go ahead and compile the payload and extensions.
If we now compare two copies of the STD API extension,
you will notice that the original file contains 278 imports,
whereas our modified version only contains 277.
You will also notice that the blacklisted ImpersonateLoggedOnUser API is
not listed in the modified version of the extension.
If we take a look at the strings located inside both files,
you will also notice that the ImpersonateLoggedOnUser string is not
found in the modified version of the extension either.
We can now copy our recompiled payload and extensions to our
Kali machine and replace the old files.
We can then start up a Metasploit handler and run our stager,
which we wrote previously.
As you can see, the Meterpreter session is still fully functional,
despite our changes to the source code.
We can now elevate our privileges using the getsystem command,
and list processes running on the machine.
I randomly chose a process from which I want to steal the user's security token.
I then ran the steal_token command, which will make use of our modified code.
As you can see, the code behaved as expected, despite the changes we made.
Manually refactoring the Meterpreter code base is
going to be very time consuming.
There are ways this can be automated using custom tools and scripts,
which make use of regular expressions, for example.
Alternatively, a more elegant approach,
which makes use of libraries designed to pass source code,
can also be chosen.
A series of excellent blog posts which demonstrate this
process in detail, can be found on SCRT's blog.
It covers string and import address table obfuscation
techniques using an automated approach,
which can help save time and avoid error‑prone manual code refactoring.
If you do decide to manually refactor parts of the Meterpreter code base,
a good starting point is the cyberspacekittens fork of the
Meterpeter payload GitHub repository.
You can check out the changes,
which were made to the project in an attempt to make it more evasive.
This should give you plenty of ideas regarding the artifacts,
which you should attempt to remove to improve your tradecraft,
and stay clear of antivirus and EDR solutions.