Bitdefender: UPX Unpacking Featuring Ten Memory Corruptions - Landave's Weblog
작성자 정보
- Maynard Magrath 작성
- 작성일
본문
This publish breaks the 2-year silence of this weblog, showcasing a collection of memory corruption vulnerabilities in Bitdefender’s anti-virus engine. The aim of binary packing is to compress or obfuscate a binary, usually to avoid wasting space/bandwidth or to evade malware analysis. A packed binary usually contains a compressed/obfuscated data payload. When the binary is executed, a loader decompresses this payload after which jumps to the precise entry point of the (internal) binary. Most anti-virus engines assist binary unpacking a minimum of for packers (corresponding to UPX) that are very popular and which can be additionally used by non-malware software. This weblog submit is about UPX unpacking of PE binaries within the Bitdefender core engine. The next vulnerabilities are presented within the management-move order of the UPX unpacker. Disclaimer: MemoryWave Community In the next, decompiled code from Bitdefender’s core engine is introduced. The naming of variables, fields, and macros is heavily impressed by the original UPX. For some snippets, a reference to the unique function is added for comparability.
It is likely that some varieties are incorrect. After the UPX loader has been detected, the Bitdefender engine tries to detect whether or not the loader applies a particular sort of deobfuscation to the compressed knowledge payload earlier than extracting it. LEFT. If this deobfuscation is detected, then the engine iterates via the corresponding instructions of the loader and parses them with their operands in order to be able to deobfuscate the information as nicely. Observe how the sure-test on the index variable i is performed. 16. Specifically, we can enhance i from 15 to 17, after which we will overwrite the stack with utterly arbitrary knowledge. The debug break is as a result of stack canary which we have overwritten. If we continue, we see that the return fails as a result of the stack is corrupted. Clearly, this offsets needs to be checked before writing to it. Both checks take a look at towards the sphere dword10.
The field dword10, sitting on the calling functions’s stack frame, is rarely initialized. This makes the bound check ineffective and introduces a completely attacker-controlled heap buffer overflow. After the extraction, the engine makes an attempt to deobfuscate the extracted data with a static XOR key. The sure test is completely fallacious. It ought to verify in opposition to the dimensions of the extracted data buffer. As a substitute, it checks against a value that is beforehand set to the uncooked information dimension of the part we extracted the information from. These two sizes don't have anything to do with each other. Particularly, one may be much smaller than the other, or vice-versa. Because the function does not return after the first deobfuscation run, the memory corruption can be triggered up to 0x300 instances in a row. This enables us to bypass the limitation that in a single deobfuscation run we always XOR with the same byte. General, we then have XORed with C0 C0 C1 C1 C1 C2 C2 for fully arbitrary C0, C1, and C2.
We are able to essentially XOR with such a sample of almost arbitrary size, and swap the byte at most 0x300 instances. Needless to say, this vulnerability is a helpful exploitation primitive because it enables very highly effective memory corruptions: XORing permits us to change selectively only sure parts of knowledge, leaving different components (for MemoryWave Community example heap metadata or critical objects) untouched. A filter is a straightforward transformation on binary code (say, x86-64 code) that's utilized earlier than compression, with the purpose to make the code extra compressible. After now we have decompressed the info, we have to revert this filtering. Bitdefender helps about 15 totally different filters. Of the 15 filters, about eight appear to be affected by such a heap buffer overflow. I treated them all collectively as one bug (after all, it isn't unlikely that they share code). The next memory corruption occurs in a loop of the perform PeFile::rebuildImports (cf.
관련자료
-
이전
-
다음