Blog Archive

Tuesday, November 11, 2008

Anti-Software_Cracking Techniques.

Author:Aodrulez.
Email: f3arm3d3ar@gmail.com




Well..we all know there are thousands of such text
files floating on the Internet.Am not adding sumthin to 
the already present chaos.This paper focuses primarily
on approaches that you might find novel or useful in 
implementing "Anti-Cracking Protection" in your apps.

Techniques:
1]A Registration-Routine Technique:

Simply bored of seeing the same tricks being used &
abused, I thought of trying a novel approach.What if we tried
this:

Usual Registration Routines:

1]Accept Username/Serial from user/file.
2]Use some math-operators & either....
 a] Calculate the serial directly from Username
    & then compare with user-input serial.(Dumb)
 b] Calculate a Hash from the username as well as serial
    using different algo ofcourse & then compare them.
3]Either carry on with the registered status.
4]or Display...a message saying.."Not Registered!"  

My way:

1] Accept the username/serial from user/file.
2] Use some algo on both the Username & serial
  and based on that, generate "opcodes".
3] Inject these opcodes into the registration routine.
4] If the "opcodes" generated match, then & only then
  will the app get registered..else it will crash!!
5] Use SEH so that in case of a crash, the app can be
  terminated elegantly.




So Algorithm-Wise this looks like this:


-----------------------------------------------------------------
        
@app_startup:
1]Implement SEH.


@registration_routine:
1]Accept username/password from the user/file.
2]Use some algo that generates "opcodes" from
 the user input data.
3]Inject these opcodes into the successful_registration 
 routine.

@successful_registration:
(most of the instrucions here are like this:)
push 0
push offset good-boy-text
push offset good-boy-caption
push 0
lea eax,MessageBoxA
db 090h }-------this should be "FF" to make the MessageBoxA 
db 0d0h } function work
            "call eax" instruction--> FFD0 "byte-sequence"
Depending upon the user input & the algo used,
the 0x90 byte should be changedto/injected-with
0xFF for the app to get registered.
Else, if the user/input is not correct, the further
routine will look malformed & the app will crash.


@SEH_routine:
1] Just when the app crashes, the SEH will be called & 
  you can make a graceful exit or maybe handle it &
  resume execution :) .
----------------------------------------------------------------------


Benefits of this approach:
1] You can simply make the whole Registration routine look
   Bogus & generate it on the fly from user-input.
2] Unless the user enters the right Serial/sequence, the registration
   routine will always look bogus.So not much can be made from 
   Disassembly of the routine.
3] The only way to crack this kind of a protection would be to
   know the "opcodes" fairly well & know how code execution takes place.




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


2]Anti-patching.


Well, most (almost all) of the debuggers
  of today rely on "0xcc" or rather "int3" for setting up
  normal breakpoints.How this thing works is like this:

The moment you place a BreakPoint sumwhere, that 
 particular OpCode gets replaced by a "0xcc" byte.Now lets
 simplify this method's idea.Its like..the actual opcode is
 replaced by 0xcc, then the debugger monitors the app's 
 execution to spot int3 being executed.. if its hit, then
 the debugger halts execution at that point & replaces the
 0xcc byte with the actual Previous Byte (opcode).
How to defeat it? One way would be to implement a 
CRC check.Or you might go on the same idea,develop a small
algo that simply calculates a magic value by going through
your code during runtime & checks it with the actual value
it should have if your app is intact.This approach of writing
your own algorithm is recommended because the standard CRC
library functions if implemented in your app, can be easily
detected by the current tools available.
Second way? Yep another good way would be to write the
important parts of your apps' code dynamically to the required
locations like used in many Virii.Example?...here we go:

A simple app with Username/Serial type registration routine:

-----------------------------------------------------------------
app_startup:
Immediately when your app starts,
1]Do a simple crc-type check on the registration
routine.
2]If intact, copy the actual registration routine
 byte-wise-encrypted into the encrypted_code section
 of the apps' memory.
3]Simultaneously Nullify or 'NOP' the actual 
 registration routine.




registration_routine:
1]Decrypte code from encrypted_code into the actual_code
section of your app.
2]Call this newly written routine for the 
 validation of registration details.



actual_code:
1]Actual registration routine goes here.


encrypted_code:
1]Its more like a buffer to store the encrypted
 registration routine.




------------------------------------------------------------------


Benefits of using this technique:
1] The actual registraion routine is always re-written
   before being executed.This kills the 0xcc byte placed
   by the debugger to cause a break in execution(breakpoint).
2] You can always use a CRC-type of check to verify the
   integrity of your registration-routine, so if patched 
   by "newbie-crackers",you could tackle this by maybe 
   over-writing from a bakup-copy of your registration 
   routine from the app's memory or a Dll. 



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

3]Applying Modified Shell-Code Trick.

ShellCodes are nothing but executable machine code to which
if EIP points to..will do something worthwhile :-)..like maybe 
spawn a Windows Calc.Shellcodes are many a times crafted for a 
particular version of an OS..because of the Library function calls
that have to be made.But with much less pain, similar technique 
can be used to cause some more Code-Reversing trouble.Okies... that
was a pathetic introduction to Shellcodes..but its another huge topic
in itself..& this paper only mentions certain aspects of it which
we can use as Anti-Cracking techniques.So what can we use from them?

Lets see another algo:
-----------------------------------------------------------------
@startup:
1]Find the exact version of the OS currently your app is
  running on.Lets assume your registration routine uses
  MessageBoxA function in it.so in that case,recover the
  address of that function from a table already present in
  your app...which looks sumwhat like this:
  
  Windows 2000  : MessageBoxA ==0x7AAAAAA;
  Windows Xp Sp1: MessageBoxA ==0x7BBBBBB;
  Windows Xp Sp2: MessageBoxA ==0x7CCCCCC;

  Or else....do sumthin like this:
  
         lea eax,MessageBoxA
  mov [api_Addr],eax   ----> "api_Addr" is a variable to 
hold its address.This eliminates 
the need for maintaining a table.

2] Call @Registration_routine(part 1)



@Registration_routine(part 1):
1]Actual registration routine lies in the
 "@encrypted_registration_routine(part 2)"
 section of your apps' memory.
2]So first you decrypt it right there.
3]Now the Win32 API function calls will
 look obsolete..because the addresses differ.
4]Inject the API's Correct memory address from the api_Addr
 variable so that its fixed.
5]Call @encrypted_registration_routine(part 2) routine.

@encrypted_registration_routine(part 2):
1]This section contains already encrypted machine code.
2]For example....the actual (un-encrypted) code could look 
 sumthing like this:
 push 0
 push offset Text
 push offset Caption
 push MB_OK
 call 0xAAAAAAAA  <---- This is the address we have to fix
when called from the previous function
after decryption.

---------------------------------------------------------------------
Benefits of this technique:
1] You don't need to have the actual code...then encrypt it...& then
   decrypt it...as in the 2nd technique described in this Paper.
2] If disassembled this code will look fairly weird.
3] Even here, the Breakpoints can be killed as described previously.










Ofcourse these techniques are not Fool-Proof but if 
implemented correctly & efficiently can prevent your app
from being cracked by the "Newbie & maybe even Intermediate"
type of a software cracker.One very important thing you must know is:
"Every Piece of code ever written to this day, can be either Reversed or
 Patched."

You can only try to make it harder or simply Boring to do so... :P
Hope this Paper was useful..... :)

A very Simple PoC of these techniques might be obtained from here:
http://www.crackmes.de/users/aodrulez/aodrulez_crackme_v1.0/

---------------------------------------------------------------------

Greetz fly out to:
1]Amforked()                 :My Mentor.
2]LiquidWorm & Jeremy Brown  :For being so nice to a noob like me.
3]www.OrchidSeven.com      :For givin me this beautiful opportunity.



No comments: