PinDemonium
a DBI-based generic unpacker for Windows executables

Sebastiano Mariani - Lorenzo Fontana - Fabio Gritti - Stefano D’Alessio

Malware Analysis●

Static analysis : Analyze themalware without executing it●

Dynamic analysis : Analyze
the malware while it isexecuted inside a controlledenvironment2

Malware Analysis●

Static analysis : Analyze themalware without executing it●

Dynamic analysis : Analyze
the malware while it isexecuted inside a controlledenvironment

Static Analysis●●●Analysis of disassembled code
Analysis of imported functions
Analysis of strings3Maybe in a fairy tale...
What if the malware tries to hinder the analysis process?

Packed Malware●●Compress or encrypt the original code
Code and strings analysis
impossible
Obfuscate the imported functions
Analysis of the imported
functions avoided??

4

Solutions
Manual approach

Automatic approach● Very time consuming● Fast analysis● Too many samples to beanalyzed every day● Scale well on thenumber of samples thathas to be analyzed everyday● Adapt the approach todeal with different
techniques● Single approach to deals
with multiple
techniques5All hail

PinDemonium

6Overview

PinDemonium is a
generic unpacker
based on Intel PIN, adynamic binary
instrumentation
framework (DBI)

7

What is a DBI?
Control Flow Graph
Basic Block

BB1

Trace
BB3BB2BB4BB6BB7BB8BB9BB10BB11BB128

What is a DBI?
Code Cache
BB1BB3BB2

Trace is copied in the code
cache

BB1BB3BB2

BB4BB6BB7BB8BB9BB10BB11BB129

What is a DBI?
Code Cache
BB1BB3BB2BB4BB6BB7

DBI provides the possibility to add
user defined code after each:- Instruction- Basic Block- Trace

BB1

User Defined
CodeBB3BB2BB8BB9BB10BB11BB1210

What is a DBI?
Code Cache
BB1BB3BB2

DBI starts executing the programfrom the code cache

BB1

User Defined
CodeBB4BB6BB7BB3BB2BB8BB9BB10BB11BB1211

Key idea

How can an
unpacker begeneric?

Exploit the functionalities of the
DBI to identify the common
behaviour of packers:
they have to write new code inmemory and eventually executeit12IATRecognizdump e the correcamong man tye theDeobfuscat

Dumpthe mcorre emoryctly

Detec
execu t written anted memor d theny regions

Our stairway to heaven
Packedmalware
Original
malware13

Our journey
beginsWe begin to build
the foundation ofour system

14

Detect WxorX memory regions
Let’s exploit the key idea behind a generic unpacker
implementing the WxorX handler module
Concepts:●●

Write Interval (WI): range ofcontinuously written
addresses

WxorX law broken:
instruction written by the
program itself and thenexecuted

Idea:
Track eachprogram:

instructionofthe●

Write instruction: get the targetaddress of the write and update
the write interval consequently.

●All instructions: check if the EIP
is inside a write interval present
in the write set. If the condition is
met then the WxorX law isbroken.
15Detect WxorX memory regions
Steps:
Current
instr.

PinDemonium

Write set

0x401000

0x412000
0x413000

0x402000
0x403000

0x401000
0x402000

Legend:EIP value

Start addr.
End addr.

: Instruction with its EIP: Write instruction and its
ranges16

Detect WxorX memory regions
Steps:
Current
instr.

PinDemonium

1.

The current instruction is awrite, no WI present, create
the new WI

Write set

0x401000

0x412000
0x413000

0x402000
0x403000

0x401000
0x402000

Write interval 10x401000 - 0x402000

Legend:EIP value

Start addr.
End addr.

: Instruction with its EIP: Write instruction and its
ranges17

Detect WxorX memory regions
Steps:
Current
instr.

PinDemonium

Write set

0x401000

0x412000
0x413000

0x402000
0x403000

1.

The current instruction is awrite, no WI present, create
the new WI

2.

The current instruction is awrite, the ranges of thewrite overlaps an existing
WI, update the matched WIWrite interval 10x401000 - 0x403000

Legend:EIP value

Start addr.
End addr.

: Instruction with its EIP: Write instruction and itsranges

18Detect WxorX memory regions
Steps:
Current
instr.

PinDemonium

1.

The current instruction is awrite, no WI present, create
the new WI

2.

The current instruction is awrite, the ranges of thewrite overlaps an existing
WI, update the matched WI

3.

The current instruction is awrite, the ranges of thewrite don’t overlap any WI,
create a new WIWrite set

0x401000

0x412000
0x413000

Write interval 10x401000 - 0x403000

Write interval 2

Legend:EIP value

Start addr.
End addr.

0x412000 - 0x413000: Instruction with its EIP: Write instruction and itsranges

19Detect WxorX memory regions
Steps:
Currentinstr.

PinDemonium

1.

The current instruction is awrite, no WI present, create
the new WI

2.

The current instruction is awrite, the ranges of thewrite overlaps an existing
WI, update the matched WI

3.

The current instruction is awrite, the ranges of thewrite don’t overlap any WI,
create a new WI

4.

The EIP of the current
instruction is inside a WI,
WxorX law broken!

Write set
Write interval 10x401000

0x400000 - 0x403000

Write interval 2

Legend:EIP value

Start addr.
End addr.

0x412000 - 0x413000: Instruction with its EIP

DUMP THE MEMORY!

: Write instruction and itsranges

20

Ok the core ofthe problem
has beenresolved...

… but we have justscratch thesurface of theproblem. Let’scollect the results
obtained so far...

21

Dump the program correctly
In order to dump the program we have exploited the capabilities of ourdumping module and Scylla
PinDemonium
Instrumented
program memory

Steps:
1.

1

The execution of awritten address isdetected

Main Module
EIP

Written Memory22Dump the program correctly
In order to dump the program we have exploited the capabilities of ourdumping module and Scylla
PinDemonium
Instrumented
progam memory

12

ScyllaSteps:
1.

The execution of awritten address isdetected

2.

PinDemonium calls
ScyllaMain Module
EIP

Written Memory23Dump the program correctly
In order to dump the program we have exploited the capabilities of ourdumping module and Scylla
PinDemonium
Instrumented
program memory2

ScyllaSteps:

1

1.

The execution of awritten address isdetected

2.

PinDemonium calls
Scylla3.

Scylla gets theaddresses of the mainmodule3

Main Module
EIP

Written Memory24Dump the program correctly
In order to dump the program we have exploited the capabilities of ourdumping module and Scylla
PinDemonium
Instrumented
program memory2

ScyllaSteps:

1
3

The execution of awritten address isdetected

2.

PinDemonium calls
Scylla3.

Scylla gets theaddresses of the mainmodule

4.

Scylla dumps themain module alongwith the written
addresses on a file

4

Main Module
EIP

1.

Written Memory
Main Module
Written Memory25

Have wealreadyfinished?

Nope...

26

Unpacking on the heap
What if the original code is written on the heap?
PinDemonium
Instrumented
program memory

Steps:

Main Module

Heap
EIP

Written Memory27

Unpacking on the heap
What if the original code is written on the heap?
PinDemonium
Instrumented
program memory2

ScyllaSteps:

13HeapWritten Memory

The execution of awritten address is
detected

2.

PinDemonium calls
Scylla3.

Scylla gets theaddresses of the mainmodule

4.

Scylla dumps themain module

4

Main Module

EIP

1.

Main Module

WRONG!

28

Unpacking on the heap
The OEP doesn’t make sense!

29Unpacking on the heap

Solution
Add the heap memory
range in which theWxorX rule has beenbroken as a new section
inside the dumped PE!

1. Keep track of writeintervals located on theheap
2. Dump the heap-zone
where the WxorX rule isbroken3. Add it as a new section
inside the PE
4. Set the OEP inside this newadded section30

Unpacking on the heap
The OEP is correct!

31

Unpacking on the heap
However, the dumped heap-zone can contain references to addresses
inside other not dumped memory areas!

32Unpacking on the heap
1. Retrieve all the currently
allocated heap-zones

Solution
Dump all the heap-zones
and load them in IDA inorder to allow static
analysis!

2. Identify the new allocatedor modified ones bycomparing the MD5 oftheir previous content
3. Dump these heap-zones
4. Create new segments
inside the .idb for each ofthem
5. Copy the heap-zones
content inside these newsegments!
33

Unpacking on the heap

34

Two down,
two stillstanding!

Reverser we arecoming for you!
Let’s deobfuscatesome importedfunctions...

35

Deobfuscate the IAT
Extended Scylla functionalities:● IAT Search : Used Advanced and Basic IAT searchfunctionalities provided by Scylla●IAT Deobfuscation : Extended the plugin system ofScylla for IAT deobfuscation

36

Deobfuscate the IAT
Steps:
1.

Is the address 0x04000012
inside the DLL memory
region? No, continue until
next jump…
ins_delta = 0

2.

Is the address 0x04001000
inside the DLL memory
region? No, continue until
next jump…
ins_delta = 8

3.

Is the address 0x75000010
inside the DLL memory
region? YES! Let’s patch theIAT entry
ins_delta = 160x04000000

0x04000012
ADD EAX, 4

10x04000012

ADD EAX, 4

MOV EBP, [ESP]

MOV EBP, [ESP]POP EBPJMP 0x04001000

PUSH EAX

230x04001000

SUB ECX, 1

POP EBP

MessageBox + 0x14

PUSH EAX

MessageBox + 0x180x75000000
Messagebox
Entrypoint[0x4000012] = (0x75000010 - 16) =0x75000000
CORRECT!

JMP 0x7500001037

One last step...

Too many dumps,
too many programs
making too many
problems… Can’t
you see? This is theland of confusion

38

Recognize the correct dump
We have to find a way to identify the correct dump

Idea

1. Entropy difference

Give for each dump a“quality” index using theheuristics defined in ourheuristics module

39

Recognize the correct dump
We have to find a way to identify the correct dump

Idea

1. Entropy difference

Give for each dump a“quality” index using theheuristics defined in ourheuristics module

2. Far jump

40

Recognize the correct dump
We have to find a way to identify the correct dump

Idea

1. Entropy difference

Give for each dump a“quality” index using theheuristics defined in ourheuristics module

2. Far jump
3. Jump outer section

41

Recognize the correct dump
We have to find a way to identify the correct dump

Idea

1. Entropy difference

Give for each dump a“quality” index using theheuristics defined in ourheuristics module

2. Far jump
3. Jump outer section
4. Yara rules42

Yara Rules
Yara is executed on the dumped memory and a set ofrules is checked for two main reasons:

Detecting Evasive code

Identifying malware family

Detect patterns of evasive
code
which
may
have
prevented
thecomplete
unpacking of the malware
like Anti-VM and Anti-Debug
techniques

When a known malware
family rule is matched after
multiple unpacking layers
probably this is the correct
dump43

Advanced Problems

You either diea hero or you
live longenough to see
yourself
become thevillain

Exploit PIN
functionality tobreak PINA.k.a. Self
modifying code45Self modifying code
Steps:

CodeCache

ins_1
ins_2
wrong_ins_3
ins_4
ins_5

Main
module oftargetprogram46

Self modifying code
Steps:

ins_1
ins_2
crash_ins_3
ins_4

1.

The trace iscollected in the code
cacheCollected
trace

ins_1
ins_2
crash_ins_3
ins_4
ins_547

Self modifying code
Steps:
Execution
startsins_1
ins_2
crash_ins_3
ins_4

1.

The trace iscollected in the code
cache

2.

The execution starts
in the code cache

ins_1
ins_2
crash_ins_3
ins_4
ins_548

Self modifying code
Steps:
Executionstarts

ins_1
ins_2
crash_ins_3
ins_4
Patch

ins_1
ins_2
ins_3
ins_4
ins_5

1.

The trace iscollected in the code
cache

2.

The execution starts
in the code cache

3.

The wrong
instruction ispatched in the main
module49

Self modifying code
Steps:

Execute
here

ins_1
ins_2
crash_ins_3
ins_4

ins_1
ins_2
ins_3
ins_4
ins_5

1.

The trace iscollected in the code
cache

2.

The execution starts
in the code cache

3.

The wrong
instruction ispatched in the main
module4.

The wrong_ins_3 isexecuted

CRASH!

50

SolutionSelf modifying code
Steps:

ins_1(write)
ins_2
crash_ins_3
ins_4

List of written
addresses

ins_1
ins_2
crash_ins_3
ins_4
ins_552

Self modifying code
Steps:
1.

1

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

List of written
addresses

ins_1
ins_2
crash_ins_3
ins_4ins_553

Self modifying code
Steps:IP

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

1.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

List of written
addresses
2crash_ins_3_addr

ins_1
ins_2
crash_ins_3
ins_4
ins_5

54

Self modifying code
Steps:IP

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

List of written
addresses
31.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

3.

The crash_ins_3 is patchedin the main modulecrash_ins_3_addr

ins_1
ins_2
ins_3
ins_4
ins_555

Self modifying code
Steps:IP

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

List of written
addresses
crash_ins_3_addr

41.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

3.

The crash_ins_3 is patchedin the main module

4.

Check if ins_2 address is
inside the list
NOPE…

ins_1
ins_2
ins_3
ins_4
ins_556

Self modifying code
Steps:IP

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

List of written
addresses
crash_ins_3_addr

1.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

3.

The crash_ins_3 is patchedin the main module

4.

Check if ins_2 address is
inside the list

5

ins_1
ins_2
ins_3
ins_4
ins_5

NOPE…
5.

Check if crash_ins_3 address
is inside the list
YES!

57

Self modifying code
Steps:

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2CheckEipWritten()crash_ins_3
CheckEipWritten()
ins_4

List of written
addresses

1.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

3.

The crash_ins_3 is patchedin the main module

4.

Check if ins_2 address is
inside the list

6
crash_ins_3_addr

NOPE…

ins_1
ins_2
ins_3
ins_4
ins_5

5.

Check if crash_ins_3 address
is inside the list
YES!

6.

Stop the execution

58Self modifying code
Steps:

7

CheckEipWritten()
MarkWrittenAddress()
ins_1 ( write )CheckEipWritten()
ins_2
CheckEipWritten()
ins_3
CheckEipWritten()
ins_4

List of written
addresses
crash_ins_3_addr

1.

Insert one analysis routine
before each instruction andanother one if theinstruction is a write

2.

Execute the analysis routine
before the write

3.

The crash_ins_3 is patchedin the main module

4.

Check if ins_2 address is
inside the list
NOPE…

ins_1
ins_2
ins_3
ins_4
ins_5

5.

Check if crash_ins_3 address
is inside the list
YES!

6.

Stop the execution

7.

Recollect the new trace
CORRECT!

59

Are there
other ways tobreak theWxorX rule?

Process Injection60

Process Injection
Inject code into the memory space of a different process
and then execute it● Dll injection● Process hollowing● Reflective Dll injection● Entry point patching

OUR WxorX TRACKER IS NO MORE SUFFICIENT!
61

Solution

Process Injection
Identify remote writes to other processes by hooking
system calls:● NtWriteVirutalMemory● NtMapViewOfSection
Identify remote execution of written memory byhooking system calls:● NtCreateThreadEx● NtResumeThread● NtQueueApcThread63

Finally for the SWAG!

Experiments➔ Test 1 : test our tool against the same binary packed
with different known packers.

➔ Test 2 : test our tool against a series of packed
malware sample collected from VirusTotal.

65

Experiment 1 :known packers
Upx

FSG

Mew

Xcom
pPElockASProte
ctmpress

PeCompa
ct

Obsidium

ExePacker

ezip

MessageBox.
exe
WinRAR.exe

ASPackeXpressorexe32packer

beropac

HyperiokernPeSpin

MessageBox.
exe
WinRAR.exeOriginal code dumped but Import directory not reconstructed
66

Experiment 2 :wild samples
Number of packed (checked manually) samples

1066
N°%

Unpacked andworking

519

49

Unpacked butDifferent behaviour

150

14

Unpacked but notworking139

13

Not unpacked

258

2467

Experiment 2 :wild samples
Number of packed (checked manually) samples

1066
Unpacked andworkingN°% of all

519

49
63%

Unpacked butDifferent behaviour

150

14

Unpacked but notworking

139

13

Not unpacked

258

2468

DEMO

More advanced IAT
obfuscation techniques
are not handled

Limitations

Packers which reencrypt / compress
code after its execution
are not supported

Evasion techniques are
not handled70Generic unpacker basedon a DBI
Able to reconstruct aworking version of theoriginal binary

Conclusions

Able to deal with IAT
obfuscation and dumping
on the heap
17 common packers
defeated
63% of random samples
correctly unpacked(known and custompackers employed)
71

The source code is available athttps://github.com/Seba0691/PINdemonium

Thank you!