Home

Awesome

ROP-COMPILER

ROP based CSGO, BF3, BF4 cheat

What is ROP

The Wikipedia article about it describes it best:

Return-oriented programming (ROP) is a computer security exploit technique that allows an attacker to execute code in the presence of security defenses such as executable space protection and code signing.[1]

In this technique, an attacker gains control of the call stack to hijack program control flow and then executes carefully chosen machine instruction sequences that are already present in the machine's memory, called "gadgets".[2] Each gadget typically ends in a return instruction and is located in a subroutine within the existing program and/or shared library code. Chained together, these gadgets allow an attacker to perform arbitrary operations on a machine employing defenses that thwart simpler attacks.

https://en.wikipedia.org/wiki/Return-oriented_programming

The TL;DR is that return-oriented programming (ROP) is a commonly used technique in exploitation to gain code execution<br />

look below at Compiler output

Why ROP

CSGO is protected by Valve Anti-Cheat (short VAC)<br /> BF3 and BF4 are protected by PunkBuster (short PB)<br /> ROP should be very difficult to detect for these Anti-Cheats for the following reasons<br />

So hopefully this cheat will be VAC / PB undetected for ever :wink:<br />

ROP-Code

You can download a compiled binary of the Rop-Compiler from here:<br /> DOWNLOAD BUTTON

For a look into the compiled code look below at Compiler output

Compiler

Data-types

In computer science a Words size is determined by the maximal number of bits the processor can process <br /> But Intel and Microsoft define a word as a 16bit number: <br />

BitsBytesDatatype name
162WORD
324DWORD
648QWORD
648DWORD64

For all data-types check microsofts documentation:<br /> https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types <br />

Accessible registers

Native x86 registers

added virtual registers

Read only register

Usable instructions

The instruction set is very limited and can be found in the >>Gadgets.h<< header <br />

Compare two values

it's very rare to find a comparison instruction followed by a return, so I am using a trick:

;//if ( ECX != 0x28 ) goto l_skip
mov eax, 0x28
sub eax, ecx;//COMPARE EAX, ECX
jne l_skip

a substraction in x86 also effects the flags.<br /> so for example:

mov eax, 0x1
mov ecx, 0x1
sub eax, ecx

the ZeroFlag will be set to 1 by the substraction instruction.<br />

Special instructions

Jump labels

@l_LabelName:

Get address of jump label

mov ebx, @l_LabelName

Get address of Gadget

mov ebx, #xchg esp,ebx

Get address of API function

mov ebx, !user32.GetAsyncKeyState

Reading from Virtual Registers

mov ecx, VR8

<sub>the compiler will translate it to (each line a single gadget)</sub><br/>

xchg eax, ecx
pop eax ;//load virtual register address from stack
mov eax, DWORD PTR[eax]
xchg eax, ecx

Writing to Virtual Registers

mov VR8, ecx

<sub>note that ebx can't be written directly to a virtual register</sub><br/><br/> <sub>the compiler will translate it to (each line a single gadget)</sub><br/>

xchg eax, ecx
pop ebx ;//load virtual register address from stack
mov DWORD PTR[ebx], eax
xchg eax, ecx

Jumps

jne l_Start

note that a jump overwrites the ebx register!<br/> look at the function addJumpToRopChain but basically its using a conditional move

mov ebx, @l_Start
cmovne esp,ebx

only that a conditional move directly to esp is very rare so it's utilizing exchange instructions to be able to use a more commonly used instruction like this:

mov ebx, @l_Start
xchg ecx, ebx
mov eax, @l_continue543
cmovne eax,ecx
xchg ecx, ebx
xchg eax, ebp
@l_continue543:

Compiler functions

Execution orderFunctionDescription
1.LoadFileToMemoryloads the raw assembly source-code file into memory
2.GetCompilerSettingssearches for the compiler settings
3.InitializeRopGadgetsdepending on the compiler settings gadgets specified in the "Gadgets.h" header get searched
4.BringYourOwnGadgetsthe gadgets that didn't get found get placed into a with random data-filled buffer
5.CompileCodecalls the four functions below
6.=> ReadInCodethe instructions get extracted from the source-code file and stored in the InstructionCache struct
7.=> ConvertToROPbuilds the ROP-chain by retrieving the address of each instruction and adding it to the RopChain vector
8.=> HijackThreadStackcreates a new thread with CreateRemoteThread and overwrites the threads stack with the Rop-chain at a random position in the stack
9.==> RelocatingJumpsrelocates all jump addresses to the address of the rop-chain in memory
10.RemoveUnusedGadgetsremoves not used gadgets from the gadget buffer created by the BringYourOwnGadgets function
11.ResumeThreadstarts the execution of the rop-chain

Compiler output

using the tool ReClass you can look inspect memory and look at the generated rop-chain<br />

Raw thread stack

This is how the generated thread-stack (ROP-Chain) looks like:<br /><br /> Image of rop-chain

Thread stack with gadget code

Now on the right I added the assembler code that is at each address:<br /><br /> Image of rop-chain

Reclass

For a Tutorial on ReClass look at UC<br /> https://www.unknowncheats.me/forum/general-programming-and-reversing/120805-reclass-usuage-reclass-and-its-content.html

ret instruction

the return instruction is essential for ROP.<br /> The CPU jumps ( by setting the InstructionPointer [on x86 EIP] ) to an address it reads from the stack<br /> to help understanding the instruction this how the CPU processes the ret instruction:

void Ret( )
{
	Eip = *(DWORD*)( Esp + 0x000000 );
	Esp = Esp + 4;
}

pop instruction

gadgets for pop instructions are easy to find and can be used to set a register to a certain value <br /> to help understanding the instruction this how the CPU processes the pop eax instruction: <br />

void PopEAX( )
{
	Eax = *(DWORD*)( Esp + 0x000000 );
	Esp = Esp + 4;
	Eip = Eip + 1;
}

jumps in ROP

in ROP the stack pointer ESP becomes the instruction pointer so by changing it follwed by a return instruction a jump happens <br /> to do conditional jumps a conditional move instruction can be used:

//Unsigned Conditional Jump
//  JE - JZ   - Equal/zero                  - ZF = 1
if ( memcmp( C, "je", 2 ) == 0 || memcmp( C, "jz", 2 ) == 0 )
{
	//"cmove esp,ebx"
	addJumpToRopChain( p, C, 2, "cmove" );
	continue;	
}

for unconditional jumps a pop esp or a xchg esp, ebx can be used<br />

Conditional jump instructions: [page: 184]<br /> https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf#G9.1746

Conditional Move Instructions: [page: 172]<br /> https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf#G9.17648