3. ROP Attacks
• Introduced by hovad shacham
• Circumvents DEP (data execution prevention)
• Turing Complete`ness
• More useful than ret-2-lib ( branching)
• Applicable to various architectures
4. ROP Attacks
• Gadgets are the building blocks
• Gadgets end with RET instruction
• Example gadgets
• Mov eax, ebx
• Ret
• Pop eax
• Ret
5. ROP attacks
x86 stack layout
. Registers ebp and esp point to base and top of the
stack respective
. EBP used to access local and passed paramters
eg . [ebp + 8] first parameter (EBP + 4) for ret
address
. ESP used are a pointer for popping values out from
stack
6. ROP attacks
• RET x86 instruction
• Pops a value from the stack into EIP
• Used to return control from a function
• RET can have a argument eg RET 8
• RET 8 == EIP = stack[top], add ESP , 8
7. X86 stack layout
calling conventions
__stdcall ( varadic arguments)
Int __stdcall function(int a, int b) // < paramerts
{
int b,c; // local c variables
return 0;
}
function(10, 20); // function call __stdcall
X86 disassembly
push 20 // arguments pushed from right to left
push 10
call function
function:
push ebp // Stack epilouge
mov ebp, esp
sub esp, 8 //8 bytes for two variabeles
….
….
add esp, 8
pop ebp
ret 8 // ret 8 stack clearance by callie
8. X86 stack layout
calling conventions
__cdecl( const no of args)
Int __cdelc function(int a, int b) // < paramerts
{
int b,c; // local c variables
return 0;
}
function(10, 20); // function call __cdecl
X86 disassembly
push 20 // arguments pushed from right to left
push 10
call function
add esp, 8 // stack clearance
function:
push ebp // Stack epilouge
mov ebp, esp
sub esp, 8 //8 bytes for two variabeles
….
….
add esp, 8
pop ebp
ret // ret no stack clearence
9. Basic stack overflow
• A local stack variable gets overflowed
• CALL instruction pushes the EIP to the stack
• Find a trampoline eg jmp esp to change the
value to eip to attacker controlled buffer
• demo
10. What about NX bit ?
• DEP restricts the execution of segments
marked as r/w
• We can re-use code from the address space of
executable
• Useful code chunks called as ROP gadgets
• Multiple gadgets can be chained together and
even API calls
11. ROP Basics(load and store gadgets)
• storing and loading values from and into
memory
• Primitive example pop eax; ret / pop ebx ret/ pop r32, ret
• To memory store pop eax, pop edx, ret / mov [eax], edx; ret
12. Wait a sec!
» Handling NULL bytes
• Some parameters contain NULL
• Even some addresses contain zero values
• Cannot inject NULL or zero values
• Bug prone functions eg strcpy stop copying
when they encounter a NULL byte (00 hex)
13. Handling NULL bytes
• Let x = value containing a ( many) NULL byte
• Let y = mask = 0xffffffff
• Mathematical axiom
• A xor B = z (say)
• Now z xor B = A
• We can 0x00000000 xor 0xffffffff = z (say)
• Xor it back to get the original value
• We have xor esi, ebx ; ret!
14. ROP basics(arithmetic )
• Msvcrt32.dll 0x77c4d6f add ebx, esi; stc; ret
• Kernel32.dll 0x7c902af5 sub eax,ecx; ret
• We have same for mul and div !
• Try in immunity search: add r32, r32;any;ret;
• You will find huge no. of gadgets
15. ROP basics(LOOPS)
• UNCONDITIONAL LOOPS or INFINITE LOOPS
• Pop back the value in ESP, pop esp;ret
7C80BCA8 5C POP ESP //kernel32.dll
7C80BCA9 C3 RETN
16. ROP basics(conditional jumps )
• The tricky part
• We need to modify ESP , based on certain
comparisons
. comparisons include greater than , less than ,
equal to;
X <y
X >y
X == some_val
.
17. Comparing with zero
• Divert flow through adding a certain value to esp
• Store two values on the stack , value_to_be_checked and esp_delta (the value to
be added to esp)
• Load the val in a general purpose register say eax
• X86 instruction NEG computes the two's complement and updates CF
. if val == 0 the CF = 0; else CF = 1
• ADC x86 instruction add the source and dest with carry flag(ADC – add
with carry flag)
• Make a general purpose reg and zero by xor r32,r32; then apply adc
r32,32
18. Comparing with zero(contd..)
• We have a REG (say eax) containing a single 1 bit or all 0 bits
• Apply NEG instruction on that REG to obtain the two's complement
• 2's comp will transform it into all zero's or all ones
• Perform bit-wise AND with ESP_DELTA
. according we will get ESP_DELTA as zero or its original value
• ADD esp, ESP_DALTA to divert the control flow
• DEMO
19. Checking for == (equality)
• Two values val1, val2 to be checked for equality
• Load two values using load and store gadgets as shown earlier
• Perform x86 SUB val1, val2,store back the result
• If both the values are same result will be zero,
. Check the result to zero as show in the previous slide
• ADD esp, ESP_DALTA to divert the control flow
• DEMO
20. Checking for <, > (less or greater)
• Two values val1, val2 to be checked for equality
• Load two values using load and store gadgets as shown earlier
• Perform x86 SUB val1, val2, SUB intruction sets the CF if dest > source
• Save CF using xor r32, r32;ret; adc r32,r32 ret; as shown in ealier slide
. CF will be 1 if dest > source else 0
• DEMO
22. JUMP oriented Programming
Attacks
• ROP used gadgets ending with RET x86 instruction
• JOP uses statements ending with Indirect Jump call
• Instead of stack uses a dispatcher table to jump to different locations
• Thwarts certain Anti-ROP defences
24. JUMP oriented Programming
Attacks
• Dispatcher gadget increments a REG by certain value to make it point to next loc to
jump on
• Add ebx, 4 ; JMP [ebx]
• Here , EBX points to the Dispatcher table
• Same gadgets as in ROP attacks
25. JOP(attack Model)
• Cannot work on stack buffer overflow , because control flow diverts through a ret
Instruction
• Will be detected by anti-ROP defenses if(stack overflow is used)
• Attack vectors include
• 1: pointer overwrite
• 2: Arbitrary DWORD overwrite
• 3: C++ vtable overwrite
27. Alphanumeric ROP Shellcode
• Traditional Shellcode can be made alphanumeric by choosing only certain
instruction
Example . pop ecx has an
opcode 0x59 which is the ASCII code of the character Y)
• Similar technique used in ROP shellcode
. Selecting a printable address rather than a printable opcode(in trad.
shellcodes)
28. Alphanumeric ROP Shellcode
Basic Technique by adding two printable addresses. The range of ASCII printable
characters is between 0x21 and 0x7e
Example . A non-printable gadget in kernel32.dll at 0x77D4B8C2 {pop ebx;ret} can be
represented by adding two printable addresses
0X225D414B(printable) + 0x55777777(printable) = 0x77D4B8C2(no-printable)
• Combined together can be used to transform a printable code into non-
printable
• Similar technique used in ROP shellcode
. Selecting a printable address rather than a printable opcode(in trad.
shellcodes)
29. Alphanumeric ROP
Shellcode(gadgets)
• Gadgets used for decoding addresses should be printable(bytes should be
in range of 0x21 - 0x7e
• We also need a memory region which has a printable address to store the
decoded gadgets addresses marked as r/w
. From reg to mem we have urlmon.dll
0x772C2E5E MOV DWORD PTR DS:[ECX],EAX
. ESP related CRYPTUI.dll 0x775513E30 XCHG EAX,ESP
. MSCTF.DLL 0x74722973 POP EAX
. Mshtml.dll 0x7D504962 ADD EAX,ECX
. msimtf.dll MEM to reg 0x74714263 MOV EAX,DWORD PTR DS:[ECX]
. All of the dll's loaded by internet explorer
31. Effectively searching gadgets
• Immunity debugger search for all sequences in all modules
• ANY for any no of op codes and any reg
• Match Different registers eg POP RA, RB ; RA and RB will be different
• Best Practice search in reverse order