You might be curious on how people actually do it, or you work with securing software and want to know what methods the other side use so you can better figure out how to protect you software. If so, read on.
I am by now means an expert in the area, but I recently did crack a piece of software to learn about it.
To learn about this I suggest you find a small shareware application or similar to practice on. They usually have copy protection that is weak enough to be cracked by a novice.
Tools
To be able to crack you need a number of different tools. Most of them will already be installed if you have installed Apple’s development tools.
- Interface Builder. You will use this application to poke around in the user interface of the program you wish to crack.
- otool. With this command line tool you can disassemble a file, or print
out other useful information about the executable. For instance you can use it to find out where in memory your program will be loaded. - class-dump. Command line utility you have to download. It has some of the same functionality as otool, but allows you to see Objective-C class definitions as they normally appear in the header file.
- gdb. This is our most important tool. The GNU Debugger. You will use it to trace through the program you wish to crack to find where int he code the copy protection resides
- HexEditor. To be able to patch your changes into an executable you need an editor that can edit the raw data on a file.
Knowledge
Before you can learn and do cracking you have to know some basics first.
- Objective-C. You do not need to be a wiz, but some basic knowledge of Objective-C is needed to crack a OS X program since most are written using it. At least most of the little shareware programs you find
- Interface Builder. You should have basic knowledge about how to work with interface builder.
- Assembly programming. Again no need to be great at it, or know PowerPC assembly. But you will need to get a reference over the instruction set. IBM also has a nice intro about PPC assembly.
- Know about the Mac OS X binary application interface (ABI). This you can read about in the Apple developer documentation. Info about the format of OS X executable can be found here and here.
- Most important though is to make yourself familiar with calling conventions for functions on OS X. This will tell you what the different registers are typically used for, which helps reading and understanding assembly code.
GDB crash course
To run a program through the gdb debugger. write:
gdb nameOfProgram.app/Contents/MacOS/nameOfProgram
The program has now been loaded into memory.
Commands in GDB
gdb has a lot of commands and they all have long descriptive names. You can get help about a command by writing help commandname
. However to save you typing, gdb allows you to write abbrivations for the names. You can write the first letter and gdb will choose the first command that match these letters. E.g. instead of writing print
you can write p
.
A lot of the commands will take a line number, function name, or address in memory as argument. Usually you just write the function name as it is. gdb supports command completion with tab if you don’t remember exact name. Line number can also be written directly. If you write an address you have to prefix it with *
. Example *0x00fbc
.
Useful commands:
run
Starts running the loaded programinfo fun
Gets information about a given function. Address it is located at etc.info sym
Dumps information about which segment and function the address or symbol is in. Example:
| (gdb) info sym 0x50fd0 | [StateController validState] in section LC_SEGMENT.__TEXT.__text
Says that address 0×50fd0 is in segment __TEXT and section __text.
break
Set a breakpoint at given function, line number or address.Short handb
rbreak
Set breakpoint at all functions with matching regular expressiondelete
Delete all breakpoints or breakpoint given by an index numberdisassemble
Disassemble code in current functionbacktrace
Show a stack backtrace of all functions that were called up to current function.stepi
Step one instruction at a time in code. Short handsi
where
Print out current location in code. Where the program counter is.print
Print the value of a memory location, expression or register. Short handp
po
Interpret expression as the address of a Objective-C object and print out result one would get from asString. This is used to e.g. print Objective-C strings. Since print does not allow you to do that.x
Examine memory by giving and address or register.disp
Set expression to display each time program is stopped. For instance after each break or step instruction. Use it to display registers or memory you want to follow the changes in.
You can look up more detailed explanation of each command in the gdb online help. One thing that is useful to know though is that most command that give information about memory or registers let you choose format. E.g. x/x *0x00fb
dumps content of address 0x00fb
as hexadecimal number. x/s *0x00fb
dumps contents as a c string.
Supported format types:
o
octalx
hexd
decimalu
unsignedt
binarya
addressi
instruction. Lets you interpret location in memory as PowerPC assembly instructionso
octalc
chars
stringT
OSType
Showing contenst of registers:
The PowerPC CPU has a lot of register. The most used general purpose registers are numbered from 0 to 31. To show contents of register you specify a register by writing $
and then its name. E.g. $r1
denotes the second general purpose register. $pc
is the program counter.
info register $r3
Dumps contents of register 3 and contents of memory it points to.
p $r3
Dump contents of memory pointed to by register 3.
x/x $r3
Dump contents of memory pointed to by register 3. as hexadecimal format.
Setting value of register:
You can set the value of a register using set
command. E.g. set $r3=0x44
otool
As with gdb you have to specify the path to the executable. E.g. otool -l nameOfProgram.app/Contents/MacOS/nameOfProgram
. otool has several options, you can read about them all by writing man otool
in Termina.app. However there are a few options that are of most use to us.
-l
Display load commands. This will give you information about where the different segments in the code get loaded into memory. And at which offset in your executable this segment can be found. E.g. if you look at the output you will see e.g.:
Section sectname __text segname __TEXT addr 0x00002884 size 0x0009149c offset 6276 align 2^2 (4) reloff 0 nreloc 0 flags 0x80000400 reserved1 0 reserved2 0
This tells us that this section can be found at offset (decimal) 6276 in executable. When this program is loaded into memory that section is placed at address (in hex) 0×00002884.-tVv
Disassembles the give executable and dumps to standard output.
class-dump
This is easy to use just type class-dump nameOfProgram.app/Contents/MacOS/nameOfProgram
to dump out definition of Objective-C classes in executable. When you download the file though it doesn’t come with an installer so you need to put it in your search path. E.g. I copied it directly to /usr/bin
but you have to be root user to do that. So do a sudo cp class-dump /usr/bin
e.g.
Lets get started
First thing to do is to go into the application bundle by right clicking and select Show Package Contents. Then you navigate to e.g Contens/Resources/English.lproj
. Here there will be .nib files for the user interface. I opened MainMenu.nib
. Here I found the registration sheet. I selected the register… button. Pressing shift+apple+i
brings up the inspector panel. Here I looked at the target
attribute. It shows which method the button click is connected to. Say it is called registerAction:
and exist in the AppController
. Try looking for something similar. Then you will have a starting point to start looking for the registration code.
An alternative is to use class-dump
on the executable and search for method names called something with register, serial number etc or a class nammed RegHandler, Reg or something similar. E.g. class-dump executable | grep register
.
Now that we found a method to inspect, load the executable in gdb. Type
break registerA
and hit tab to complete our method. Then we have set a break point. Type run
and out application should start running and then stop executing when it reaches our breakpoint.
When you trace through the code using stepi
you will often see lines like this:
00010070 bl 0x12e10 ; symbol stub for: _objc_msgSend
What this is a dispatching of a message to an Objective-C object. This is how methods are called in Objective-C. r3 contains pointer to object that will receive message. You can find out what kind of object it is by typing po $r3
, this will give a description of object. If object is a NSString
it will display the string. r4 contains the message selector. This basically says which method to call. The good thing about this is that the message selector also happens to be a pointer to the c string name of the method. So by typing x/s $r4
you can find out what the name is of the objective-c method being called. r5, r6.. contains the first, second… arguments of the method call. The result of the method call is returned in r3.
r1 and r30 typically points to the start of the stack. So stw
and lwz
using these registers usually access local variables in the method.
How copy protection works
Copy protection can work in many ways. But the way it worked in my case is that I register the product with a name. I then get back a serial number for that registration name from the application maker. So say I register the application on “Erik” then there will be a unique serial number associated with that name.
When the program loads it reads my registered name from a file and then performs a calculation on it. This will produce a serial number or seed that is compared with the serial number I have put into my application.
What I managed to do was to eventually locate the method that did generation of serial number or seed. I then put a break at that method and rerun the application. Then I did a backtrace
to find out which method called the serial number generator at startup.
From there on I was able to find the place where the serial number method was called and the code that compared the results afterwards.
What the code did was doing a comparison with a fixed number against the returned seed (the registered code and provided serial number are used together to produce some unique seed numbers).
In the debugger I used set
to set the registered that were compared to the exact same number they were compared against. Then I typed continue
to continue execution of code. The program now ran as registered. So it worked.
Patching
The last step to do when you have found out how to circumvent the copy protection is to change the executable (patch it). This you can do with HexEdit. The problem is to find out where in the file to make changes.
There are a number of things that are handy to know when doing this:
- Since PowerPC is a RISC processor every instruction has the same length, which is 32 bits (4 bytes). Thus you can easily calculate the number of bytes a chunk of code takes. Just multiply number of instructions with 4. This also means you can easily jump over an instruction when tracing by writing
jump *($pc+4)
- As described before you can use
otool -l
to get information about code or data segments. Using this information you can find the location of an address in memory in the file as follows:location_in_file = location_in_memory - segment_address - segment_offset
So to find the location in the executable to change, you use info sym
as mentioned before to figure out in which segment and section it is in. Then use otool -l
to find the coresponding segment and section. Then read of the offset and address to calculate location of code in the executable.
To find out what hex codes corresponds to instructions you can write a simple assembly program as below. You can just fill in the instructions you need the hex codes for.
.text
.globl _main
_main:
li r0,3241
stw r0,84(r30)
lwz r0,84(r30)
Name the file with the filename extension .s
. The file can then be compiled with e.g.: gcc newfunc.s -o temp
if your file is named newfunc.s.
You can now load your app into gdb and look at the hex code for your application by writing x/24xb main
. Which will list the 24 first bytes starting from main as hex values. 24 bytes corresponds to 24/4 = 6 instructions.
If you have any questions or comments please let me know. I will update this post later.
References
Here you can find more information:
www.phrack.org
PowerPC cracking with GDB
3 comments:
Really helpful article.
Got me a lot further than nowhere, I'm still not where I want to be, but its a start!
Thanks for the help
Business intelligence Analyst
SQIAR (http://www.sqiar.com/services/bi-strategy/) is a leading Business Intelligence company.Sqiar Provide business intelligence Services Which help the company to present Information in Meaningful form.
Nothing got into my mind
Post a Comment