OSX 10.9 Intel Reverse Engineering Tutorial (adapted)  

 Toolkit to get started

  1. gcc 4.9 + gdb 7.6 w/ ~/.gdbinit (or clang 5.0/llvm 3.3 + lldb 300.2.51)
  2. decent hex editor: 0xEd/Hex Fiend (gui) or od, chex, hexdump/hexedit (cli)
  3. diagnostics: otool/XCode, file, strings; inspect universal binary - moatool, lipo; OSX - class-dump v3.4
  4. Hopper Disassembler/IDA Pro

 Mac OSX Application Architecture

 Challenge.app package content structure

 Basic gdb command

 List

  1. cfa - Auxiliary carry
  2. cfc - Carry flag
  3. cfd - Direction flag
  4. cfi - Interrupt flag
  5. cfo - Overflow flag
  6. cfp - Parity flag
  7. cfs - Sign flag
  8. cft - Trap flag
  9. cfz - Zero flag

example.c

#include <stdio.h>
main(int argc, char *argv[])
{
 printf("Hello GDB!\n");
 printf("Argument is: %s\n", argv[1]);
}
0x00001fb9 in main ()
--------------------------------------------------------------------------[regs]
EAX: 00001FE1  EBX: 00001FB2  ECX: BFFFF848  EDX: 00000000  o d I t S z a p c 
ESI: 00000000  EDI: 00000000  EBP: BFFFF828  ESP: BFFFF810  EIP: 00001FB9
CS: 0017  DS: 001F  ES: 001F  FS: 0000  GS: 0037  SS: 001F
[001F:BFFFF810]----------------------------------------------------------[stack]
BFFFF860 : D2 F9 FF BF  F1 F9 FF BF - 01 FA FF BF  3B FA FF BF ............;...
BFFFF850 : 33 F9 FF BF  6C F9 FF BF - 88 F9 FF BF  C1 F9 FF BF 3...l...........
BFFFF840 : 00 00 00 00  01 00 00 00 - FC F8 FF BF  00 00 00 00 ................
BFFFF830 : 01 00 00 00  48 F8 FF BF - 50 F8 FF BF  BC F8 FF BF ....H...P.......
BFFFF820 : 00 10 00 00  BC F8 FF BF - 40 F8 FF BF  7A 1F 00 00 ........@...z...
BFFFF810 : 00 00 00 00  00 00 00 00 - 3C F8 FF BF  37 10 E0 8F ........:   mov    DWORD PTR [esp],eax
0x1fbc :   call   0x300a 
0x1fc1 :   mov    eax,DWORD PTR [ebp+0xc]
0x1fc4 :   add    eax,0x4
0x1fc7 :   mov    eax,DWORD PTR [eax]
0x1fc9 :   mov    DWORD PTR [esp+0x4],eax
0x1fcd :   lea    eax,[ebx+0x3a]
0x1fd3 :   mov    DWORD PTR [esp],eax
--------------------------------------------------------------------------------
gdb$ x/s $eax
0x1fe1 :    "Hello GDB!"
...
_main:
...
7:    +13  00001fb3  8d832f000000 leal 0x0000002f(%ebx),%eax  Hello GDB!
...
9:    +22  00001fbc  e849100000   calll 0x0000300a            _puts
...
14:   +39  00001fcd  8d833a000000 leal 0x0000003a(%ebx),%eax  Argument is: %s\n
...
16:   +48  00001fd6  e82a100000   calll 0x00003005            _printf
...

 Get cracking!

  1. Reconnaissance: program limitation & error/info messages - anything interesting?
    1. are they contained in the binary itself, or external resources/assets?
    2. refer to Apple’s documentation for methods, eg. ‘applicationDidFinishLaunching’ may contain method ‘isRegistered’
    3. look for program control flow - “good” vs. “bad” paths
  2. Solutions
    1. JE [0x74 0x2b] -> NOP [0x90]
    2. patch return value of method to always be true

 original

-(BOOL)[Level1 isRegistered]
    +0  00002a88  55       pushl  %ebp
    +1  00002a89  89e5     movl   %esp,%ebp
    +3  00002a8b  8b4508   movl   0x08(%ebp),%eax
...

gdb$ assemble

xor eax, eax
inc eax
ret
00000000  31C0  xor eax,eax
00000002  40    inc eax
00000003  C3    ret
  1. also can patch code before method invocation
...
   +22  00002534  e8252b0000 calll  0x0000505e -isRegistered
   +27  00002539  84c0       testb  %al,%al
   +29  0000253b  742b       je     0x00002568 -if not reg, show bad msg
...

gdb$ assemble @ 0x00002534

xor eax, eax
inc eax

 Patching

 Typical valid serial # gen/verify routine

-(BOOL)[Level1 validateSerial:forName:]

  1. Verify if user serial number length is ok. If ok continue, else give an error.
  2. Compute the good serial number.
  3. Compare the user serial number with the good serial number.

Serial should be 8 chars in length, as this piece of code shows:
+29 00002abb 83f808 cmpl $0x08,%eax

A quick look at the whole method and we find the piece of code we are interested in:

...
  +369  00002c0f  891c24     movl  %ebx,(%esp) 

/* Keygen for Macserialjunkies Challenge '09
   The serial algorithm has a bug because the format string has no zero padding.
   For example with the following name "zeparreco" the valid serial is 39940081
   but since there is lack of padding, the algorithm generates 399481.
   Serial length must be equal to 8 so this username is impossible to keygen due to this small bug.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>

int main(int argc, char *argv[])
{
 char name[256], *pname;
 printf("Macserialjunkies.com challenge #1 Keygen v0.1\n\n");
 printf("name:\n");
 fflush(stdout);
 fgets(name, 256, stdin);
 if ((pname = strchr(name, '\n')) != NULL)
 {
  *pname = '\0';
 }
/* serial number is composed by 8 digits
   there are two algorithms, one for the first 4 digits and the other for the remaining
*/
// first block of four digits
 int i=0;
 int digit,multiplier=4;
// mov    eax,0x68db8bad
 int wtf = 0x68db8bad;
 int accumulator=0;
 int ecx=0;
 unsigned long long temp1;
 int temp2, temp3, temp4;
 int x=0;
 int stringsize = strlen(name);
 int firstblock,secondblock;
for (x=0; x < stringsize ; x++)
{
// movsx  eax,BYTE PTR [edi+ebx]
 digit = name[i];
// inc    ebx
 i++;
// imul   eax,esi
 digit = digit * multiplier;
// add    esi,0x4
 multiplier += 4;
// shl    edx,0x4
// sub    edx,eax
 digit = (digit << 4 ) - digit;
// lea    ecx,[edx+ecx+0x29a]
 ecx = digit + ecx + 0x29a;
// imul   ecx
 temp1 = (unsigned long long) ecx * wtf; 
// this grabs the ecx value since long multiplication the result goes to EDX:EAX
 temp1 = temp1 >> 32;
// mov    eax,ecx
// sar    eax,0x1f
 temp2 = ecx >> 0x1f;
// sar    edx,0xc
 temp1 = temp1 >> 0xc;
// sub    edx,eax
 temp3 = temp1 - temp2;
// imul   edx,edx,0x2710
 temp4 = temp1 * 0x2710;
// sub    eax,edx
 ecx = ecx - temp4;
}
// the last ecx is the good first serial part
firstblock = ecx;
// second block
 i=0;
 multiplier = 4;
 int edx;
 x=0;
 ecx=0;
 int firstsar, secondsar;
for (x=0; x < stringsize ; x++)
{
//movsx  eax,BYTE PTR [edi+ebx]
 digit = name[i];
// inc    ebx
 i++;
// imul   eax,esi
 digit = digit * multiplier;
// add    esi,0x8
 multiplier += 8;
// lea    edx,[eax+eax*4]
 edx = digit + digit * 4;
// lea    edx,[eax+edx*2+0x2d]
 edx = digit + edx*2 + 0x2d;
 ecx = ecx + edx;
 temp1 = (unsigned long long) ecx * wtf;
 edx = temp1 >> 32;
 firstsar = ecx >> 0x1f;
 secondsar = edx >> 0xc;
 temp2 = secondsar - firstsar;
 edx = secondsar * 0x2710;
 temp3 = ecx - edx;
}
// 2nd part of good serial
 secondblock = temp3;
// convert to decimal and print
printf("Serial number is: %04d%04d\n", firstblock, secondblock);
}

 Future sections

More coming soon, stay tuned!

 
108
Kudos
 
108
Kudos

Now read this

How I gained access to Amazon EC2 servers from Github Search (adapted)

Github Search allows advanced filters that allow us to search for these private keys @ link. This looks for: private keys with a .pem extension “BEGIN RSA PRIVATE KEY” text that marks the beginning of a private key sorted by most... Continue →