The stager is a piece of shell code.
Shell code is machine code which is ready to be executed by a CPU.
It is tied to a specific CPU architecture,
which you can specify when generating the stager using the msfvenom tool.
Shell code is position independent,
meaning that it can be dropped anywhere in memory and it should be able to run.
It doesn't rely on the operating system to load its dependencies.
For example, if it needs to perform HTTP requests,
the shell code will resolve the required APIs by itself at runtime so
that it can call them to communicate over HTTP.
The stager is written in assembly and compiled using
the Metasm assessment Ruby compiler.
Shell code is very versatile.
It can be sent over the network to exploit memory corruption bugs in software,
or it can be used to backdoor executable files.
During the course, we will focus on the latter.
To generate a reverse the HTTP stager,
we can go ahead and run the following msfvenom command.
In this case,
we choose the payload type using the ‑p option and we configured the
LHOST and LPORT to specify the IP address and TCP port of the handler
we want our stager to connect back to.
We can then specify the format where we can choose hex for a
hexadecimal representation of the stager shell code.
When you run this command, some Ruby code is being called,
which generates a stager.
Let's take a look at the code.
In this case, since we generated a 64‑bit reverse HTTP stager,
the code being run is in the reverse_http_x64.rb file.
If we take a look at the generate method inside the file,
we notice that the parameters that were passed to msfvenom are
being passed into the generate_reverse_http method.
If we take a look at this method,
we can see some inline assembly code and two variable
placeholders which will also hold assembly code,
asm_block_api and asm_reverse_http.
The former consists of a function which will be used to locate all the
APIs which are required by the stager at runtime.
The latter consists of the actual stager code,
which will leverage various APIs and make use of the
asm_block_api function to locate them.
The asm_block_api uses a structure called the PEB,
also known as Process Environment Block,
which contains a linked list of all modules loaded in the current process.
This list can be used to locate a module's base address in memory,
which, in turn,
can be used to access its export table to locate
the address of a given function.
If our stager requires the LoadLibraryA function located in the kernel32 module,
the ROT13 hash of the module and function is calculated,
and the value is placed inside the assembly code.
The method which calculates this hash can be found in the block_api_rb file.
If we debug the Ruby code as we generate the stager,
we can indeed check the ROT13 hash,
which is pre‑calculated for the LoadLibraryA API.
We can load the stager in a disassembler such as Defuse, which is web based.
You can see that at runtime this ROT13 hash is
passed to the asm_block_api function.
Instead of using Defuse,
we could also regenerate the stager using msfvenom and the raw format to
send the shell code to a file which can then be disassembled by Metasm We
can then grep for the ROT13 hash to find it.
As explained,
the function first traverses the linked list to find the base address
of kernel32 then accesses kernel32's export table.
It then starts looping over the exported functions,
calculating their ROT13 hashes and comparing them with
the precomputed hash we just saw.
If a match is found, the function calls the API with the supplied parameters.
If we go back to the Ruby code,
we can take a look at which APIs are resolved and
called by the stager at runtime.
It first loads the WinINet library using the LoadLibraryA
function and then calls a series of APIs inside the WinINet
module after it has been loaded,
to make an HTTP request which will be sent to the handler.
It then allocates the memory using VirtualAlloc,
and finally reads the HTTP response into the allocated memory
buffer and jumps to it using a ret instruction.
All this assembly code is compiled by Metasm and formatted appropriately
to be sent to standard output or directly to a file.