Sie sind auf Seite 1von 70

!

!
!
!
!
! Clash of the Titans: ZeuS v SpyEye
!
! GIAC (GREM) Gold Certification
!
!
! !"#$%&'()*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6(
! !78,+%&'(937&%(:"31%(
!
!
!
! !553;#37'(<=>=(
!
!
!
! !?+#&*5#(
! @1(#$,+(;*;3&/(A3(7,+5"++(73#*,4+(%B(#A%(&3531#(?%#+(C(D3"E(*17(E;.F.3/(*17(+#"7.(
! #$3,&(,1#3&*5#,%10(G3(73+5&,?3($%A(#%(&383&+3(31H,133&(#$3(#A%(?,1*&,3+(*17(
5%6;*&3(#$3(%?B"+5*#,%1(*17(*1#,I73?"HH,1H(#35$1,J"3+("+37(?.(#$360(E,153(#$3&3(
!
! ,+(*4&3*7.(6"5$(4,#3&*#"&3(73+5&,?,1H(#$3,&(,17,8,7"*4(6*4,5,%"+(5*;*?,4,#,3+/(#$,+(
! ;*;3&(7%3+(1%#(B%5"+(%1(#$%+3(*+;35#+0(@1+#3*7/(#$3(B%5"+(,+(;&,6*&,4.(%1(#$3(,1#3&I
! ;&%53++(5%66"1,5*#,%1(?3#A331(#$3(#A%(?%#+(C(A$,5$(,+(*(&34*#,834.(&*&3(
! ;$31%631%1(,1(#$3(A%&47(%B(6*4A*&30(
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

© 2010 The SANS Institute Author retains full rights.!


!
!
! Clash of the Titans: ZeuS v SpyEye 2
! (
!
!
!
!
1. Introduction
! The stage, it seems, is set for an epic battle between two of the most dangerous
!
fighters in the nefarious world of malware. In one corner: ZeuS, undoubtedly the reigning
!
! champion of Banking Trojans, so much so, that the distinction of “king” has often been
!
used to describe it (Falliere & Chien, 2009). In the other corner: SpyEye, a relatively new,
!
! but at the same time worthy, challenger, posing to dethrone ZeuS. This paper documents
! a part of this budding and dynamic battle as it unfolds – so dynamic in fact, that within
!
! the time it took to write this paper, both crimeware kits had already moved on to their
! next releases, implementing some serious licensing and anti-reversing measures (Krebs,
!
! 2010).
!
! The skinny from reports is that SpyEye is challenging the supremacy of ZeuS by
! threatening to remove ZBot from infected systems.1 It has received much attention
!
! (Krebs, 2010; Coogan, 2010; Mieres, 2010; McMillan, 2010; Kelchner, 2010; Paz,
! 2010) recently due to its ability to “Kill ZeuS”. Has SpyEye really discovered the
!
Achilles’ heel of ZeuS? And is all this media hype justified? After all, there have been
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
others such as Opachki (Stewart, 2010), which also claim to be able to remove ZeuS from
an infected host. Why then, should SpyEye receive such attention? Well, in this case, as
is often seen, the devil lies in the details. This paper shows that SpyEye uses a far
superior technique for removing ZeuS than other malware. Whether SpyEye is actually
successful at removing the large diversity of ZeuS variants that have appeared over the
years, remains to be seen. However, the technique in itself is rather interesting and has
been discussed in-depth in Section 6 of this paper. But first, let us get to know more
about the stage and the contestants.

2. The Stage: Reversing Tools and Environments


During the course of this research we have used many tools – most of which are
mentioned in this section. Even though, output from all of these might not appear in text

((((((((((((((((((((((((((((((((((((((((((((((((((((((((
>(D?%#(,+(#$3(1*63(H,831(#%(?%#(?,1*&,3+(?34%1H,1H(#%(#$3(D3"E(?%#13#K+L0()%A383&/(,1(#$,+(;*;3&/(A3(

"+3(#$3(#3&6(D?%#(*17(D3"E(,1#3&5$*1H3*?4.0(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! (
!
! of the paper - this was done to conserve space and not to devalue the importance of the
! tool itself.
!
! 2.1. Virtual Machines
!
! Virtual machines provide a safe sandbox for executing and analyzing malware. In
! addition, they also provide the ability to take snapshots and to revert to an existing
!
! snapshot at a later stage. This makes both static and dynamic analysis easier. For this
! research, we used VMWare ESXi Server version 4.0 in order to host our Virtual
!
! Machines. We used two virtual machines:
!
! 1. The Infected box, which is a Windows XP SP2 version 5.1.2800 virtual
! machine with single 500MHz processor with 512 MB Ram and 4 GB disk
!
space. The host file (c:\Windows\System32\drivers\etc\host) was modified to
!
! redirect traffic from the bots to the second VM described below. (Figure 1)
!
!
! 2. The C&C box, which is a Windows 2000 Server SP4 version 5.0.2195 virtual
! machine. We are running a fake server script written in python. This script is
!
given in the section 10.7 entitled “Fake Server Script”. (Figure 2)
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! (
! !"#$%&'()'*"+,"-./01&+,&2'*3'%$00"0#'4&$5'602'57898&'
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

(
!"#$%&':)';<;'5&%=&%'*3'

2.2. Dynamic Analysis Tools


Regshot: Shows Registry and File changes between two of its snapshots
(TianWei, 2008).
Wireshark: Network Protocol Analyzer and packet capture utility (Combs, 1999).
Process Explorer: Tool to display process information (Russinovich M. , 1998).
Process Monitor: Records detailed file-system, registry and thread activity
(Russinovich & Cogswell, 1996) .
(

2.3. Code Analysis Tools


OllyDbg: Debugger for Win32 binaries (Yuschuk, 2000).
Immunity Debugger: Debugger for Win32 binaries (Immunity, 2009).
IDA Pro: Disassembler and debugger with graphing and visualization capabilities
(Datarescue sa/nv , 2006).

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! (
!
! 2.4. Miscellaneous Tools
! LordPE: PE dumping and editing utility (mmi, 2009).
! PEiD: PE File identification tool to identify file type, packers, compilers etc.
! (Jibz, snaker, & Qwerton, 2005).
! Python: General Programming Language (Rossum, 2000).
! VirusTotal: Online Scanning of Binaries (Hispasec, 2008).
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 7
! (
!
!
!
!
!
3. ZeuS : The Reigning Champion
! (
! M$3(+*6;43("+37(#%(*1*4.N3(D3"E(?%#13#(A*+(B%"17(,1(#$3(A,47(B&%6(*(;"?4,5(
!
+%"&530()3&3(*&3(+%63(73#*,4+(*?%"#(#$3(+*6;432'(
!
! (
! @731#,B,3&+'((
(
! QRS('(T5B5UVBWW3V?<X7T53357X?*V=SX3>TW((
! ( E)!>'(?V*<X<?BT>TW*=U=*?UVVUW<?YSWS=7SX?SX=WUT((
! !O(-*63+'(M&%Z*10D?%#([E.6*1#35\/(M]^_`E:^M0EO](
(
! [M&317Q,5&%\/(M&%Z*1IE;.0G,1T<0D?%#0*3B$([a*+;3&+b.\(
! ( (
!
PEiD output is shown in Figure 3. Although PEiD is not able to identify the packer, some
!
! of its heuristics indicate that the binary is packed.
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>)'?9"@'A$,7$,'!B%'4CB,'

((((((((((((((((((((((((((((((((((((((((((((((((((((((((
<(!(6%&3(5%6;&3$31+,83(4,+#(%B(!O(1*63+(,+(H,831(,1(!;;317,P(>=0>(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 8
! (
!
! Inspecting the file in OllyDbg shows the common dialog box shown in Figure
! 4.
!
!
!
!
!
!
!
! !"#$%&'D)';B--B0'AEE8@F#'@"GEB#H'
'
!
Moreover, the absence of meaningful referenced strings in code confirms the
!
! packing (Figure 5).
!
!
!
!
!
!
!
! !"#$%&'I)'6EE'J&1&%&0+&2'K&L,'5,%"0#M'
! (
! Since the binary is packed, the packer is not known and no automated unpacking
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
is possible, we unpacked the binary manually. During the process, we found the
following anti-debugging technique:

...
00403A2A .>PUSH DWORD PTR SS:[EBP-8] ; /hObject <- Push invalid handle
00403A30 .>CALL <JMP.&KERNEL32.CloseHandle> ; \CloseHandle

(
This technique is well documented (Falliere, 2007) and involves trying to close an
invalid handle, which, in presence of a debugger, gives STATUS_INVALID_HANDLE
(0xC0000008) exception. To bypass it, we patched the binary by replacing these
instructions with NoOps (0x90). Once this check is bypassed, the binary does not give
much more trouble. After a series of cross section hops, each section, contributing to
unpacking, the binary is finally unpacked. However, even after unpacking, no meaningful
referenced text strings are seen in the code. This is because strings are obfuscated. They
are present in the binary in a form where first byte gives the string size and the remaining
bytes are encoded. The following figure shows the code used to de-obfuscate strings on
the fly (Figure 6):

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 9
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&'N)'5,%"0#'@&+B2"0#'OBB7'GM'MPBQ0'F8'/@6?%B'
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
(
After unpacking, the Trojan creates the import table by loading the necessary
DLLs using Kernel32!LoadLibrary and getting the address of needed procedures using
Kernel32!GetProcAddress.

ZBot is known to create Mutexes to mark different stages of execution. At this


initial stage, our sample creates the following Mutex as shown by the code in Figure 7:

!"#$%&'R)'3G"0'@%B77&%SM'3$,&L';%&G,"B0'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 0
!
! Then it checks if another Mutex is present as shown in Figure 7. This Mutex is
! created at a later stage in execution. This check ensures that the host is not already
!
infected (Figure 8).
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'T)';P&+U'1B%'9L"M,"0#'3$,&L'
! (
! The Trojan then checks for the presence of the processes associated with firewall
!
! software as shown by the code in Figure 9:
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'V)'A$,7BM,'G02'4B0&6EG%-';P&+U'
(
Next, it creates a copy of itself in the following location:

%system%\ntos.exe

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 1
!
! It sets the attributes of the file created to SYSTEM|ARCHIVE and then adds a random
! amount of random data at the end of the file as shown by the code Figure 10. This
!
ensures that the dropped file has a different MD5/SHA1 hash each time it is created.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'(W)'677&02'JG02B-'@G,G'
! (
It then appends the name of the newly created file to the end of the key:
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\userinit

This ensures that the malware executes upon windows start-up as shown in the
Figure 11.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 2
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'(()'6$,B%$0'X&8'
! (
! Now that the binary is installed on the system, it starts the infection process by
!
! injecting code into the WinLogon.exe process (Figure 12, Figure 13):
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'(:)'A7&0'Y"0EB#B0'!B%';B2&'/0Z&+,"B0'
(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 3
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'(>)';B2&'/0Z&+,"B0'"0,B'Y"0EB#B0'="G'X&%0&E>:[;%&G,&J&-B,&KP%&G2'
(
Once the code injection is complete, the main process goes into an infinite loop
waiting for the creation of a certain Mutex, which will be created at a later stage in the
infection process. This loop along with the name of the Mutex is shown in the Figure 14.

!"#$%&'(D)'YG","0#'B0'3$,&L';%&G,"B0'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 4
!
! Now let’s inspect the injected code. The injected code creates a new directory as
! shown in Figure 15.
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&'(I)';%&G,&'QM07B&-'@"%&+,B%8'
!
(
!
And then creates a file named “video.dll”. This file is later used to save the
!
! downloaded configuration file (Figure 16):
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'(N)';%&G,&'="2&BH2EE'1"E&'
(
It also creates a file named “audio.dll” which is used to store the stolen data to be
sent to the server (Figure 17).

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 5
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'(R)';%&G,&'G$2"BH2EE'1"E&'
! (
! Next, it creates a Named pipe, which is later used for communication of this
! component with other ZBot components (Figure 18).
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'(T)''Y"0EB#B0'"0Z&+,"B0'+%&G,&M'G'\G-&2'?"7&'
(
Then it creates a thread, which is responsible for Inter-Process Communication
between various ZBot components. This thread first creates a Mutex (Figure 19). Note
that the presence of this Mutex was checked earlier to ensure that the system is not
already infected. Also note that the name of the Mutex is same as the name of the Named
pipe created earlier. The importance of this fact will be discussed when in Section 6
covering the interaction of SpyEye with ZeuS . This thread then connects to the Named
Pipe and waits for a client to connect to it.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 6
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'(V)'Y"0EB#B0'"0Z&+,"B0'+%&G,&M'G'3$,&L'
! (
! Meanwhile, the main thread, running the code injected into winlogon.exe, checks
! for the presence of a Mutex. Note that this Mutex is same as the one for which the
!
dropper process is waiting. If this Mutex does not exist, the code in winlogon.exe, does
!
! another code injection – this time into svchost.exe using the same techniques described
!
before.
!
! The code injected into svchost.exe creates another Named pipe (Figure 20) and
!
then "#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
creates a thread, which is responsible for Inter-Process Communication via Mutexes
and Named Pipes. This thread creates another Mutex with the same name as the pipe.
Note that this is the same Mutex for which the original dropper process is waiting, as
discussed earlier. After that, the thread connects to the Named Pipe and waits for a client
to connect to it and then send data.

!"#$%&':W)'5=+PBM,'"0Z&+,"B0'+%&G,&M'\G-&2'?"7&'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 7
!
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&':()'5=+PBM,'"0Z&+,"B0'+%&G,&M'3$,&L'
!
(
!
The injected code in svchost.exe is responsible for network communication. It
!
! sets up a connection with the remote server and downloads an encrypted configuration
!
file. A lot has already been written about network communication of ZeuS (Shevchenko,
!
! 2009). Therefore, in order to save space, we have included the configuration file format
!
and encryption scheme in Appendix 10.2.
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
As mentioned previously, the main binary is waiting in an infinite loop for
creation of the Mutex, which is finally created by the code injected to svchost.exe. Once
this Mutex has been created, it breaks out of that loop. It steals cookies and other
information from Macromedia Flash *.so files, saving the stolen data into the file
audio.dll. It also connects to named pipes created by other components and
communicates with them as discussed later. Finally it terminates leaving other
components injected into processes to steal data, and communicate with each other via
their individual pipes.

Since we have Zbot installed and running, happily stealing information and
passing it on to its server, we can now discuss a little bit about the named pipe based
communication technique of Zbot. The function responsible for this communication takes
a single parameter as input. This parameter is a pointer to a structure which, based on
code analysis, seems to have the following format:

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 8
!
! !""#$%& '()$*+,%$#-& ./01$&
! !"!!!!# $# %&'()#*#+,-).#&'()#/,0.1)#
! !"!!!$# $# %23)045#*#/,0.1)#46#,0#23)04#
! !"!!!7# $# %23)048#*#/,0.1)#46#,064%)9#23)04#
! ;&49*#<=0>4'60#(6'04)9#6;#:6--,0.#&96>)??69#
! !"!!!:# $# ;=0>4'60#
! !"!!5!# $# ?@A=4)"+,-)*#&6'04)9#46#A=4)"B+,-)#C49'0D#
!
! This function does the following:
!
! 1. Create a Mutex with the name szMutexName (Figure 22)
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'::)'4&$5'/?;'5,&7M'(]>'
2. Set hEvent2 (Figure 22)

3. Wait for hEvent1 to be set (Figure 22)

4. While hEvent1 is set loop:

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 1
! ( 9
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&':>)'4&$5'/?;'5,&7M'DG]D+'
!
(
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
a. Connect to the Named Pipe – This is a blocking call, which waits
till a client connects. (Figure 23)

b. Once a client is connected, read the command code from the


named pipe. (Figure 23)

c. Read the size of parameters of the command. (Figure 23)

d. If the parameter size is higher than 0x10 (16):

i. Allocate memory for the parameter.

ii. Read the parameter into the allocated buffer.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 0
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
!"#$%&':D)'4&$5'/?;'5,&7M'DH2H"']'DH2H""'
(
e. Call the command processor function with the command code, the
parameter and the parameter size. (Figure 25)

f. Write the response to the Named Pipe. (Figure 25)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 1
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&':I)'4&$5'/?;'5,&7M'D&']'D1'
g. Disconnect from the Named Pipe. (Figure 26)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 2
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
!"#$%&':N)'4&$5'/?;'5,&7M''D#^'I]R'
(
5. Close Mutex Handle. (Figure 26)

6. Set hEvent2. (Figure 26)

7. Return. (Figure 26)

During code analysis we found two kinds of command processors:

1. Command Processor to handle commands between 0x01 and 0x0E

2. Command Processor to handle commands 0x03, 0x0F through 0x11

These commands can be used to gain information, such as the current path of
Zbot binary (Command Code: 0x0B) or to Request for some action such as close handle
of the Zbot config file to allow another component to write to it (Command Code: 0x06).
The code in Figure 27 shows processing of Command Code: 0x06, which causes the
closure of the handle to the config file (“Video.dll”).

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 3
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&':R)'?%B+&MM"0#'B1';B--G02';B2&'N'
!
!
! At this point, our introduction to ZeuS is more or less complete. However, the
!
! above description of ZeuS must follow a “Mea culpa” of sorts, since it does not come
! close to describing the complete functionality of Zbot – unfortunately that would take
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
considerably more time and space than what the scope of this paper allows. That said, it
is now time to move on to the other side of our metaphorical battlefield and get
introduced to SpyEye.

4. SpyEye: The challenger


The SpyEye sample was also found in the wild.
Here are some details about the sample3:

@731#,B,3&+'((
QRS('(WXV>X5>==7<7B5WWY<UST>BYXSY?W<VY(
E)!>'(3553<YWXB>XT?=<B5>WV*X*Y*B<<B>3U37Y5<5YB(
!O(-*63+'(M&%Z*10E;.3.3([E.6*1#35\/(ME9c`FcF:^M0EQ!(
[M&317Q,5&%\/(M&%Z*1IE;.0G,1T<0E;.F.3+07([a*+;3&+b.\(
( (
(

((((((((((((((((((((((((((((((((((((((((((((((((((((((((
T(!(6%&3(5%6;&3$31+,83(4,+#(%B(!O(1*63+(,+(H,831(,1(!;;317,P(>=0T(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 4
!
! PEiD output for the sample is shown in the Figure 28. It appears that the sample is
! not packed. Figure 29 shows the list of inter-modular calls and text strings found in
!
OllyDbg. While the text strings show many DLLs, the inter-modular calls do not show
!
! any method being called from them. This seems quaint.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&':T)'?9"@'A$,7$,'!B%'57898&'5G-7E&'
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 5
!
!"#$%&':V)'6EE'J&1&%&0+&2'K&L,'5,%"0#M'"0'57898&'+B-7G%&2'Y",P'/0,&%]-B2$EG%';GEEMH'
!
(
! The reason becomes clear as further code is inspected. The first function to be
!
! called returns the OS version. To understand how SpyEye does this, let us consider the
! code shown in Figure 30. The returned value is the OS version. So somehow, the 4-byte
!
! value passed (0x9C480E24) is being converted into a function that returns the OS version
! and that function is being called. Clearly some hashing scheme is used wherein the key
!
! 0x9C480E24 is converted into a function that can return the OS Version. Such
! obfuscation techniques are discussed in some books and papers (Eagle, 2008; Skape,
!
! 2004).
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>W)'57898&'Y"0>:6?/';GEEM'="G'_GMP&M'
(
Upon further inspection, we found the code snippet shown in Figure 31.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 6
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>()';B2&',B'+B0=&%,'6?/'!$0+,"B0'\G-&',B'_GMP'
(
The following python code explains the algorithm:

#!/usr/bin/python
import sys

def nameToHash(name):
j = 0

for i in range(0,len(name)):
left = (j << 0x07) & 0xFFFFFFFF
right = (j >> 0x19)
j = left | right
j = j ^ ord(name[i])

return j

Hence, we are now able to explain how the function name is converted to hash. To
find the appropriate function, SpyEye converts the name of each exported function to its
hash and matches this value with the hash passed as the function argument. If the value
matches, the address of the exported function is returned. To make further analysis easier,

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 7
!
! we wrote a python script given in Appendix 10.4, which can return the name of the
! function given the hash value. Using this script, the function name corresponding to
!
0x9C480E24 was found to be Kernel32!GetVersionExA. This explains the mystery of
!
! how an API function is identified based on its hash.
!
! So now let’s see how the exported function gets called. We assumed that if we put a
! breakpoint on this function i.e. Kernel32!GetVersionExA, it would be hit and we could
!
! see the stack-trace and find where the call is made – but to our surprise we found that the
! breakpoint is never hit. Looks like SpyEye goes to great lengths to avoid such analysis in
!
! a debugger. Upon further static analysis we found that it uses a novel technique that has
! not been observed in common malware. Almost all calls to common Windows DLLs
!
! have been replaced with a special code that maps a DLL into a new section in the
! memory and find the address of the function to be called within that section and then calls
!
! that function. The general technique used to accomplish this is as follows:
!
1. Select the library implementing the function.
!
! 2. Find the base of Ntdll.dll.
!
3. Find address of the procedure LdrLoadDll within Ntdll.dll.
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
4. Load the library, whose name was found in Step 1, using LdrLoadDll.
5. Find the function name from the hash value as discussed before and shown in
Figure 31.
6. Find the offset of the function inside the loaded DLL.
7. Pass the DLL name and the function offset to a function that does the
following:
a. Open the DLL file using ntdll!NtOpenFile
b. Create a new section using ntdll!NtCreateSection
c. Map the file into the newly created section using
ntdll!MapViewOfSection. Hence the DLL is mapped into a new section in
memory.
d. Find the function address inside the new section from the offset passed.
Return this address.
8. Now function at address returned by step 7d is called using the appropriate
arguments.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 8
!
! 9. After the function call, the DLL is unmapped.
! The code showing this implementation is given in Appendix 10.5. Astute readers
!
will quickly realize that the malware must need a different technique than the one
!
! described above to call the methods, such as ntdll!NtOpenFile used to determine the
!
function addresses. This is absolutely correct. The Trojan has functions that use a slightly
!
! different approach to finding these native API functions. For these functions, the code
! finds the method name from hash and then calls them without mapping ntdll into a new
!
! section – since they are themselves needed for the process of mapping.
!
! Once this mechanism was found, we searched the code for all calls, which were
! made in this manner. Using the script given in Appendix 10.4, we added labels to code
!
! where we found such calls being made. These labels took the form of
! “[API_FunctionName]Caller”, for example, “CreateDirectoryACaller” as shown in
!
! Figure 32. Over all, close to 50 such labels were added.
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>:)'5B-&'OGF&EM'622&2'"0'/@6?%B'

Stepping further into code we also encountered the code snippet shown in Figure
33.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 2
! ( 9
!
!
!
! !"#$%&'>>)'57898&'_GMP',B'5,%"0#'9LG-7E&'
! The function takes a 4-byte value and returns a string (in this case explorer.exe).
! Hence, the call is somehow converting the 4-byte hash value into a string. Following the
!
! code we found that the hash value is used as an index into a table. The table points to
! strings of bytes in memory. This is actually an ASCII string in its encoded form. The
!
! decoding algorithm is shown in Figure 34.
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
!"#$%&'>D)'57898&'5,%"0#'@&+B2"0#'
(
Simply stated, it consists of starting from the end of the string and subtracting
each character from its previous one, while all changes are made in place. Here is an
encoded the string:

00405AE0 65 DD 4D B9 28 9A FF 71 9F 04 7C E1

Using the algorithm discussed above, we can see that the last character should be

0xE1 – 0x7C = 0x65 (‘e’)

Decoding whole string in this manner, we find that the string is “explorer.exe”:

00405AE0 65 78 70 6C 6F 72 65 72 2E 65 78 65

Having understood both the code and string obfuscation mechanisms, the code
can now be analyzed in detail. The main task being performed can be described in the
following Steps as shown in flowchart of Figure 35:

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 0
!
! 1. Try to Create Mutex named “__CLEANSWEEP__”
!
2. If Mutex already exists, it means the system is already infected, go to step
!
! 6. Else go to Step 3.
!
! 3. Try to inject code into “explorer.exe”. If injection succeeds, go to step 6.
! Else go to Step 4.
!
! 4. Try to inject code into any process. If injection succeeds, go to step 6. Else
!
! go to Step 5.
!
! 5. All injection attempts have failed, so just call the injected code in this
! current process itself. Then go to Step 6.
!
! 6. Call ExitProcess
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 1
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>I)'57898&'@%B77&%'3G"0'!$0+,"B0'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 2
!
! Since following code injection into explorer.exe is tedious, we patched the code in
! OllyDbg to directly go to code that should have been injected into Explorer. This happens
!
to be the dropper code that creates a directory with the name c:\cleansweep.exe and
!
! inside the directory creates a file cleansweep.exe and a file config.bin. Creation time of
!
all of these files is set to the creation time of ntdll.dll. It then opens the dropped file as a
!
! sub-process of itself. To save space, we are not showing that full code here, but the final
! call to CreateProcessA (CreateProcessACaller to be precise) is shown in Figure 36.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>N)'57898&'@%B77&%'EG$0+P"0#'2%B77&2'F"0G%8']';%&G,&?%B+&MM6'+GEE'

Some information regarding the dropped executable is shown below4:

@731#,B,3&+'((
QRS('(7>7SU>B<>SXTB<S3<=T=SX?VT5=VBBSW(
E)!>'(VVY>?<YYYYSY*?SVXW><WUSX73>V?7U>TY<SV*7W(
!O(-*63+'(M&%Z*10E;.3.3([E.6*1#35\/(ME9c`FcF:^M0!(
[M&317Q,5&%\/(M&%Z*10G,1T<0E;.F.3+0?([a*+;3&+b.\(
(

((((((((((((((((((((((((((((((((((((((((((((((((((((((((
X(!(6%&3(5%6;&3$31+,83(4,+#(%B(!O(1*63+(,+(H,831(,1(!;;317,P(>=0Y(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 3
!
! This binary is unpacked and has strings that are mostly un-obfuscated. Some important
! referenced strings are shown in Figure 37, Figure 38, Figure 39 and Figure 40.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'>R)'57898&'5,%"0#M)'3$,&L^';B01"#'?GMMQB%2^'?A5K'%&`$&M,'G02'7G%G-&,&%M'
! (
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'>T)'57898&'5,%"0#M)'5&%=&%';B--G02M^'3B%&'3$,&L&M'
(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 4
!
!
!
!
!
!
!
!
!
! !"#$%&'>V)'57898&'%&1&%&0+&M'4CB,'E"U&'0G-&2'7"7&M'
! (
!
!
!
!
!
!
!
! (
! (
! !"#$%&'DW)'5$M7"+"B$M'M,%"0#M'2&GE"0#'Q",P';%&2",';G%2'!B%-MH'
! (
! To better control the new process being created, we terminated the existing
! process before it calls CreateProcessA. We then launched the process (cleansweep.exe)
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
independently of the dropper in a debugger.

The main loop of this binary does the following tasks:

1. Check that the OS version is higher than 5 (Figure 41). Else exit.

!"#$%&'D()'@%B77&2'57898&'3G"0'5,&7M'(^:'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 5
!
!
!
2. Create a Mutex to mark presence and confirm that the host has not already
!
! been infected (Figure 41).
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'D:)'@%B77&2'57898&'3G"0'5,&7'>'
'
3. Read the config.bin file created in the same folder by the dropper (Figure
42). The config.bin is actually just a password protected zip file whose
first two bytes (in the header) have been replaced with 0xFF. If the first
two bytes are changed to “P” and “K”, making the file a legitimate PKZip
archive, the file see to be a password protected archive. The password is
known from the strings seen earlier. Upon extraction, the file config.bat is

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 6
!
! retrieved. Figure 43 shows the contents of the config.bat file. It also shows
! the extracted URL.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'D>)'57898&';B01"#'!"E&'@&+B2&2'
! (
! 4. Try to inject code into explorer.exe. If this succeeds the process
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
terminates. Else go to step 5. (Figure 44)

5. Try to inject code into any process. (Figure 44)

6. Exit (Figure 44)

!"#$%&'DD)'57898&'@%B77&2'3G"0'5,&7M'D^'I^'N'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 7
!
! We followed the second injection, this time done by the dropped binary
! cleansweep.exe, into explorer.exe. The injected code was dumped using the LordPE and
!
opened in IDAPro for static analysis. The function is shown in Figure 45. The following
!
! steps describe the basic functionality:
!
! 1. Create Mutex named __CLEANSWEEP__ (Figure 45)
!
! 2. Create a thread that monitors the existence of Mutex called
! __CLEANSWEEP_UNINSTALL__. This Mutex stops SpyEye when an
!
! updated binary is downloaded from the C&C server. (Figure 45, Figure
! 46)
!
! 3. Create an auto-run registry key to ensure that cleansweep.exe is executed
!
upon Windows startup as shown in Figure 46.
!
!
4. Do further code injection into any process – this generally ends up being
!
! the generic host process svchost.exe. The injected code seems to do
! further code injections and other malicious functions. (Figure 45)
!
! 5. Create a thread which initiates C&C communication with server sending
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
some information such as a GUID, the version of the bot, the version of
Internet Explorer, User-Type, Cpu Load, Config file CRC etc. Also create
another thread which monitors existence of the Mutex
__CLEANSWEEP_UNINSTALL__. (Figure 45)

6. Get current module name and check for if contains *explorer.exe*. If it


does go to step 8. Else go to step 7. (Figure 45)

7. Call function to create threads, which implement other malicious


functionalities including a user-mode rootkit component to hide files and
registry keys created. Since a comprehensive description of malicious
functionalities is out of the scope of this paper, these are not described
here. To give an idea of the complexity and number of functional
components involved, please refer to the Figure 47, obtained from an
article based on a conversation with the SpyEye creator(Error! Reference

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 8
!
! source not found.). It also creates a thread which monitors the existence
! of the Mutex __CLEANSWEEP_UNINSTALL__. Go to Step 8.
!
! 8. Deal with ZeuS and Windows Defender. We will discuss interaction with
! ZeuS in Section 6 of this paper. Figure 48 shows SpyEye disabling
!
! windows defender.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 3
! ( 9
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'DI)'9L7EB%&%'/0Z&+,"B0'F8';E&G0MQ&&7H&L&']'3G"0'!$0+,"B0'
(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 0
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'DN)'57898&'6$,BJ$0'J&#"M,%8';%&G,"B0'
! (
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

(
!"#$%&'DR)'57898&';B-7B0&0,M'1%B-'AE2&%'*&%M"B0H'J&7%B2$+&2'1%B-'a3"&%&M^':W(Wb'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 1
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'DT)';B2&'1B%'2"MGFE"0#'Y"02BQM'@&1&02&%'
! (
! Before we move on to the topic of interaction, let us take a moment to summarize and
!
compare the features of the ZBot and SpyEye that we have discussed so far.
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

5. Feature Comparison
Now that we have discussed some of the features of ZeuS and SpyEye, we are in
a position to make a comparative analysis of their features as discussed in (Figure 49).
Note that this comparison is based on features observed in the analyzed samples – other
samples may show different behavior. Moreover, this table is a small subset of features
and do not include their malicious capabilities such as key logging and form grabbing.

2$/%13$4+5%& '7,8,$& 9$1'&


'/670$&
'/670$&:/;<(=>& E%)#?(F)F)#?,-(1)#,0,1F@).#G,?#064#;6=0.# E%)#K)=C#?,-(1)#,0,1F@).#
46#H)#(,>I).J# G,?#;6=0.#46#H)#(,>I).#G'4%#
,0#=0I06G0#(,>I)9#
'%3(=>& C(F2F)#%,?#,#>6-(1)"#?49'0D#6H;=?>,4'60# K)=C#%,?#,#9)1,4'3)1F#?'-(1)#
!?"1#;/%(5=& 4)>%0'L=)#,0.#>6.)#9);)9?#46#?49'0D?#HF# ?49'0D#6H;=?>,4'60#4)>%0'L=)J#
-),0?#6;#,#%,?%M#G%'>%#'?#(,??).#46#,#
;=0>4'60#4%,4#9)4=90?#,#?49'0DJ#

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 2
!
@5A$& C(F2F)#%,?#,#>6.)#6H;=?>,4'60#4)>%0'L=)# K)=C#?,-(1)#,0,1F@).#.'.#064#
!
!?"1#;/%(5=& G%)9)#,1-6?4#,11#N'0O8#P&Q#>,11?#,9)# %,3)#,0F#6H;=?>,4'60#64%)9#
!
9)(1,>).#G'4%#,#>6-(1'>,4).#?>%)-)#-,I'0D# 4%,0#(,>I'0DJ#
! >6.)#,0,1F?'?#L='4)#%,9.J#
! B$?1>>$3& P14%6=D%#C(F2F)#'?#I06G0#46#%,3)#?6-)# K)=C#?,-(1)#G,?#;6=0.#46#
! B$%$;%(5=& P04'R)H=DD)9#49'>I?M#G)#.'.#064#>6-)#,>96??# %,3)#,0#,04'B.)H=DD)9#
! 4%)-#'0#6=9#,0,1F?'?J#E%'?#-'D%4#H)#H)>,=?)# 4)>%0'L=)#'03613'0D#Q03,1'.#
! G)#.'.#064#;6116G#!""#>6.)#'0S)>4'60?J# /,0.1)?J#
!
! .(3%1/0& C(F2F)#?,-(1)#G,?#064#;6=0.#46#%,3)#,0F# K)=C#?,-(1)#G,?#064#;6=0.#46#
C/;D(=$& TA#R)4)>4'60#4)>%0'L=)?J# %,3)#,0F#TA#R)4)>4'60#
!
B$%$;%(5=& 4)>%0'L=)?J#
!
E=%(& C(F2F)#%,?#,#96=4'0)M#G%'>%#.'?,H1)?# K)=C#?,-(1)#%,?#,#;=0>4'60M#
!
E.42(3$F/00& N'0.6G?#R);)0.)9#(96.=>4#;96-#A'>96?6;4J# G%'>%#.'?,H1)?#N'0.6G?M#K60)#
! G$;D=(H1$#& P1,9-#,0.#U=4(6?4#;'9)G,11?J##
! B3577$3& C(F2F)#?,-(1)#,99'3)?#'0#4%)#;69-#6;#,# K)=C#?,-(1)#G,?#,1?6#?))0#46#
! I51%(=$#& .96(()9M#G%'>%#.96(?#,0.#'0?4,11?#4%)# ,99'3)#,?#,#.96(()9M#G%'>%#
! ?,-(1)J# .96(?#,0.#'0?4,11?#4%)#?,-(1)J#
! /6G)3)9M#'4#,1?6#,(()0.?#
! 9,0.6-#,-6=04#6;#9,0.6-#
! .,4,#46#)0?=9)#4%,4#4%)#%,?%#
! ,0.#;'1)#?'@)#'?#.';;)9)04#;69#
! ),>%#?,-(1)J#
! E1%531=& C(F2F)#=?)?#4%)#I)F*# K)=C#=?)?#4%)#V$%&'()(*V#
! G$;D=(H1$& HKCU\SOFTWARE\Microsoft\Windows ?=HI)F#6;*#
NT\CurrentVersion\Run#
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
HKLM\SOFTWARE\Microsof
t\Windows
NT\CurrentVersion\Winl
ogon#
@5A$&J=K$;%(5=& C(F2F)#.6)?#-,0F#>6.)#'0S)>4'60?J#23)0#4%)# K)=C#,1?6#'0S)>4?#'4?#
.96(()9#>6.)#'?#'0S)>4).#'046#)"(169)9J)")M# >6-(60)04?#'046#-,0F#
G%'>%#1),.?#46#?)3)9,1#64%)9#>6.)#'0S)>4'60?J# .';;)9)04#(96>)??)?#?=>%#,?#
?3>%6?4J)")M#G'016D60J)")#,0.#
>?9??J)")J#
J=%$3735;$##& C(F2F)#?,-(1)#?))-?#46#'-(1)-)04#Q&:# K)=C#=?)?#A=4)")?#,?#G)11#,?#
@5661=(;/%(5=& =?'0D#A=4)")?#601FJ# +,-).#&'()?#;69#Q&:#
*J:@-&
@5="(>13/%(5=& C(F2F)#%,?#,#.);,=14#'0'4',1#>60;'D=9,4'60#;'1)M# K)=C#?,-(1)#.6)?#064#%,3)#,#
2(0$& G%'>%#.'9)>4?#4%)#E96S,0#46#.6G016,.#,#9),1# .);,=14#>60;'D=9,4'60J#Q4#0)).?#
>60;'D=9,4'60#;'1)#;96-#4%)#:W:#?)93)9J#E%)# 46#D)4#'4?#>60;'D=9,4'60#;96-#
>60;'D=9,4'60#;'1)#'?#'0#4%)#;69-#6;#,# 4%)#:W:#?)93)9J#E%)#?,-(1)#
(,??G69.#(964)>4).#&XK'(#,9>%'3)J## ,0,1F@).#=?)?#4%)#0938H#
,1D69'4%-#,160D#G'4%#060BI)F#
?()>';'>#)0>6.'0DJ#/6G)3)9M#'4#
'?#I06G0#4%,4#0)G)9#3)9?'60?#
6;#K)=C#06G#=?)#,#(9'3,4)#I)F#
H,?).#)0>6.'0D#?>%)-)#
?'-'1,9#46#Y:$J#
'

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 3
!
!"#$%&'DV)'57898&'='4&$5']'!&G,$%&';B-7G%"MB0'
!
!
! 6. The battle begins.
!
! Now is the moment we’ll all been waiting for – seeing the malware samples
! exchange blows or at-least one of them knocking out the other. Let’s turn to some
!
! dynamic analysis first:
!
! Test 1:
!
! The Figure 50 shows the response of our fake web-server (Appendix 10.7) in a
! scenario where a system is first infected with Zbot and then restarted. Initially Zbot
!
sample sends a request to download its configuration file and then sends some POST
!
! requests. Upon restart, the request for configuration file and subsequent POST requests
!
are seen again. As expected, Zbot is still present on the victim’s host. Now we run the
!
! spy-eye sample which sends an initial website checking request and a GET request. The
! victim host is restarted – to check if Zbot is still present. The absence of request to
!
! download the ZBot configuration file shows that it has been removed from the system.
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 4
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'IW)'4&$5'='57898&']'K&M,('
!
!
Test 2:
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
In this test, as shown in Figure 51, we first the SpyEye sample is run. It sends its
requests and the server responds. Next Zbot is run – it also sends its requests. The two
bots seem to co-exist peacefully – hence SpyEye does not in any way prevent Zbot from
being installed. Upon restarting, however, Zbot requests are not seen any more. This
indicates that Zbot has been removed. This is because upon system restart, SpyEye gets
executed before the Zbot sample and removes it.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 5
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'I()'4&$5'='57898&']'K&M,:'
! (
! As discussed before, and shown in Figure 45, in step 8, a call is made to a
!
function responsible for removing ZeuS and disabling windows defender. This function
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
call is shown in Figure 48. In this section, we will focus on the function, which
implements the “Kill ZeuS” functionality. This functionality involves the following steps:

1. Get the names of ZeuS Binary and Mutex by sending the command 0x0B
to the ZeuS named pipes. (Figure 52)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 6
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'I:)'4&$5'J&-B=GE'M,&7M'('G02':'
(
2. Stop the threads of ZeuS by sending them Kill Command (0x03). (Figure
52)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 7
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'I>)'4&$5'J&-B=GE'M,&7M'>'G02'D'
! (
! 3. Close handle of ZeuS Mutex (since we duplicate the handle). (Figure 53)
!
! 4. Delete the binary whose path was obtained in step 1 as shown in Figure
! 54. (Figure 53)
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'ID)'4&$5'C"0G%8'@&E&,"B0';B2&'
(
Before we go into more details for each of these steps, let us first understand how
SpyEye connects to named pipes created by ZeuS. It uses the following steps to
communicate with ZBot named pipes:

1. Get a list of all open handles for each process in the System. (Figure 55)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 8
!
!
!
!
!
!
!
!
! !"#$%&'II'4&$M';B--$0"+G,"B0'5,&7'('
! (
! 2. For each process, for each handle:
!
! a. Get the name of the handle. (Figure 56)
!
!
!
!
!
!
!
!
!
!
!
!"#$%&'IN)'4&$M';B--$0"+G,"B0'5,&7':G'
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
(
b. Find if the handle-name has any of the following substrings as
shown in Figure 57:

i. __SYSTEM__

ii. _AVIRA_

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 4
! ( 9
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'IR)'4&$M';B--$0"+G,"B0'5,&7':F'
(
c. If it does, try to open a pipe with the name
\\.\pipe\<handle_name>

And set the Named pipe handle state to


“PIPE_READMODE_MESSAGE”. (Figure 58)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 0
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'IT)'4&$M';B--$0"+G,"B0'5,&7':+'
! (
! d. Now write the command (received as parameter) to the Pipe
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
opened before. (Figure 59)

!"#$%&'IV)'4&$M';B--$0"+G,"B0'5,&7M':2]:&'
(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 1
!
! e. Write Parameter Length to the Pipe (0 in our case). (Figure 59)
!
f. If Parameters are present, then write the parameters (There are
!
! none in our case) (Figure 60)
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'NW)'4&$M';B--$0"+G,"B0'5,&7':1']':#'
(
g. Read the Response. (Figure 60)

h. Read the length of data and allocate buffer of that length. (Figure
61)

i. Read the data into the buffer and copy it to the fileName argument
provided as input to this function. (Figure 61)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 2
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&'N()'4&$M';B--$0"+G,"B0'5,&7':"'
!
(
!
j. In addition, if the caller provided a pointer for the Mutex-Name
!
! argument, then set the handle-name as the name of the Mutex.
!
Note that as mentioned in the section 3, the Mutex name and pipe
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
name are the same. (Figure 62)

!"#$%&'N:)'4&$M';B--$0"+G,"B0'5,&7':Z'
(
k. Close the Pipe and Object handles.

Note that the above loop ensures that the command is sent to all ZeuS pipes. The
Figure 63 and Figure 64 show the ZeuS side of things i.e. how ZeuS handles these
commands. As shown in Figure 63, upon receiving the command 0x0B, it returns back

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 3
!
! the path of the Zbot binary, in this case – “C:\WINDOWS\system32\ntos.exe”. Figure 64
! shows the code setting an event, which is used to wake all threads and terminate them. It
!
is likely that Zbot uses this event during bot binary updates.
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'N>)'?%B+&MM"0#'A1'WLWC';B--G02'
! (
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'ND)'?%B+&MM"0#'B1'WLW>';B--G02'
(
( It should be noted here that SpyEye does not remove the registry keys created by
Zbot. In addition, it also does not remove the other files such as the configuration files
belonging to ZeuS from the host wither. However, having removed the executable
(d,H"&3(SX) and terminated the threads (d,H"&3(YX), the ZBot infection has clearly been
eliminated from the host. In this round of battle, SpyEye is the clear victor.

7. Conclusion
In this paper, we have discussed the details obtained from reverse engineering of
samples belonging to the SpyEye and ZeuS botnets. Our research has shown that the two

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 4
!
! bots uses similar and comparable infection strategies. For example both have obfuscated
! code to deter static analysis. Both also make extensive use of process injection techniques
!
and set up auto-run registry keys to ensure that they are executed when the system
!
! restarts. Both have techniques to bypass, evade or disable host-based firewalls. They also
!
use similar command and control structure, where the controlling server provides a
!
! configuration file, which is encrypted. This configuration file generally contains details
! of sites to be monitored, form grabbing details, in addition to URLs belonging to C&C
!
! sites.
! We also studied the interaction between the two bots. While it is generally known
!
! that SpyEye has capabilities to remove ZeuS, the exact technique used was not publicly
! known at the time of this research. In this paper we have given the details of how SpyEye
!
! exploits the named pipe communication mechanism that ZeuS uses to communicate
! between its components in order to command ZeuS to terminate all its threads and then
!
! removes its binary from the infected host. In effect, it hijacks the IPC mechanism of ZeuS
! and uses it to clean up Zbot from the machine. This technique is likely to work for all
!
! ZeuS samples that use named pipes with names containing the strings “__SYSTEM__”
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
and/or “_AVIRA_”.
As a final comment, we would like to assure the readers that no bots were harmed
during the course of this research!

8. Acknowledgements
I would like to thank my friends and co-workers – Nima Dezhkam, Bin Lin and
Steven Zhou, members of the Malware Research Team at Telus Security Labs for their
help and support during this research. I am also thankful to Thayaparen Thankarajah,
Program Director, Telus Security Labs for his help and guidance.
In addition, I am indebted to my research advisor, Pedro Bueno, who not only
helped in selecting this research topic, but was also extremely encouraging with his
generous compliments and patient reviews.

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 5
!
! 9. References
! e*&&3&*/(F0(K<==SL0(!"#$%"&'!()*+,'-+./%"')+'0"1.'1,.'2+03'2$)*'!4'5!+0)16%"'
!
! 47"8/)16%"9'#$%":;<+#)210"=>(]3#&,3837(B&%6($##;'ff5%730H%%H4305%6f;f;3B,43f(
! e%6?+/(g0(K>UUUL0(?$0":*103';<+#)210"=>(]3#&,3837(B&%6($##;'ffAAA0A,&3+$*&b0%&Hf(
!
! e%%H*1/(90(K<=>=L0(<@(4("'A+)'B"0:/:'C"/:'A+)>(]3#&,3837(!;&(<=>=/(<=>=/(B&%6(
! E.6*1#35(e%1135#'($##;'ffAAA0+.6*1#3505%6f5%1135#f?4%H+f+;.3.3I?%#I
!
! 83&+"+IN3"+I?%#(
! R*#*&3+5"3(+*f18(0(K<==YL0(DEF'!0+'E$:1::"-6%"0'1,.'E"6/GG"0';<+#)210"=>(]3#&,3837(
!
! B&%6($##;'ffAAA0$3PI&*.+05%6f,7*;&%f(
! F*H43/(e0(K<==WL0(@6;%&#37(d"15#,%1(^?B"+5*#,%10(@1(e0(F*H43/(H*"'DEF'!0+'A++3(K;;0(
!
! X<WIXT<L0(E*1(d&*15,+5%'(-%(E#*&5$(9&3++0(
! d*44,3&3/(-0(K<==VL0(?$,.+2:'F,)$IE"6/G'J"#"0",8">(]3#&,3837(!;&(<T/(<=>=/(B&%6(
!
! E.6*1#35(e%1135#'($##;'ffAAA0+.6*1#3505%6f5%1135#f*&#,543+fA,17%A+I
! *1#,I73?"HI&3B3&3153(
!
! d*44,3&3/(-0/(h(e$,31/(F0(K<==UL0(C"/<&'K$,G'L#')*"'A+):>(]3#&,3837(!;&,4(<T/(<=>=/(B&%6(
! E.6*?#35(E35"&,#.(]3+;%1+30(
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
),+;*+350(K<==WL0(M$0/:H+)1%'<81,0(]3#&,3837(R35(<S/(<=>=/(B&%6(O,&"+M%#*4'(d&33(
%14,13(6*4A*&3(+5*1'($##;'ffAAA08,&"+#%#*405%6f?"+5*)*+$0$#64(
@66"1,#./(@0(K<==UL0(D--/,$)('E"6/GG"0';<+#)210"=>(]3#&,3837(B&%6(
$##;'ffAAA0,66"1,#.,1505%6f;&%7"5#+I,667?H0+$#64(
_,?N/(+1*b3&/(h(iA3&#%10(K<==SL0(!4$E;<+#)210"=>(]3#&,3837(B&%6(
$##;'ffAAA0;3,70,1B%f(
a345$13&/(M0(K<=>=L0(<@('4("')++%'3$)'G+":'1#)"0'C"/:'6+),")>(]3#&,3837(!;&(<T/(<=>=/(
B&%6(E"1?43#(:4%H'($##;'ff+"1?34#?4%H0?4%H+;%#05%6f<=>=f=<f&3*4I4,B3I
6*B,*IA*&+I+;.I3.3I#%%4Ib,#0$#64(
a&3?+/(:0(K<=>=L0(<@(4("'B:>'C"/<'J$B1%0(>(]3#&,3837(!;&(<T/(<=>=/(B&%6(a&3?+(^1(
E35"&,#.'($##;'ffb&3?+%1+35"&,#.05%6f<=>=f=Xf+;.3.3I8+IN3"+I&,8*4&.f(
Q5Q,44*1/(]0(K<=>=L0(N"2'J/::$1,'6+),")')0$":')+'3$%%'0$B1%>(]3#&,3837(!;&(<T/(<=>=/(
B&%6(e%6;"#3&(G%&47'(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 6
!
! $##;'ffAAA05%6;"#3&A%&4705%6f+f*&#,543fU>SXY>Wf-3A`]"++,*1`?%#13#`#
! &,3+`#%`b,44`&,8*4(
!
! Q,3&3+/(_0(K<=>=L0(<@(4("'I'N"2'6+)'+,')*"'-103")>(]3#&,3837(!;&(<T/(<=>=/(B&%6(
! Q*4A*&3(@1#344H3153(:4%H'(
!
! $##;'ff6*4A*&3,1#0?4%H+;%#05%6f<=>=f=>f+;.3.3I13AI?%#I%1I6*&b3#0$#64(
! Q,3&3+/(_0(K<=>=L0(<@(4("'A+)'5!10)')2+9>'O+,B"0:1)$+,:'2$)*')*"'80"1)+0'+#'80$-"210">(
!
! ]3#&,3837(!;&(<T/(<=>=/(B&%6(Q*4A*&3(@1#344,H3153(:4%H'(
! $##;'ff6*4A*&3,1#0?4%H+;%#05%6f<=>=f=<f+;.3.3I?%#I;*&#I#A%I
!
! 5%183&+*#,%1+IA,#$0$#64(
! 66,/(c0(K<==UL0(P+0.!4>(]3#&,3837(B&%6(
!
! $##;'ffAAA0A%%76*1105%6f5%44*?%&*#,83f#%%4+f,173P0;$;fj%&79F(
! 9*N/(]0(K<=>=L0(K""@$,G'1,'4("'+,')*"'4Q4ALH'1,.'1'!+::$6%"'A+)'?10>(]3#&,3837(!;&(
!
! <T/(<=>=/(B&%6(M&317(Q,5&%(:4%H'($##;'ff?4%H0#&3176,5&%05%6fb33;,1HI*1I
! 3.3I%1I#$3I3.3?%#I*17I*I;%++,?43I?%#IA*&f(
!
! ]%++"6/(g0(K<===L0(!()*+,'!0+G01--$,G'P1,G/1G"';<+#)210"=>(]3#&,3837(B&%6(
! $##;'ffAAA0;.#$%10%&Hf(
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
]"++,1%8,5$/(Q0(KK>UUWLL0(!0+8"::'47@%+0"0';<+#)210"=>(]3#&,3837(B&%6(
$##;'ff#35$13#06,5&%+%B#05%6f31I"+f+.+,1#3&1*4+f??WUYYST0*+;P(
]"++,1%8,5$/(Q0/(h(e%H+A344/(:0(K>UUYL0(!0+8"::'R+,$)+0;<+#)210"=>(]3#&,3837(B&%6(
$##;'ff#35$13#06,5&%+%B#05%6f31I"+f+.+,1#3&1*4+f??WUYYXS0*+;P(
E$385$31b%/(E0(K<==UL0(H$-"')+'J"B$:$)'C"/:'F%-$G*)(>(]3#&,3837(!;&(<T/(<=>=/(B&%6(
M$&3*#FP;3&#+(:4H%'($##;'ff?4%H0#$&3*#3P;3&#05%6f<==Uf=Uf#,63I#%I&38,+,#I
N3"+I*46,H$#.0$#64(
Eb*;30(K<==XL0(S$83'<$)">(]3#&,3837(d3?(>/(<=>=/(B&%6(k173&+#*17,1H(G,17%A+(
E$3445%73'($##;'ffAAA0$,5b0%&Hf5%73f+b*;3f;*;3&+fA,1T<I+$3445%730;7B(
E#3A*&#/(_0(K<=>=L0(L@18*3$'P$,3'S$T183"0'H0+T1,'F,1%(:$:>(]3#&,3837(!;&(<T/(<=>=/(
B&%6(E35"&3A%&b+(:4%H'(
$##;'ffAAA0+35"&3A%&b+05%6f&3+3*&5$f#$&3*#+f%;*5$b,f(
M,*1G3,0(K<==WL0(J"G:*+)';<+#)210"=>(]3#&,3837(B&%6(
$##;'ff+%"&53B%&H3013#f;&%Z35#+f&3H+$%#f(
c"+5$"b/(^0(K<===L0(L%%(E6G';<+#)210"=>(]3#&,3837(B&%6($##;'ffAAA0%44.7?H073f(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 7
!
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 8
!
! (
!
!
! 10. Appendix
!
! 10.1. VirusTotal Results – ZeuS/ZBot sample:
!
E=%(L(31#&& .$3#(5=&& M/#%&N7A/%$&& I$#10%&
!
,B?L=,9).## $JZJ!JZ!## 8!5!J!8J8O## &NCJN'0O8[QX#
!
P%0\,HBTO## ZJ!J!J8## 8!5!J!8J8O## N'0BE96S,0]KH64J^55_7J/#
!
! P04'T'9## 7J8J5J5^8## 8!5!J!8J8O## EY]&CNJKH64J&XJ8#
! P04'FBPT\## 8J!JOJ^## 8!5!J!8J8O## E96S,0]N'0O8JKH64JD)0#
! P3,?4## $J7J5OZ5J!## 8!5!J!8J8O## N'0O8*A,1G,9)BD)0#
! PT`## aJ!J!J^O!## 8!5!J!8J8O## C/)=98J:b\c#
! d'4R);)0.)9## ^J8# 8!5!J!8J8O## E96S,0JC(FJKd64J2AQ#
! :PEBc='>I/),1## 5!# 8!5!J!8J8O## E96S,0C(FJKH64J,);%#
! :6-6.6## $!OZ# 8!5!J!8J8O## E96SN,9)JN'0O8JE96S,0C(FJKH64J`)0#
! R9N)H## ZJ!J5J58888## 8!5!J!8J8O## E96S,0J&96"FJ87$8#
! )C,;)## ^J!J5^J!## 8!5!J!8J8O## N'0O8J&NCKH64J&I#
! )E9=?4BT)4## OZJ8J^O8O## 8!5!J!8J8O## N'0O8]<,I)P1)94Jd[D)0)9'>#
! <B&964## $JZJ5J7Z## 8!5!J!8J88## B#
! <BC)>=9)## aJ!J5ZO^!J!## 8!5!J!8J8O## E96S,0JC(FJKd64J2AQ#
!
<694'0)4## $J!J5$J!## 8!5!J!8J85## NO8]&,>IPD)04JPO7<[49#
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
`R,4,## 5a# 8!5!J!8J8O## E96S,0JC(FJKd64J2AQ#
QI,9=?## EOJ5J5J7!J!## 8!5!J!8J8O## &NCJN'0O8#
X^P04'T'9=?## ^J5!Ja7!## 8!5!J!8J88## E96S,0JN'0O8JA,1G,9)J5#
X,?()9?IF## ^J!J!J58Z## 8!5!J!8J8O## E96S,0BC(FJN'0O8JKH64J,);%#
A>P;))## Za!!# 8!5!J!8J88## C(FBPD)04JHG#
A>P;))eP94)-'?## Za!!# 8!5!J!8J88## C(FBPD)04JHG#
A>P;))B`NB2.'4'60## _J7JZ## 8!5!J!8J8O## E96S,0J&CNJKH64J&XJ8#
A'>96?6;4## 5JZ$!_# 8!5!J!8J8O## &NC*N'0O8]KH64J&X#
+URO8## $7a!# 8!5!J!8J8O## N'0O8]C(FJKH64Jb<#
0&964)>4## 8!!aJ5J7J!## 8!5!J!8J8O## E96S,0]NO8JPD)04J^55_7JRb#
&,0.,## 5!J!J8J8## 8!5!J!8J88## E9S]C'06G,1JNNb#
&:E661?## ^J!JOJZ## 8!5!J!8J8O## E96S,0JKH64#
&9)3"## O# 8!5!J!8J8O## A).'=-#Y'?I#A,1G,9)#
Y'?'0D## 88JO$J!5J!O## 8!5!J!8J55## E96S,0JN'0O8J`)0)9'>JZ5<a5_82#
C6(%6?## $JZ!J!## 8!5!J!8J8O## A,1]<,I)PTBdE#
C=0H)14## Z_a$# 8!5!J!8J8O## E96S,0BC(FJN'0O8JKH64JD)0#
CF-,04)>## 8!!a5J8J!J$5## 8!5!J!8J8O## E96S,0JKH64#
E%)/,>I)9## _JZJ5J_J8!_## 8!5!J!8J8O## E96S,0]X9F(4'IJ>)"#
E9)0.A'>96## aJ58!J!J5!!$## 8!5!J!8J8O## EYUbfKdUEJCTY#
TdPO8## OJ58J58J8## 8!5!J!8J8O## E96S,0BC(FJN'0O8JKH64J,);%#

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 5
! ( 9
!
! T'Y6H64## 8!5!J8J8OJ85a7## 8!5!J!8J8O## C(FG,9)JKH64J`)0J^55_7#
! T'9=?d=?4)9## ZJ!J8^J!## 8!5!J!8J8O## E96S,0J&NCJKH64JgdT#
!
!
10.2. Zbot Network Communication:
! The code injected into svchost.exe is responsible for network communication
!
including downloading the configuration file. The configuration file is encrypted and may
!
! have some compressed strings. We are giving here, some details about the encryption and
! compression schemes used. Some of this information is mentioned in the blog entitled,
!
! “Time to Revisit Zeus Almighty” (Shevchenko, 2009). The following python code
! decrypts the configuration file. Note that this script works on the encryption scheme of
!
! ZBot versions where shared secrets keys are not used. Also please note that this code is
! provided with no support or guarantee of correctness.
!
!
! def decodeRecordData(recordDataEncoded):
recordDataDecoded = ''
! for i in range(0, len(recordDataEncoded)):
! byte = ord(recordDataEncoded[i])
! al = i&0xFF
! if al%2 == 0:
dl = (al + 5)&0xFF
! dl = (2*dl)&0xFF
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
else:
dl = (0xF9 - 2*al)&0xFF

decodedByte = (byte+dl)&0xFF
recordDataDecoded += str(chr(decodedByte))
return recordDataDecoded
(
The following python code gives the decompression algorithm identified as nrv2b.

def getBit(pos, recordDataEncoded, fourBytes, count):


#Get the bit at position count. If count == 0, reinitialize count and move to
#next decompression.
if count == 0:
count = 31
fourBytes = struct.unpack('<L', recordDataEncoded[pos:pos+4])[0]
print 'Read Four Bytes: 0x%.8X at Pos: %d'%(fourBytes, pos)
pos += 4
else:
count -= 1
bit = ((fourBytes >> count ) & 1)
return (bit, pos, fourBytes, count) (

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 0
!
! def secondDecode(recordDataEncoded):
recordDataDecoded = ''
! sPos = 0
! dPos = 0
! lastMOff = 1
shift = 0
! fourBytes = 0
!
! #Main Loop
! while True:
if sPos >= len(recordDataEncoded):
! return recordDataDecoded
!
! (gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,
! fourBytes, shift)
while(gb != 0):
! # While gb != 0, simply copy the code
! recordDataDecoded += recordDataEncoded[sPos]
! sPos += 1
if sPos > len(recordDataEncoded):
! 'Record Data Len Exceeded 1'
! return recordDataDecoded
! dPos += 1
! (gb, sPos, fourBytes, shift) = getBit(sPos,
recordDataEncoded, fourBytes, shift)
!
! #mOff calculation
! if sPos >= len(recordDataEncoded):
return recordDataDecoded
! (gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
fourBytes, shift)
mOff = 2+gb
if sPos >= len(recordDataEncoded):
return recordDataDecoded
(gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,
fourBytes, shift)
while(gb == 0):
if sPos >= len(recordDataEncoded):
return recordDataDecoded
(gb, sPos, fourBytes, shift) = getBit(sPos,\
recordDataEncoded, fourBytes, shift)

mOff = 2*mOff + gb
if sPos >= len(recordDataEncoded):
return recordDataDecoded
(gb, sPos, fourBytes, shift) = getBit(sPos,\
recordDataEncoded, fourBytes, shift)

if mOff == 2:
mOff = lastMOff
else:
mOff = (mOff - 3) * 256 +
ord(recordDataEncoded[sPos])
sPos += 1
if sPos > len(recordDataEncoded):
return recordDataDecoded

if int(mOff) == -1:
break;
else:
mOff += 1
)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6(
lastMOff = mOff (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 1
!
!
!
!
! #mLen calculation
if sPos >= len(recordDataEncoded):
! return recordDataDecoded
! (mLen, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
! fourBytes, shift)
! if sPos >= len(recordDataEncoded):
! return recordDataDecoded
! (gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
! fourBytes, shift)
! mLen = mLen*2 + gb
! if mLen == 0:
! mLen += 1
if sPos >= len(recordDataEncoded):
! return recordDataDecoded
! (gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
! fourBytes, shift)
!
mLen = 2*mLen + gb
! if sPos >= len(recordDataEncoded):
! return recordDataDecoded
! (gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
! fourBytes, shift)
! while (gb == 0):
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
if sPos >= len(recordDataEncoded):
return recordDataDecoded
(gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
fourBytes, shift)

mLen = 2*mLen + gb
(gb, sPos, fourBytes, shift) = getBit(sPos, recordDataEncoded,\
fourBytes, shift)

mLen += 2

mPos = dPos - mOff


if mPos < 0:
print 'mPos is negative'
return recordDataDecoded
if mPos > dPos:
return recordDataDecoded
#Copy uncompressed data
recordDataDecoded += recordDataDecoded[mPos]
mPos += 1
dPos += 1
while mLen > 0:
mLen -= 1
recordDataDecoded += recordDataDecoded[mPos]
dPos += 1
mPos += 1

return recordDataDecoded (
(
)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 2
!
Using the above algorithm for decryption, we found that the configuration file being
!
! downloaded by this Zbot sample had over 50 different URLs mostly for banking
!
institutions.
!
!
! 10.3. SpyEye Sample
! E=%(L(31#&& .$3#(5=&& M/#%&N7A/%$&& I$#10%&
!
,B?L=,9).## $JZJ!JZ!## 8!5!J!OJ8Z## E96S,0BC(FJN'0O8JC(F2F)?J.[P8#
!
P%0\,HBTO## ZJ!J!J8## 8!5!J!OJ8$## N'0BE96S,0]C(F)F)J58_$_$#
!
P04'T'9## 7J8J5J5a_## 8!5!J!OJ8$## EY]PD)04JLL?#
!
P04'FBPT\## 8J!JOJ^## 8!5!J!OJ8$## E96S,0]N'0O8JC(F2F)?JD)0#
!
! P3,?4## $J7J5OZ5J!## 8!5!J!OJ8$## N'0O8*C(FG,9)BD)0#
! P3,?4Z## ZJ!JOO8J!## 8!5!J!OJ8$## N'0O8*C(FG,9)BD)0#
! PT`## aJ!J!J^7^## 8!5!J!OJ8Z## `)0)9'>5_Jd<`Q#
! d'4R);)0.)9## ^J8# 8!5!J!OJ8Z## E96S,0J`)0)9'>JO5Za78^#
! :PEBc='>I/),1## 5!# 8!5!J!OJ8$## E96S,0C(FJC(F2F)?J.#
! :6-6.6## $O^O# 8!5!J!OJ8$## E96SN,9)JN'0O8JE96S,0C(FJPD)04JhP<K#
! R9N)H## ZJ!J5J58888## 8!5!J!OJ8Z## E96S,0JA=1R96(5J75Z#
! )C,;)## ^J!J5^J!## 8!5!J!OJ8$## N'0O8JEYPD)04JcL?#
! )E9=?4BT)4## OZJ8J^O7^## 8!5!J!OJ8Z## N'0O8]C(F)F)JP#
! <BC)>=9)## aJ!J5ZO^!J!## 8!5!J!OJ8Z## E96S,0BC(F*NO8]C(F)F)JP#
! <694'0)4## $J!J5$J!## 8!5!J!OJ8$## NO8]C(F2F)?JR[49#
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
`R,4,## 5a# 8!5!J!OJ8Z## E96S,0J`)0)9'>JO5Za78^#
QI,9=?## EOJ5J5J7!J!## 8!5!J!OJ8Z## E96S,0JN'0O8JC(F)F)#
b',0D-'0## 5OJ!Ja!!## 8!5!J!OJ8$## E96S,0]&'0>,3J.;F#
X^P04'T'9=?## ^J5!J5!!$## 8!5!J!OJ88## E96S,0BC(FJN'0O8JC(F2F)?J.#
X,?()9?IF## ^J!J!J58Z## 8!5!J!OJ8Z## E96S,0BC(FJN'0O8JC(F2F)?J.#
A>P;))## ZaO!# 8!5!J!OJ8$## d,>IR669BC(F)F)#
A>P;))eP94)-'?## ZaO!# 8!5!J!OJ8$## d,>IR669BC(F)F)#
A>P;))B`NB2.'4'60## _J7JZ## 8!5!J!OJ8$## E96S,0JPD)04JLL?#
A'>96?6;4## 5JZ_!Z# 8!5!J!OJ8$## E96S,0*N'0O8]C(F)F)#
+URO8## $a^8# 8!5!J!OJ8$## N'0O8]C(FJC(F2F)Jd#
+69-,0## _J!$J5!## 8!5!J!OJ8$## C(F)F)JP#
0&964)>4## 8!!aJ5J7J!## 8!5!J!OJ8$## E96S,0BC(F]NO8JC(F2F)?J58_$_$#
&,0.,## 5!J!J8J8## 8!5!J!OJ8$## C=?('>'6=?#;'1)#
&:E661?## ^J!JOJZ## 8!5!J!OJ8$## E96S,0JC(F)F)#
&9)3"## O# 8!5!J!OJ8Z## /'D%#Y'?I#C(FG,9)#
Y'?'0D## 88J$!J!OJ!5## 8!5!J!OJ8Z## E96S,0JN'0O8J`)0)9'>JZ5<aa!Z<#
C6(%6?## $JZ5J!## 8!5!J!OJ8$## A,1]C(F)F)BP#
C=0H)14## _!^8# 8!5!J!OJ8Z## E96S,0JN'0O8J`)0)9'>[dE#
CF-,04)>## 8!!a5J8J!J$5## 8!5!J!OJ8Z## E96S,0JC(F)F)#
E%)/,>I)9## _JZJ8J!J8$8## 8!5!J!OJ8$## E96S,0]C(FJC(F2F)?J.#

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 3
!
! E9)0.A'>96## aJ58!J!J5!!$## 8!5!J!OJ8$## EC&if2i2dUEJCAP#
! TdPO8## OJ58J58J8## 8!5!J!OJ8$## E96S,0BC(FJN'0O8JC(F2F)?J.#
! T'Y6H64## 8!5!JOJ8$J88$8## 8!5!J!OJ8$## E96S,0JN'0O8JC(F)F)J58_$_$#
! T'9=?d=?4)9## ZJ!J8^J!## 8!5!J!OJ8$## E96S,0C(FJC(F2F)?JdR#
!
!
! 10.4. Script to Map SpyEye Hash Value to Functions:
!
! The following script creates a hash table whose keys are the 4 Byte hash and the
! value is the name of the DLL export. It uses PEFile (Carrera, 2005) python package to
!
obtain the names of exports. Note that it uses the nameToHash function described in
!
! Section 4, Figure 31.
!
(
!
#!/usr/bin/python
! import os,sys
! sys.path.append('./pefile')
import pefile
! import NameToHash
! #CommonDLLs contains the following DLLs:
! #advapi32.dll kernel32.dll ntdll.dll oleaut32.dll
#shlwapi.dll user32.dll ws2_32.dll
! #imagehlp.dll msvcrt.dll ole32.dll
! #shell32.dll urlmon.dll wininet.dll

! DirPath = './CommonDLLs'
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
def listExportsInFile(inFileName):
pe = pefile.PE(inFileName)
expList = []
try:
exportsDir = pe.DIRECTORY_ENTRY_EXPORT.symbols
except:
exportsDir = None
if exportsDir:
for exp in exportsDir:
expList += [exp.name]
return expList

def hashAllExportsInCommonDLLs():
dllNames = os.listdir(DirPath)
funcDict = {}
for dll in dllNames:
dllFile = os.path.join(DirPath,dll)
exportList = listExportsInFile(dllFile)
for fName in exportList:
if fName:
hash = NameToHash.nameToHash(fName)
funcDict["%.8X"%hash] = (dll,fName)
return funcDict

if __name__ == '__main__': (
listAllExportsInCommonDLLs()
(
10.5. SpyEye Function calling Technique
(
1. Select Library Name based on argument given (Figure 65).

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 4
!
!
!
!
!
!
!
!
! !"#$%&'NI)'5,&7'('
!
! 2. Find base of Ntdll.dll. (Figure 66)
!
! 3. Find address of LdrLoadDll within Ntdll.dll. (Figure 66)
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'NN)'5,&7M':]D'
4. Load the library whose name was found in Step 1 using LdrLoadDll. (Figure
66)
5. Find the function name from the hash value as discussed before. (Figure 67)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 5
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'NR)'5,&7'I'
! 6. Find the offset of the function inside the loaded DLL.
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'NT)'5,&7'R'
(
7. Pass the DLL name and the function offset to a function that does the following
(Figure 68):
a. Open the DLL file using ntdll!NtOpenFile (Figure 69)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 6
!
!
!
!
!
!
!
!
!
!
!
!
!"#$%&'NV)'5,&7'RG'
!
!
! b. Create a new section using ntdll!NtCreateSection(Figure 70)
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

!"#$%&'RW)'5,&7M'RF^'R+'
(
c. Map the file into the newly created section using
ntdll!MapViewOfSection. Hence the DLL is mapped into a new section in
memory. (Figure 70)
d. Find the function address inside the new section from the offset passed.
Return this address. (Figure 71)

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 7
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
! !"#$%&'R()'5,&7'R2'
! 8. Now function at that address is called using the appropriate arguments. (Figure
! 72)
!
9. After the function call, the DLL is unmapped. (Figure 72)
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

(
!"#$%&'R:)'5,&7'T^'V'
(
(

10.6. SpyEye Dropped Binary Sample:


M/#%&
E=%(L(31#&& .$3#(5=&& N7A/%$&& I$#10%&
,B?L=,9).## $JZJ!JZ!## 8!5!J!$J5$## E96S,0BC(FJN'0O8JC(F2F)?[QX#
P%0\,HBTO## ZJ!J!J8## 8!5!J!$J5O## N'0BE96S,0]PD)04J5!$$$7JRX#

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 8
!
! P04'T'9## ^J5!J_J^_## 8!5!J!$J5$## EY]PD)04JLL?#
! P04'FBPT\## 8J!JOJ^## 8!5!J!$J5$## E96S,0]N'0O8JC(F2F)?JD)0#
! P=4%)04'=-## ZJ8J!JZ## 8!5!J!$J5$## NO8]C(F2F)?JPJD)0[21.69,.6#
! P3,?4## $J7J5OZ5J!## 8!5!J!$J5$## N'0O8*C(FG,9)BD)0#
! P3,?4Z## ZJ!JOO8J!## 8!5!J!$J5$## N'0O8*C(FG,9)BD)0#
! PT`## aJ!J!J^7^## 8!5!J!$J5$## `)0)9'>5_Jd/2&#
! d'4R);)0.)9## ^J8# 8!5!J!$J5$## E96S,0J`)0)9'>JO5!8^_O#
! :PEBc='>I/),1## 5!# 8!5!J!$J5$## B#
! :1,-PT## !Ja_J!JOBD'4## 8!5!J!$J5$## B#
! :6-6.6## $Za_# 8!5!J!$J5$## E96SN,9)JN'0O8JE96S,0C(FJC(F)F)JhP#
! R9N)H## ZJ!J8J!OO!!## 8!5!J!$J5$## E96S,0JR',1)9J55#
! )C,;)## ^J!J5^J!## 8!5!J!$J5$## N'0O8JEYPD)04JcL?#
!
)E9=?4BT)4## OZJ8J^$8Z## 8!5!J!$J5$## N'0O8]C(F2F)J/#
!
<B&964## $JZJ5J7Z## 8!5!J!$J5O## NO8]C(F2F)?JPJD)0[21.69,.6#
!
<BC)>=9)## aJ!J5ZO^!J!## 8!5!J!$J5$## E96S,0BC(F*NO8]C(F)F)JP#
!
! <694'0)4## $J!J5$J!## 8!5!J!$J58## NO8]C(F2F)?Jd[49#
! `R,4,## 5a# 8!5!J!$J5$## E96S,0J`)0)9'>JO5!8^_O#
! QI,9=?## EOJ5J5J7!J!## 8!5!J!$J5$## E96S,0BC(FJN'0O8JC(F2F)?#
! b',0D-'0## 5OJ!Ja!!## 8!5!J!$J5O## B#
! X,?()9?IF## ^J!J!J58Z## 8!5!J!$J5$## E96S,0JN'0O8JC(F2F)?JH#
! A>P;))## ZJ$!!J!J55Z7## 8!5!J!$J5$## d,>IR669BC(F)F)#
! A>P;))B`NB
2.'4'60## _J7JZ## 8!5!J!$J5$## E96S,0JPD)04JLL?#
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
A'>96?6;4## 5JZ_!Z# 8!5!J!$J5$## E96S,0*N'0O8]C(F)F)Jd#
+URO8## Z!87# 8!5!J!$J5$## N'0O8]C(FJC(F2F)Jd#
+69-,0## _J!$J55## 8!5!J!$J5$## B#
0&964)>4## 8!5!B!$B5$J!5## 8!5!J!$J5$## E96S,0]NO8JC(F2F)?J5!$$$7#
&,0.,## 5!J!J8J^## 8!5!J!$J5O## E9S]R6G016,.)9JARN#
&:E661?## ^J!JOJZ## 8!5!J!$J5$## E96S,0JC(F)F)#
&9)3"## O# 8!5!J!$J5$## A).'=-#Y'?I#A,1G,9)#
Y'?'0D## 88J$OJ!8J!$## 8!5!J!$J5$## B#
C6(%6?## $JZ8J!## 8!5!J!$J5$## A,1]C(F)F)BP#
C=0H)14## _5^Z# 8!5!J!$J5$## d,>I.669JC(F)F)#
CF-,04)>## 8!!a5J8J!J$5## 8!5!J!$J5$## E96S,0JC(F)F)#
E%)/,>I)9## _JZJ8J!J8_5## 8!5!J!$J5$## E96S,0]C(F2F)?JH#
E9)0.A'>96## aJ58!J!J5!!$## 8!5!J!$J5$## EC&if2i2dUEJP#
TdPO8## OJ58J58J$## 8!5!J!$J5$## E96S,0JN'0O8JC(F2F)?JH#
T'Y6H64## 8!5!J$J5$J88^_## 8!5!J!$J5$## E96S,0JN'0O8JC(F2F)?J5!$$$7#
T'9=?d=?4)9## ZJ!J8^J!## 8!5!J!$J5O## B#
(

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 6
! ( 9
!
! 10.7. Fake Server Script
! Given here is the fake http server written in python, which was used to respond to both
!
! ZeuS and SpyEye:
! from http.server import HTTPServer, SimpleHTTPRequestHandler
! import cgi
import base64
! import time
! import binascii
! from ( datetime import datetime
! (
PORT = 80
! (
! (
def printMessage(msg):
print( "[%s] %s"%(datetime.now(), msg) )
! (
! class( MRTRequestHandler(SimpleHTTPRequestHandler):
! (
def do_GET(self):
if self.path.find('x98x10.bin') > 0:
! ( printMessage('Got ZeuS ConfigFile request: '+self.path)
! ( resp = 'HTTP/1.1 200 OK\r\nServer: TSL_MRS/2.0.63 (Unix)'\
! ( + '\r\nDate: Tue, 26 Jan 2010 23:30:22 GMT\r\nContent-Type: text/plain;'
+ '\r\ncharset=UTF-8\r\nConnection: close'
! ( + '\r\nLast-Modified: Tue, 26 Jan 2010 23:30:22 GMT'\
! ( + '\r\nAccept-Ranges: bytes\r\nContent-Length: '
! ( f = open('c:\\FakeWebServer\\x98x10.bin','rb')
bytes = f.read()
! ( resp += '%s'%len(bytes)
! ( resp += '\r\n\r\n'
( "#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!
toSend = binascii.a2b_qp(resp)+bytes
printMessage('Sending Configuration file: '+self.path)
( self.wfile.write(toSend)
( elif self.path.find('bt_version_checker.php') > 0:
( printMessage('Got SpyEye version_checker Request: '+self.path)
resp = 'HTTP/1.1 200 OK\r\nServer: Apache/2.2.9'\
( + '\r\nVary: Accept-Encoding\r\nContent-Type: text/html\r\n'
( dataToSend = ''
( resp += 'Content-Length: %s\r\n\r\n'%(len(dataToSend))
resp += dataToSend
( toSend = binascii.a2b_qp(resp)
( printMessage('Sending a 200OK Response: ')
( self.wfile.write(toSend)
else:
( SimpleHTTPRequestHandler.do_GET(self)
( return
(
def do_POST(self):
( if self.path.find('websitechk.php') > 0:
( printMessage('Got SpyEye Website Check')
( elif self.path.find('s.php') > 0:
printMessage('Got ZBot POST Request')
( else:
( printMessage('Got Unkonwn Request: %s'%self.path)
( printMessage('Sending 200OK Response')
fullResp = 'HTTP/1.1 200 OK\r\nDate: Mon, 15 Feb 2010 18:56:24 GMT'
+'\r\nServer: Apache/2\r\nX-Powered-By: PHP/5.2.12\r\nHall: OK'\
+'\r\nVary: Accept-Encoding,User-Agent\r\nContent-Length: 0\r\n'\
+'Connection: close\r\nContent-Type: text/html\r\n\r\n'
toSend = binascii.a2b_qp(fullResp)
self.wfile.write(toSend)
return

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!
!
!
! Clash of the Titans: ZeuS v SpyEye 7
! ( 0
!
! (
def main():
global PORT
! server_address = ('', PORT)
! httpd = HTTPServer(server_address, MRTRequestHandler)
httpd.serve_forever()
!
! if __name__ == '__main__':
! main()(
! (
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
!
"#$!%&'(#)*)&'+!,!-./0!.-12!1.03!0045!.567!5895!.467!:;83!-/;0!383;!

)*&+$,#(-*..*&/($*&+$,#01*..*&2#34"+05%6( (
© 2010 The SANS Institute Author retains full rights.!

Das könnte Ihnen auch gefallen