Pandora Ransomware
[TOC]
overview
First of all, I love oalabs. Below of code is copied from his research, and I get a lot from just repeat it. And maybe there are also bogus-control-flow in this sample however.
Sample: 5b56c5d86347e164c6e571c86dbf5b1535eae6b979fede6ed66b01e79ea33b7b
Unpacked sample: 2619862c382d3e375f13f3859c6ab44db1a4bce905b4a617df2390fbf36902e7
on the malshare(by the oalabs)
References
- Control Flow Flattening
- Deobfuscation - Recovering an ollvm
- dumpulator
- Control Flow Unflattening
- malshare
- oalabs
Dumpulator
according to the jmp [register]
Our approach is to seperate the dispatcher bb from the payload bb. For each dispatcher bb the code is emulated with all conditions to generate the conditional jump addresses
. The bb is then replaced with a simple compare and conditional jmp. Emulation is done with Dumpulator.
Once the dispatcher has been deobfuscated we should be able to see the control flow for the payload bb
, and futher simplify the dispatcher using more traditional tools, possibly removing it completely.
- if the jump is relative it’s for a code bb
- if the jump is register then it’s a cf bb
- if there is a ret this is the end
build a table of bb the start is next head after jmp, end is jmp emulate patch the jmp for each table entry
IDA Produce Basic Block Table
There are two dispatcher bb formats, one that uses cmovl, cmovz
, and one that uses setl and setz
. We need to match both patterns
and determine the type of condition for our jmp statement
, and the eax cmp value. For each bb record the following information so it can be used in our emulator.
- bb start
- bb end
- add cmov instruction
- type of cmov instruction (l,z)
- eax cmp value
- jmp register
Results: (bb_start, bb_end, eax_value, jmp_condition,jmp_condition_address, jmp_register)
1 | # Basic blocks for dispatcher |
bb_table means the Dispatcher bb, and this bb has two formats that uses (cmovl, cmovz) or uses (setl and setz)
bb_orig_table means the origin payload bb
Emulate Basic Blocks
For each dispatcher bb emulate the block both satisfying the condition and not satisfying it to produce both the jmp address for the conditional jmp and the jmp address for the unconditional jmp.
1 | DUMP_FILE = '13.25.dmp' |
ida patch
conditions
- cmovl setl————jl
- cmovz setz————jz
- setnz————jnz
so why this???
1 | cmovl rdx, r12 ; Move if Less (SF!=OF) |
1 | import struct |
analysis
1 | print(hex(patch_jmp_cond_start),hex(jmp_rel_statisfied),hex(patch_jmp_start),hex(jmp_rel)) |
output beblow
1 | patch_jmp_cond_start jmp_rel_statisfied patch_jmp_start jmp_rel |
this means
Author: scr1pt