title: Anti Disassembly Techniques
categories: [cheatsheets]
tags: [security, reverse-engineering]
Anti Disassembly
2 Types of Disassembly Algorithms
- Linear Disassembly
- Flow-oriented Disassembly
Linear Disassembly
- Have Problems distinguish between Code & DATA
- Disassemble the complete .text section
- often contanis wrong disassembly (even in non-malicious code)
- iterates blindly over buffer
Flow-Oriented Disassembly
- used by commercial products
- the disassembler follows the Jmp's and only disassembles locations that are reached in the code
Anti Disassembly Techniques
Jump-Same-Target
- Two conditional jumps are made to the same location
- the first byte after the location
- define the NOP byte as a byte-constant: eg 0xe8 (call-instruction)
_start:
push ebp
mov ebp, esp
xor eax, eax
jz jump+1
jnz jump+1
jump:
nop
push eax
push ebx
push ecx
Result in BinaryNinja: Interprets the 0xe8 as call instruction, still continues the correct execution!
No result in IDA Pro.
Jump with Constant Condition
- use a conditional jump with a constant condition
- will insert a call instruction
- disassembler disassembles the else-branch first.
- Working for BinaryNinja
- Not working for IDA Pro
_start:
push ebp
mov ebp, esp
xor eax, eax
jz jump
nop ; define this as 0xe8
jump:
push eax
push ebx
push ecx
Impossible Disassembly
One Byte is together in two instructions
inc eax
-----
hex: EB FF C0 48
----- **
instr: jmp-1 dec eax
the EBB FF jumps in the middle of the jump instruction, therefor being FF C0 the next instruction (inc eax)
then 48 as dec eax
Works in IDA Pro
Binary Ninja can disassembly this
simply insert "EB FF C0 48" at any position
like a complicated NOP-Instruction
section .text
global _start
_start:
push ebp
mov ebp, esp
jmp $-1 ; change sec. Byte to FF
nop ; change to 0xC0
dec eax
; do your stuff here
push eax
push ebx
push ecx
- also possible even more complex
- replace 9 nop bytes with: 66 B8 EB 05 31 C0 74 FA E8
- Binary Ninja gets it!, IDA Pro Not
Function Pointers
- using function pointers in following way
mov [ebp+0x8], offset sub_12342
push 0x1
push 0x2
call [ebp+0x8]
...
..
..
call [ebp+0x8]
- Problem: only first call can be found in the xref Window
- in combination with other anti-dissass. techniques very powerfull
- should be used extensivly to be effective
Return Pointer Abuse
- Retn or Ret pops a value from the stack and jumps to it
- can be abused to confuse disassemblers
call $+5 ; pushes next addr on the stack
add [esp+4+var_4], 5 ; add 5 to the stack (-> So the address points to the 'real function')
retn
---------------------------------
push ebp ; real function, not found by IDA pro because of the return instruction
mov ebp, esp
...
..
.
Misusing Structed Exception Handlers (SEH)
- Use the SEH to confuse Disassemblers
- add a custom SE Handler at fs:0x00 with
```C
; malicious func @ sub_deadbeef
mov eax, sub_deadbeef
push eax ; push handler addr on stack
push dword ptr fs:0 ; push current old handler ptr on stack (prev)
mov fs:0, esp ; set the stack pointer as SEH_STRUCT
xor ecx, ecx
div exc ; force an exception by dividing by zero
```