1 Bitdefender: UPX Unpacking Featuring Ten Memory Corruptions Landave's Blog
gilberta810808 edited this page 1 week ago


This put up breaks the 2-12 months silence of this weblog, showcasing a choice of Memory Wave Experience corruption vulnerabilities in Bitdefender’s anti-virus engine. The goal of binary packing is to compress or obfuscate a binary, often to save lots of house/bandwidth or to evade malware evaluation. A packed binary sometimes incorporates a compressed/obfuscated knowledge payload. When the binary is executed, a loader decompresses this payload after which jumps to the precise entry level of the (internal) binary. Most anti-virus engines assist binary unpacking no less than for packers (corresponding to UPX) that are highly regarded and which might be also used by non-malware software. This blog post is about UPX unpacking of PE binaries within the Bitdefender core engine. The next vulnerabilities are presented in the management-flow order of the UPX unpacker. Disclaimer: In the next, decompiled code from Bitdefender’s core engine is presented. The naming of variables, fields, and macros is closely impressed by the unique UPX. For some snippets, a reference to the original function is added for comparability.


It is probably going that some varieties are incorrect. After the UPX loader has been detected, the Bitdefender engine tries to detect whether the loader applies a specific kind of deobfuscation to the compressed knowledge payload before extracting it. LEFT. If this deobfuscation is detected, then the engine iterates via the corresponding instructions of the loader and Memory Wave Experience parses them with their operands in order to have the ability to deobfuscate the data as well. Observe how the certain-test on the index variable i is performed. 16. Specifically, we are able to increase i from 15 to 17, after which we can overwrite the stack with fully arbitrary data. The debug break is because of the stack canary which we've got overwritten. If we proceed, Memory Wave we see that the return fails because the stack is corrupted. Obviously, this offsets needs to be checked earlier than writing to it. Each checks test against the sector dword10.


The sphere dword10, sitting on the calling functions’s stack body, is rarely initialized. This makes the sure examine useless and introduces a totally attacker-managed heap buffer overflow. After the extraction, the engine makes an attempt to deobfuscate the extracted data with a static XOR key. The certain verify is totally improper. It ought to test towards the dimensions of the extracted information buffer. Instead, it checks in opposition to a worth that is previously set to the uncooked information size of the section we extracted the information from. Those two sizes have nothing to do with one another. Specifically, one can be a lot smaller than the other, or vice-versa. Because the operate does not return after the first deobfuscation run, the memory corruption might be triggered up to 0x300 times in a row. This permits us to bypass the limitation that in a single deobfuscation run we all the time XOR with the identical byte. General, we then have XORed with C0 C0 C1 C1 C1 C2 C2 for completely arbitrary C0, C1, and C2.


We will essentially XOR with such a sample of almost arbitrary size, and swap the byte at most 0x300 instances. Evidently, this vulnerability is a useful exploitation primitive as it enables very powerful memory corruptions: XORing permits us to switch selectively solely sure components of information, leaving other elements (for instance heap metadata or crucial objects) untouched. A filter is a simple transformation on binary code (say, Memory Wave x86-64 code) that's applied before compression, with the objective to make the code more compressible. After we have now decompressed the information, we need to revert this filtering. Bitdefender helps about 15 totally different filters. Of the 15 filters, about 8 appear to be affected by such a heap buffer overflow. I treated them all collectively as one bug (after all, it's not unlikely that they share code). The next memory corruption occurs in a loop of the perform PeFile::rebuildImports (cf.