Cracking Tutorial #1 - "Sandwich" CrackMe A cracking and keygenning lesson by qwertyoruiop. Hey there! This tutorial will show you how to crack the "Sandwich" CrackMe. Sandwich is a quite simple CrackMe that - Requirements: • Apple's Xcode and command line utilities (developer.apple.com) • Sandwich, an easy crackme available here: http://reverse.put.as/wp-content/uploads/2010/05/1-Sandwich.zip • An hex editor. I like to use 0xED. • Having IDA as well may be useful, but it's quite expensive. - Beginning: First of all, start the "Sandwich" application. It'll ask you to enter a serial number. Open Terminal. Run: gdb ~/Downloads/Sandwich.app/Contents/MacOS/Sandwich This will start "gdb", the GNU Debugger. The GNU Debugger is an useful utility that will let you to disassemble, add breakpoints, see the stack trace etc. in real time. It's a really useful tool. - Running Sandwich in the debugger: Once gdb is ready, it'll ask you for commands. To run Sandwich, type "run" or just "r" (gdb) r Starting program: /Users/qwertyoruiop/Downloads/Sandwich.app/Contents/MacOS/Sandwich Reading symbols for shared libraries [etc.] The application will start. - Getting symbols: For applications that were not stripped you can use "nm" to list their symbols. This is quite useful, but only a very small handful of applications are being shipped with their full symbol table. We're lucky: Sandwich did not get stripped. Open a new Terminal window/tab, and type: nm ~/Downloads/Sandwich.app/Contents/MacOS/Sandwich Since Sandwich is a fat binary containing both x86 and PPC code, it'll list both x86 and PPC symbols. We're interested in cracking the x86 code, so we'll just look at the i386 part. 00001b0f t -[SandwichAppDelegate applicationDidFinishLaunching:] 00001cdf t -[SandwichAppDelegate awakeFromNib] 00001b1f t -[SandwichAppDelegate setWindow:] 00001d0e t -[SandwichAppDelegate validate:] 00001b2d t -[SandwichAppDelegate validateSerial:] 00001b14 t -[SandwichAppDelegate window] The "-[SandwichAppDelegate validateSerial:]" method looks quite interesting. - Cracking: Let's take a look at -validateSerial:'s assembly code. Go back to gdb's terminal window. Press Ctrl+C to get back to the gdb console. This will pause the application. (gdb) Type: disas 0x0001b2d (gdb) disas 0x0001b2d 0x00001b2d <-[SandwichAppDelegate validateSerial:]+0> push %ebp [etc.] You're now looking at -validateSerial:'s assembly code. The first lines of it are called "Function Prolog". Basically, it prepares a new stack frame, it gets arguments etc. Now, if you know some x86 assembly you should notice that there are a lot of conditional jumps to 0x1cd2. Let's see what "0x1cd2" does.. 0x00001cd0 <-[SandwichAppDelegate validateSerial:]+419>: jmp 0x1cd4 <-[SandwichAppDelegate validateSerial:]+423> THIS => 0x00001cd2 <-[SandwichAppDelegate validateSerial:]+421>: xor %eax,%eax 0x00001cd4 <-[SandwichAppDelegate validateSerial:]+423>: mov -0xc(%ebp),%ebx 0x00001cd7 <-[SandwichAppDelegate validateSerial:]+426>: mov -0x8(%ebp),%esi 0x00001cda <-[SandwichAppDelegate validateSerial:]+429>: mov -0x4(%ebp),%edi 0x00001cdd <-[SandwichAppDelegate validateSerial:]+432>: leave 0x00001cde <-[SandwichAppDelegate validateSerial:]+433>: ret Hmm, xor %eax, %eax. That means that %eax will be set to 0. Seems quite interesting. Also, just before the xor you can see a jump instruction that will skip the xor. So, the only way for %eax to be 0 is to pass at least one check, causing a conditional jump to 0x00001cd2. If you understand x86 assembly quite well, you can see that the program puts a pointer to the NSString* instance containing the serial you entered on the "edi" register, and the program will send it a few messages using the Objective-C runtime. Those checks are: 1) Length: The serial you have provided to the program MUST be 19 (0x13) characters long 2) Format: The serial you have provided MUST have this format: 1111-2222-XXXX-3333 2) Mathematical rule: 0x19C5 - ((1111 + 2222) >> 2) MUST BE 3333 If any of those fail, eax will be set to 0 and the function will return. So, to crack it we must remove the "xor %eax, %eax". - Patching: Open a new Terminal window. If you're using 0xED as hex editor, type this: open -a 0xED Downloads/Sandwich.app/Contents/MacOS/Sandwich 0xED will open Sandwich's binary file. 0x00001cd2 <-[SandwichAppDelegate validateSerial:]+421> xor %eax,%eax The offset from the very beginning of the binary to the xor instruction is 0x1cd2. Use the "go to offset" function to get to 0x1cd2 You'll see something like this: 31C08B5DF48B75F88B[etc] We just have to patch the xor, nothing else. 0x00001cd2 <-[SandwichAppDelegate validateSerial:]+421>: xor %eax,%eax 0x00001cd4 <-[SandwichAppDelegate validateSerial:]+423>: mov -0xc(%ebp),%ebx So, we'll have to patch 0x00001cd4-0x00001cd2=0x2 bytes: 31C0 We can use the "no-op" instruction (aka. nop). It's opcode is 1 byte long and it's: 0x90 Since we have to patch an instruction that's 2 bytes long, we'll have to repeat the nop twice. Make sure the "Overwrite" write mode is enabled on your hex editor, and replace 31C0 at 0x1CD2 with 9090. 90908B5DF48B75F88B[etc.] Save the binary. Go back to gdb's window, type "run" at the gdb shell. (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) Type "y", press enter. Write some random serial, click on "Validate". Sandwich will tell you the serial is valid. - Exercises: If you understood this tutorial, you should try to write a keygen for Sandwich. The algorithm is trivial. Use the rules I have written earlier if you're a beginner. The keygen source is below: ----- CUT HERE ----- int main(int argc, char** argv) { short a = (unsigned int)(arc4random()) % 9999; short b = (unsigned int)(arc4random()) % 9999; short c = (unsigned int)(arc4random()) % 9999; if(argv[1]){ a=atoi(argv[1]) % 9999; if(argv[2]){ b=atoi(argv[2]) % 9999; if(argv[3]) c=atoi(argv[3]) % 9999; } } short d = 0x19C5 - ((a+b)>>2); printf("Serial: %04hd-%04hd-%04hd-%04hd\n", a, b, c, d); } ----- CUT HERE ----- You just cracked your first (and hopefully not last) CrackMe! Keep in mind that Sandwich is an easy CrackMe, but you can understand the basic concept. If you have IDA, things will be much simpler. It's just a matter of a few clicks. Have fun, ~qwertyoruiop!