anti-disassembly.md 3.3 KB


title: Anti Disassembly Techniques date: 2021-01-13 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

```