All Your Docs Are Belong To Us
› reversing an av engine to compose signatures capable of detecting classified documents
01/01/2018
love these blog posts? support my tools & writing on patreon! Mahalo :)
In this blog post we'll detail how to reverse, then 'extend' a popular anti-virus engine. With the creation of a new anti-virus signature, classified documents will be automatically detected:
Background
In the battle against malicious code, anti-virus products are a staple. Somewhat ironically though, it is interesting to note that these products share many characteristics with the advanced cyber-espionage collection implants that they seek to detect. Characteristics such as persistence, extensibility, advanced scanning, collection, and self-defense mechanisms:
persistence
Anti-virus products are often installed in a manner which ensures they are always running, often with background components hidden from the casual user.
scanning
Anti-virus products, by design, seek to observe and scan all files, including non-executable files such as documents.
automatic updates
Anti-virus products often automatically updated various components such signatures, which extends their capabilities in a nontransparent manner.
upload (exfiltration) of files
Anti-virus products may upload suspicious or flagged files for further analysis.
self defense & anti-analysis
Anti-virus products often implement advanced self-defense mechanisms to thwart reverse-engineering efforts.
Anti-virus signatures are particularly interesting and will be the main focus of the blog. Such signatures may be:
- updated daily
- encrypted both in transit and on-disk
- deployed to only certain regions, or specific clients
- separate from the source code of the anti-virus product
...in other words, insight into such signatures (which influence the logic of the anti-virus core) is a rather complex task!
Could a (subverted?) anti-product be the perfect cyber-espionage collection tool?
Recently anti-virus software written by the popular cybersecurity company Kaspersky, has been blamed for both detecting and exfiltrating classified NSA documents to Russia. Whoa! Of course I'm not going to comment on any of this 🤐 - but from a technical point of view I was intrigued! Specifically I wanted to see if I could 'add' such a signature to Kaspersky (without modifying any executable code) so the anti-virus engine would automatically detect classified documents and mark them for collection.
My goal was simple: reverse Kaspersky's product to gain the knowledge necessary to create a signature which would flag classified documents, presumably for exfiltration.
Please avoid jumping to the conclusion that this something Kaspersky, or any other anti-virus company actually did!
Understanding Kaspersky
The target for this analysis was the latest version of Kaspersky Internet Security for macOS. Once downloaded, it installs various components such as various kernel extensions, a daemon, and various user components:
$ ps aux | grep -i kaspersky
root 975 /Library/Application Support/Kaspersky Lab/KAV/Binaries/kav -r -bl
user 1599 /Applications/Kaspersky Anti-Virus For Mac.app/Contents/MacOS/kav_app
user 1116 /Library/Application Support/Kaspersky Lab/KAV/Applications/Kaspersky Anti-Virus Agent.app/Contents/MacOS/kav_agent
A cursory triage identified the daemon, (/Library/Application Support/Kaspersky Lab/KAV/Binaries/kav) as containing the code responsible for core of the anti-virus scanning and detection logic. As such, it was the target of the reversing session.
Modern anti-virus products are incredibly complex pieces of software and Kaspersky is likely one of the most complex. Thus, merely gaining a reasonable understanding of its signatures and scanning logic is a challenging task. Luckily research by the godlike 29A VXer z0mbie and books such such as the "Antivirus Hacker's Handbook" (Joxean Koret) provide insight into this process. This blog post is indebted to these resources!
Though the installer ships with built-in signatures, as is the case with any anti-virus program, Kaspersky's anti-virus engine regularly checks for, and automatically installs any new signatures:
Let's take a closer look at this process.
When new signatures are available, they are downloaded by the kav daemon from Kaspersky's update servers (i.e. dnl-03.geo.kaspersky.com):
Not too surprising the signatures appear to be compressed and encrypted in a proprietary manner.
Once received, the signatures are first stored in the /private/tmp/temporaryFolder/updates/kdb/i386/ folder, before being installed:
# fs_usage -w -f filesystem
05:51:32.804433 stat64 /private/tmp/temporaryFolder/updates/kdb/i386/base010c.kdc 0.000003 kav.11742
05:51:32.804440 open F=80 (R_____) /private/tmp/temporaryFolder/updates/kdb/i386/base010c.kdc
# tail -f /Library/Logs/Kaspersky\ Lab/kav_daemon_2017-11-01-091336_pid_02464.log
05:53:01.704 13365 INF updater [updater_facade_ai.cpp:345] Publishing journal event with code: 1408419436, core code: 107, defaultLocalization: File updated, param1: /Library/Application Support/Kaspersky Lab/KAV/Bases/KLAVA/base011b.kdc, param2:
05:53:02.277 11764 INF bl [ReportsWriter] sqlite query processed: 'insert into "UpdaterFileUpdatedEvent" values (6159,0,'/Library/Application Support/Kaspersky Lab/KAV/Bases/KLAVA/base011b.kdc',13);'
05:53:02.277 11764 INF bl [ReportsWriter] sqlite query processed: 'insert into "UpdaterFileUpdatedEvent" values (6160,0,'/Library/Application Support/Kaspersky Lab/KAV/Bases/KLAVA/base011c.kdc',13);'
# hexdump -C /private/tmp/temporaryFolder/updates/kdb/i386/base010c.kdc
00000000 55 50 44 53 cc 65 02 00 00 00 02 00 1f 8b 08 00 |UPDS.e..........|
00000010 00 00 00 00 00 0b 74 9d 07 d8 db d4 f9 f6 83 1d |......t.........|
00000020 c8 09 a3 ec b4 10 66 28 ab ac 24 8c b0 21 83 0c |......f(..$..!..|
00000030 32 08 49 08 10 a6 24 cb b6 3c 24 db f2 26 6c 08 |2.I...$..<$..&l.|
00000040 7b af b0 cb 86 b2 09 1b ca 0a a3 94 51 f6 0a a5 |{...........Q...|
00000050 ec b2 f7 28 04 c8 f7 bb e5 a4 7f 4e bf 8b 5c 97 |...(.......N..\.|
00000060 6e 59 ef 6d eb 3c 92 ce 39 cf 3c ca f8 51 23 87 |nY.m.<..9.<..Q#.|
00000070 f4 e9 b3 64 9f 5f ff db 80 83 cb fd 54 b2 1d b7 |...d._......T...|
While the daemon is running, it appears that these signatures are stored in the kavbase_00000000 cache file. For example, here we find the EICAR (test) signature X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*h:
# grep -r EICAR-STANDARD-ANTIVIRUS-TEST /Library/Application\ Support/Kaspersky\ Lab/
Binary file /Library/Application Support/Kaspersky Lab//KAV/Bases/Cache/kavbase_00000000 matches
# strings -a /Library/Application Support/Kaspersky Lab//KAV/Bases/Cache/kavbase_00000000
..
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*h
Via the lsof command we can confirm that the Kaspersky daemon has this file (exclusivley?) open:
# lsof -p 508 | grep kavbase_00000000
kav 975 root /Library/Application Support/Kaspersky Lab/KAV/Bases/Cache/kavbase_00000000
kav 975 root /Library/Application Support/Kaspersky Lab/KAV/Bases/Cache/kavbase_00000000.lck_00000002
Though in the past researchers (such as z0mbie), have written parsers to decrypt and decompress the proprietary file format of Kaspersky's signatures, these tools are Windows only and at this point, likely dated. And yes, while I may have been able to port and update these tools, I decided to take a simpler route and interact with the signatures while in memory. Though this approach is not persistent, it neatly bypasses the need to understand the complex proprietary on-disk file format of Kaspersky's signatures...yet as we'll see, still allows us to create a signature that will detect classified documents.
Recall that our goal is compose a signature that is able to detect classified documents. So far we know that encrypted signatures are downloaded from Kaspersky's servers, installed, then used by the the Kaspersky deamon, kav. We can easily (and passively) confirm kav's duties by simply creating a text file, adding the EICAR (test) signature, then saving or closing the file (test.txt):
# fs_usage -w -f filesystem
07:07:13.240475 open F=83 (R_____) /Users/user/Documents/test.txt kav.4343
07:07:13.242416 read F=83 B=0x44 kav.4343
07:07:17.597921 unlink /Users/user/Documents/test.txt kav.4343
Easy to see kav opens the document, reads in the entire file (0x44 bytes), scans these bytes and upon detection, deletes it.
Working on another document (dontScanMe.rtf) illustrates that when it's modified, Kaspersky appears to open it and read in its contents (presumably to scan it for malicious content):
# fs_usage -w -f filesystem
09:21:42.208362 open F=82 (R_____) /Users/user/Desktop/dontScanMe.rtf kav.4343
09:25:00.937012 lseek F=82 O=0x00000000 kav.4343
09:25:00.937032 read F=82 B=0x15d kav.4343
Besides confirming that kav is indeed the component that performs the scanning, this experiment confirms that Kaspersky is already actively scanning (all) documents...for patterns.
Of course, this is what anti-virus products do: they scan files for (malicious) patterns. Logically this includes documents which can often contain exploits or malicious code. Thus, the fact that Kaspersky is scanning documents should not be seen as suspicious nor surprising at all! However, as the anti-virus engine is already scanning all documents, this means we (or anybody else!) should be able to craft a signature that can detect documents with classification markers.
While early engines scanned for simple patterns, modern anti-virus products are far more intelligent. As described by Joxean in his "Antivirus Hacker's Handbook" book, Kaspersky's scanning logic is rather complex. Specifically, it appears that detection signatures may actually be composed of both simple patterns and executable code (i.e. a detection routine). This allows the anti-virus product to contain far more powerful and complex detection logic that clearly blurs the traditional definition of a signature. 'Executable' signatures that may be pushed down to a client need to be dynamically linked into the anti-virus core. Koret notes; "after being decrypted and decompressed, these files are linked together, and the newly generated binary forms the new core, with all of the plug-ins statically linked" (pp 58). Yes this means Kaspersky has implemented their own full-featured loader/linker!
If you thought nation-state malware was the only code that has the ability to download encrypted payloads from a remote server and execute them in memory; well 😜 . However, there is a good technical reason for an advanced anti-virus product such as Kaspersky to utilize such functionality. Besides protecting its signatures from malware authors who would seek to bypass them, this also "offers low memory usage and faster start-up" (pp 58).
For analysis purposes, let's poke around kav's memory to find these dynamically loaded in-memory executable signatures. Due to the fact that this code is dynamically loaded and linked in, it likely won't show up when we enumerate memory regions in a debugger using a command such as 'image dump sections':
(lldb) image dump sections
Dumping sections for 301 modules.
Sections for '/Library/Application Support/Kaspersky Lab/KAV/Binaries/kav' (i386):
Load Address Perm Section Name
--------------------------------------- ---- ----------------------------
[0x0000000000000000-0x0000000000001000)* --- kav.__PAGEZERO
[0x000000000008e000-0x000000000039a000) r-x kav.__TEXT
[0x0000000000092500-0x000000000031c620) r-x kav.__TEXT.__text
...
However, using tool such as vmmap should reveal an executable section of memory that isn't listed in the debugger's list of module sections. And, it does: an 11MB chunk of memory at 0x12824000:
# vmmap kav
Process: kav [975]
Path: /Library/Application Support/Kaspersky Lab/KAV/Binaries/kav
Load Address: 0x8e000
Identifier: kav
Version: ???
Code Type: X86
OS Version: Mac OS X 10.13 (17A365)
----
Virtual Memory Map of process 975 (kav)
Output report format: 2.4 -- 32-bit process
VM page size: 4096 bytes
==== Non-writable regions for process 975
...
VM_ALLOCATE 0x12824000-0x13379000 [11.3M 7300K 7300K 4304K] r-x/rwx SM=PRV
In a debugger, we can dump this memory via the 'memory read' command (note the '-binary' flag):
(lldb) memory read --force --binary --outfile /tmp/signatures.bin 0x12824000 0x13379000
11882496 bytes written to '/tmp/signatures.bin'
Opening the dumped binary data in a disassembler (and setting it's base address to 0x12824000) reveals signature-related strings and binary code:
At this point we have a decent of understanding of Kaspersky's signatures and their interactions with the anti-virus engine....well, at least enough of an understanding to compose a signature that will detect classified documents!
Detecting Classifed Documents
Anti-virus engines are designed to automatically scan files (including documents!) for malicious patterns. As we've identified the in-memory location of the unencrypted signatures and detection routines for Kaspersky, constructing a signature to detect classified documents shouldn't be too hard. Of course if an anti-virus company wanted to (or was forced to) they'd simply deploy a new signature likely to select clients (targets), in order to persistently detect such documents. However here, as our goal is simply to illustrate that detecting classified documents is feasible from a technically point of view - we'll simply subvert an existing signature in memory. This 'new' signature will cause the anti-virus engine to automatically flag documents containing classification markers.
In the "Antivirus Hacker's Handbook" Joxean discusses bypassing a Kaspersky detection signature, designed to detect documents containing malicious code that exploits CVE-2010-3333. As this flaw is Microsoft-specific, it's a good target for us to subvert for our own purposes!
Looking thru the signature detection routines we dumped from memory, we find the function that implements this signature logic at address 0x13071230:
As noted by Joxean, this detection routine begins by checking that the document being scanned starts with a 'rich text format' (RTF) header, "{\rt" and is at least 0x5d00 bytes in size. The following pseudo code illustrates these initial checks:
//esi is an 'item object'
// +0 points to the start of the document being scanned
// +0xdc14 contains the length of the document
if ((*esi != '{\rt') || (*(esi + 0xdc14) <= 0x5d00))
{
//bail
}
Following this, the detection code reads chunks of data from within the document and then scans for various strings such as "dplineco", "{\sp2{\sn1 pF", and "ments}", within those chunks. If these are all found within the document, the function returns 0x1 indicating that according the signature detection routine, the document is malicious.
To see this in action let's scan a malicious document containing an exploit for CVE-2010-3333 (hash: deac10f97dd061780b186160c0be863a1ae00579). But first, we set a breakpoint at the start of the detection routine (address: 0x13071230):
(lldb) b 0x13071230
Breakpoint 1: address = 0x13071230
* thread #131, stop reason = breakpoint 1.1
frame #0: 0x13071230
-> 0x13071230: pushl %ebp
0x13071231: movl %esp, %ebp
0x13071233: subl $0x20, %esp
0x13071236: movl 0x12828164, %eax
Target 0: (kav) stopped.
During the scan of the document the breakpoint on the signature detection routine triggers! Here, we can dump the argument it takes (in $esp+4), which is a pointer to an 'item object' containing information about the document that is being scanned. Specifically we can see at start of this object are the bytes in the document ("{\rtxa{\..."), while at offset 0xdc14 is the document's size (0x00006e1e):
(lldb) x/x $esp+4
0xb11c5f44: 0x79f6041c
(lldb) x/s 0x79f6041c
0x79f6041c: "{\rtxa{\ansi{\shp{
(lldb) x/x 0x79f6041c+0xdc14
0x79f6e030: 0x00006e1e
We can step through the signature detection function to confirm all the checks 'pass' - meaning the document will be flagged as malicious for CVE-2010-3333.
First is the check that the document starts with "{\rt" (or 0x74725c7b):
-> 0x13071244: cmpl $0x74725c7b, (%esi)
0x1307124a: pushl %edi
0x1307124b: jne notMalicious
(lldb) x/x $esi
0x79f6041c: 0x74725c7b
Then the check to ensure the size of the document is at least 0x5d00:
-> 0x13071251: cmpl $0x5d00, 0xdc14(%esi)
0x1307125b: jb notMalicious
(lldb) x/x $esi+0xdc14
0x79f6e030: 0x00006e1e
As the file being scanned is an RTF document with a size greater or equal to 0x5d00, the code continues by checking for the string "dplineco" near the footer of the document. It does this by invoking the function at 0x129fcc70, which scans a chunk of bytes for a string:
Breaking at 0x1307128b on the call to 0x129fcc70 and dumping the arguments shows the string to find ("dplineco") as well as the bytes to search in (necor0\dplinecog0\dplinecob0}}}}):
(lldb) x/4x $esp
0xb11c5f00: 0x79f6041c 0xb11c5f2c 0x00000008 0x79f617fc
(lldb) x/s 0xb11c5f2c
0xb11c5f2c: "dplineco"
(lldb) x/s 0x79f617fc
0x79f617fc: "necor0\dplinecog0\dplinecob0}}}}"
As there is a match, the signature check continues on checking for the presence of "{\sp2{\sn1 pF", and "ments}", again by invoking the function at 0x129fcc70:
* thread #111, stop reason = breakpoint 3.1
-> 0x129fcc70: push ebp
0x129fcc71: mov ebp, esp
0x129fcc73: sub esp, 0x10c
0x129fcc79: mov eax, dword ptr [0x12828164]
Target 0: (kav) stopped.
(lldb) x/5x $esp
0xb11c5efc: 0x13071314 0x79f6041c 0xb11c5f1c 0x0000000d
0xb11c5f0c: 0x79f6181c
(lldb) x/s 0xb11c5f1c
0xb11c5f1c: "{\sp2{\sn1 pF"
(lldb) x/s 0x79f6181c
0x79f6181c: "ture1\levelold0\levelprev1\levelprevspace1\...{\sp2{\sn1 pF}...
* thread #111, stop reason = breakpoint 3.1
-> 0x129fcc70: push ebp
0x129fcc71: mov ebp, esp
0x129fcc73: sub esp, 0x10c
0x129fcc79: mov eax, dword ptr [0x12828164]
(lldb) x/5x $esp
0xb11c5efc: 0x1307132d 0x79f6041c 0xb11c5f2c 0x00000006
0xb11c5f0c: 0x79f6181c
(lldb) x/s 0xb11c5f2c
0xb11c5f2c: "ments}"
(lldb) x/s 0x79f6181c
0x79f6181c: "ture1\levelold0\levelprev1\levelprevspace1\...ments}...
Since the document we're scanning passes all the checks (e.g. size >= 0x5d00) and matches on all the signatures components the signature detection routine returns 0x1, which indicates the document appears to be malicious.
isMalicious:
1307134c mov eax, 0x1
...
13071357 mov esp, ebp
13071359 pop ebp
1307135a ret
In the Kaspersky UI, we can see the document has indeed been flagged and quarantined:
With a comprehensive understanding of this signature detection routine - now let's subvert it to instead automatically detect classified documents! 😅
Documents that are classified by the US government contain classification markings. For example top secret documents that contain "sensitive compartmented information" will be marked TS/SCI. We'll construct a Kaspersky detection signature for such documents by subverting the aforementioned CVE-2010-3333 signature. (Obviously if an anti-virus company wanted to detect such documents they'd create a new signature - but here, we're taking the easy route!). Specifically we'll simply modify the search strings (e.g. "ments") to match for classification markers such as "TS/SCI" in documents.
I wanted to compose signature to detect classified documents without modifying the executable code of the the AV-product (either on-disk, or in-memory).
Why?
-
First, if one is patching the executable code of any program, this is changing the fundamental logic of the product which IMHO somewhat invalidates the point of this exercise. Also, by avoiding modifications to the executable code of the product, we can illustrate that even if the source code (which of course is compiled into the executable code) of an anti-virus product is available for auditing, this in reality does nothing to alleviate concerns that the product (via signatures) could be used for malicious purposes.
-
However, this means that in this specific case, our signature to detect classified signature will initially be somewhat scoped, based on the constraints enforced in the executable code of the signature we are choosing to subvert (as Kaspersky apparently supports signatures that contain both executable code as well as matching patterns). For example it will be limited to RTF documents of size >= 0x5d00. Again, note that an AV company that wanted to (or was force to) deploy an actual signature to detect and exfiltrate any and all classified documents would of course not be limited to these self-imposed constraints).
-
Note that at the end of this post (once we already successfully created a non-executable detection signature), for completeness we illustrate the creation of a more powerful signature that depends on modifications of the signature detection's executable code (without touching the anti-virus engine's core code).
Modifying Kaspersky's CVE-2010-3333 signature to instead detect and quarantine classified documents is as simply as modifying the matching patterns in memory...for example, changing "ments" to "TS/SCI". This can either be done either via a debugger (memory write 0x130a4d80 0x54 0x53 0x2f 0x53 0x43 0x49) or by an external process that modifies the memory of the kav daemon. We'll illustrate the latter, as it doesn't require a debugging session and thus can be executed programmatically (and can also account for the fact that address where the signature detection routine is found is dynamic).
To modify the memory of a remote process one can invoke the mach_vm_write() API. As it's name suggest this will write some number of bytes at a specified offset into a process.
Apple provides a function definition, though no further details:
kern_return_t mach_vm_write(vm_map_t target_task, mach_vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt);
In order to invoke this API, one has to be root and have access to the target (remote) process's task. Obtain such access by invoking the task_for_pid() method.
The following code (based on @osxreverser's readmem project) illustrates how to utilize these APIs in order to write arbitrary bytes into the memory of a remote process:
//write some bytes into a remote process
write_memory(pid_t pid, mach_vm_address_t address, vm_offset_t bytes, mach_msg_type_number_t size)
{
//task port
vm_map_t port = 0;
//get task for remote process
task_for_pid(mach_task_self(), pid, &port));
//suspend
task_suspend(port);
//write write write!
// assumes that memory is writable!
mach_vm_write(port, address, bytes, size);
//resume
task_resume(port);
}
By means of this code we can now programmatically change the signature match patterns in the kav daemon process ...such as "ments}" at memory 0x130a4d80. To detect top secret documents that contain sensitive compartmented information we change the memory values of the signature match pattern to "TS/SCI". Re-reading the remote memory either via a debugger or the mach_vm_read() API confirms it's been changed:
(lldb) x/s 0x130a4d80
0x130a4d80: "TS/SCI"
...now Kaspersky should automatically flag and quarantine any documents containing this classification marker!
With our signatures added to Kaspersky, it's time to test!
Winnie the Pooh is a popular childhood book which, AFAIK, is not classified! However if we add the "TS/SCI" classification marker to it, when this change is written out to the file-system (via an auto-save, a manual save, or a document close), the document will be scanned and the signature in Kaspersky should now trigger and the document should be flagged:
Ok, not a whole lot of surprise that this worked - but still, neat to confirm that an anti-virus product can be trivially, yet surreptitiously used to detect classified documents!
Though this signature works, we noted that it is slightly "constrained" by the executable code of the signature detection function. For example, as the code first checks the document is at least 0x5d00 bytes, smaller classified documents won't be matched.
Of course there is nothing stopping us from improving this signature by modifying the executable code of the signature detection function. As we already illustrated we could create a signature without modifying any executable code, let's jump into modifying executable instructions.
As Kaspersky appears to distribute signatures that contain executable code (i.e. self-contained signature detection routines), which are dynamically linked into the the core anti-virus engine at runtime, we'll still constrain ourselves by only patching such code.
That is to say, we won't touch the anti-virus engine!
Patching the executable code of the existing signature detection routine to extend it, (e.g. to detect documents of any size that contain classification markers anywhere in the file), is fairly straightforward.
First, we can patch the code responsible for the 'file check' comparison at 0x13071251 (cmp dword [esi+0xdc14], 0x5d00). We'll change the code so it accepts any file over zero bytes in size:
;scan any file over 0 bytes
;cmp file size, now with 0
cmp dword [esi+0xdc14], 0x0
;unlikely to have a negative sized file
;so this jump won't be taken ;)
jb notMalicious
Similar one- or two-byte patches of this signature detection routine instruct the anti-virus engine to search for classification markers anywhere in the file (or at the start).
With this new signature even basic documents containing classification indicators are automatically flagged and quarantined (that is to say, 'deleted' from their original location and moved into a 'quarantined' location):
Collection?
Now what about exfiltration or collection? As previously mentioned, anti-virus companies often collect (upload) suspicious, flagged, or quarantined files in order to perform analysis 'in the cloud.' This of course allows them to perform more comprehensive or computationally-intensive analysis (vs. on the user's computer), collect threat intelligence, and in general improve the detection capabilities of their products.
Kaspersky refers to one of their public collection capabilities as "Kaspersky Security Network" (KSN) which (as they note): "allows Kaspersky Lab quick collecting of data concerning new threats and developing methods to protect computers from new threats." It is unclear if flagged documents would be automatically submitted for further analysis (though in the KSN docs they state, "The Kaspersky Security Network service may process and submit whole files, included objects detected through malicious links which might be used by criminals to harm your computer and/or their parts, to Kaspersky Lab for additional examination."). Moreover Kaspersky specifically notes in a company blog post that files detected as malicious may be uploaded, stating "the archive itself was detected as malicious and submitted to Kaspersky Lab for analysis, where it was processed by one of the analysts."
Due to time constraints I did not reverse-engineer or analyze the opt-out collection capabilities of Kaspersky. Moreover, as I didn't want to interact with their backend systems for a variety of reasons 🤐 I disabled network connections (in the analysis VM) to ensure that documents flagged by the new signature (i.e. Winnie the Pooh) under no circumstances would be submitted to Russia!
Of course, I am confident without a doubt that any anti-virus product with collection capabilities could arbitrarily collect (exfiltrate) files flagged by their product. However it's worth stating again, that this capability is designed to support legitimate functionality of the product!
Conclusion
In this blog post we illustrated how an anti-virus product could trivially be utilized to detect classified documents via signatures. I want to reiterate that this does not imply that any anti-virus company would ever do this! To me, it just seemed like a fun reversing exercise!
However, hopefully I've illustrated that any anti-virus product is only one signature away from being the absolute perfect cyber-espionage collection tool! And as their signatures are encrypted, (may be) tactically deployed, are automatically installed, contain executable code, and are generic decoupled from the source-code of anti-virus product, think very very long and hard about who you trust!
To end this writeup, it's interesting that in a recent blog post Kaspersky discusses this scenario, pointing out that their signature creation process would be difficult to secretly subvert or influence via "external attempts" (for example to detect/collect classified documents) :
However, a malicious or willing insider within any anti-virus company, who could tactically deployed such a signature, would likely remain undetected. And of course, in a hypothetical scenario; any anti-virus company that is coerced to, or is willing to work with a larger entity (such as a government) would equally be able to stealthily leverage their product to detect and exfiltrate any files of interest.
Sometimes the line between what is good and evil, comes down to a single signature...
love these blog posts & tools? you can support them via patreon! Mahalo :)