Anda di halaman 1dari 4

Get krackinʼ part 2 - sniffing

In a previous tutorial we had a look at the application Pixelmator and made a simple krack for it so it
accepted anything we typed in as a license code.
Wouldnʼt it be great..if we could instead get it to accept our own valid license code?
Yes my friends, in this tutorial we will be attempting a serial sniff! :D Boom!

Introduction (you can skip this if youʼre on a PPC Mac)


In this tutorial we will just be working on the PPC side of things. This means that if youʼre on a Intel Mac you
will have to read the following to understand how to debug PPC binaries on Intel Macs: http://
developer.apple.com/documentation/MacOSX/Conceptual/universal_binary/universal_binary_exec_a/
chapter_950_section_8.html
Note that the method described by Apple only works on PPC binaries and not Universal binaries. So make
sure you get a PPC binary of Pixelmator. To do that you could use this simple terminal command:
ditto --rsrc --arch ppc /path/to/Pixelmator.app /path/to/Pixelmator-ppc.app

Hey ho, letʼs go!


Get yourself an otx dump of the PPC side of Pixelmator. In the previous tutorial we learned that the license
code was checked in the function “-(BOOL)[PXApplicationDelegate isLicenseCodeValid:]”. Go to this part of
the code and letʼs have a look.

-(BOOL)[PXApplicationDelegate isLicenseCodeValid:]
+0 0006f8ec 7c0802a6 mfspr r0,lr
+4 0006f8f0 bda1ffb4 stmw r13,0xffb4(r1)
+8 0006f8f4 7cbc2b79 or. r28,r5,r5
+12 0006f8f8 90010008 stw r0,0x8(r1)
+16 0006f8fc 9421ff20 stwu r1,0xff20(r1)
+20 0006f900 41820664 beq 0x6ff64 return;

+24 0006f904 3fc0005e lis r30,0x5e


+28 0006f908 7f83e378 or r3,r28,r28
+32 0006f90c 3bde5100 addi r30,r30,0x5100 length
+36 0006f910 809e0000 lwz r4,0x0(r30) length
+40 0006f914 4bfeff03 bla 0xfffeff00 -[r3 length]
+44 0006f918 2f830000 cmpwi cr7,r3,0x0
+48 0006f91c 419e0648 beq cr7,0x6ff64 return;

Okay, so what we see here is a call to -[r3 length] at line and then what it returns is compared to 0 (cmpwi
cr7, r3, 0x0). If the length is equal to 0 then the app branches to the end of this function (beq - branch if
equal). We can presume that the app simply checks if the user has entered anything in the license code
textfield here.

+464 0006fabc 7fe3fb78 or r3,r31,r31


+468 0006fac0 4bfeff03 bla 0xfffeff00 -[r3 length]
+472 0006fac4 2f830027 cmpwi cr7,r3,0x27 '''
+476 0006fac8 409e049c bne cr7,0x6ff64 return;

Going a bit further down in the code, past all the “replaceOccurrencesOfString:withString:options:range:”
stuff, which doesnʼt really do anything for us, we get a call to -[r3 length] again. This time it is compared to
0x27. Since everything in our output is written in hexadecimal values 0x27 doesnʼt mean itʼs compared to 27,
but 39. So now we know that the serial has to be 39 characters long!
+480 0006facc 3c80005e lis r4,0x5e
+484 0006fad0 3ca00055 lis r5,0x55
+488 0006fad4 7fe3fb78 or r3,r31,r31
+492 0006fad8 8084670c lwz r4,0x670c(r4) hasPrefix:
+496 0006fadc 38a5d484 addi r5,r5,0xd484 PIXEL-100
+500 0006fae0 4bfeff03 bla 0xfffeff00 -[r3 hasPrefix:]
+504 0006fae4 2f830000 cmpwi cr7,r3,0x0
+508 0006fae8 419e047c beq cr7,0x6ff64 return;

Now it checks if the prefix of our license code is “PIXEL-100”. This letʼs us know that the code should start
with PIXEL-100, followed by 30 more characters.

+512 0006faec 3c80005e lis r4,0x5e


+516 0006faf0 3ca00055 lis r5,0x55
+520 0006faf4 7fe3fb78 or r3,r31,r31
+524 0006faf8 80846344 lwz r4,0x6344(r4) componentsSeparatedByString:
+528 0006fafc 38a5d494 addi r5,r5,0xd494 -
+532 0006fb00 4bfeff03 bla 0xfffeff00 -[r3
componentsSeparatedByString:]
+536 0006fb04 3c80005e lis r4,0x5e
+540 0006fb08 808450bc lwz r4,0x50bc(r4) count
+544 0006fb0c 4bfeff03 bla 0xfffeff00 -[r3 count]
+548 0006fb10 2f830007 cmpwi cr7,r3,0x7
+552 0006fb14 409e0450 bne cr7,0x6ff64 return;

What this next part does is that it checks how many parts of the license code we enter is separated by
“-” (dashes) and compares this to 7. Since we already now the serial has to start with PIXEL-100, we already
got two of those parts. So with five more to go the code should look something like this PIXEL-100-XXXXX-
XXXXX-XXXXX-XXXXX-XXXXX. Itʼs not sure that code will have this exact format but this is just something
we can do if I know the length and number of dashes.

+556 0006fb18 3fc0005e lis r30,0x5e


+560 0006fb1c 38a0000a li r5,0xa
+564 0006fb20 7fe3fb78 or r3,r31,r31
+568 0006fb24 3f2038e3 lis r25,0x38e3
+572 0006fb28 3bde5f08 addi r30,r30,0x5f08 characterAtIndex:
+576 0006fb2c 3f400055 lis r26,0x55
+580 0006fb30 63398e39 ori r25,r25,0x8e39
+584 0006fb34 809e0000 lwz r4,0x0(r30) characterAtIndex:
+588 0006fb38 3b5ad4a4 addi r26,r26,0xd4a4
0ZAQ9XSW8CDE7VFR6BGT5NHY4MJU3KILO2P1
+592 0006fb3c 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]
+596 0006fb40 809e0000 lwz r4,0x0(r30) characterAtIndex:
+600 0006fb44 38a0000b li r5,0xb
+604 0006fb48 7c771b78 or r23,r3,r3
+608 0006fb4c 7fe3fb78 or r3,r31,r31
+612 0006fb50 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]

In the next part of our output is a lot of calls to -[r3 characterAtIndex:]. What this does is that it takes the
character at the given index and returns it. Worth noting is that this index starts at 0, so if the index is 4, this
will be the 5th character in the string.
The number of which index it takes the character from is stored in the register r5. You can see that 0xa (10)
is loaded into r5 (li r5,0xa) before the first call to -[r3 characterAtIndex:], so this first character it takes from
our serial is the 11th, PIXEL-100-[X]XXXX-XXXXX-XXXXX-XXXXX-XXXXX.
You might have noticed the one line that contains a lot of letters and numbers. Weʼll ignore that as it doesnʼt
really help us right now.
Now moving further down the output we get a lot of calls to -[r3 characterAtIndex:], but nothing really
happens after those calls, no values get compared. What we can figure out however is the exact format that
our license code will use since it will skip all the places where the dashes are supposed to be.
+1068 0006fd18 38a00026 li r5,0x26
+1072 0006fd1c 7c741b78 or r20,r3,r3
+1076 0006fd20 7fe3fb78 or r3,r31,r31
+1080 0006fd24 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]
+1084 0006fd28 7cbdc896 mulhw r5,r29,r25
+1088 0006fd2c 7fa0fe70 srawi r0,r29,31
+1092 0006fd30 809e0000 lwz r4,0x0(r30) characterAtIndex:
+1096 0006fd34 7c7f1b78 or r31,r3,r3
+1100 0006fd38 7f43d378 or r3,r26,r26
+1104 0006fd3c 7ca51e70 srawi r5,r5,3
+1108 0006fd40 7ca02850 subf r5,r0,r5
+1112 0006fd44 1ca50024 mulli r5,r5,0x24
+1116 0006fd48 7ca5e850 subf r5,r5,r29
+1120 0006fd4c 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]
+1124 0006fd50 7f9b1800 cmpw cr7,r27,r3
+1128 0006fd54 409e0210 bne cr7,0x6ff64 return;

This is where we start seeing something interesting. It does some math and at the end there r27 and r3 are
compared. They have to be equal or the app will branch to the end of the function (bne - branch if not equal).
We can assume that it checks one character of our entered license code here, compares it to an expected
value and doesnʼt branch if both values are the same.

It might be a good idea load Pixelmator in gdb now, if you havenʼt already done so. Enter PIXEL-100-
XXXXX-XXXXX-XXXXX-XXXXX-XXXXX in the textfield and before pressing the “License Now” button, set a
breakpoint at 0x06fd50 and we will have a look at which values are compared.

Breakpoint 2, 0x0006fd50 in -[PXApplicationDelegate isLicenseCodeValid:] ()


(gdb) p $r27
$1 = 88
(gdb) p $r3
$2 = 55

When the program stops at our breakpoint we do the following to see what r27 and r3 contains. What we do
here is use the p (print) command in gdb to see what the registers contain. The values that get returned are
ASCII character codes. 88 is the ASCII code for “X”, the character in our serial. 55 is the ASCII code for “7”,
the expected character it gets compared too.
You might be asking yourself which of the Xʼs we are comparing here. There are two ways to get past this
problem. The first and the way I prefer to do it is to simply change the Xʼs in the serial we enter to something
that is easier to find, for example PIXEL-100-ABCDE-FGHIJ-KLMNO-PQRST-UVWXY. This way we know
that if the X gets compared here we only have one of those in our serial and that means the 7 has to go
where the X is.
The other method (if we decide to keep all the Xʼs) would be to find out which of the Xʼs gets stored in r27.
To do that we have to go back in our output and find which one of the -[r3 characterAtIndex:] calls stores its
character in r27.

+680 0006fb94 38a00010 li r5,0x10


+684 0006fb98 7c701b78 or r16,r3,r3
+688 0006fb9c 7fe3fb78 or r3,r31,r31
+692 0006fba0 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]
+696 0006fba4 809e0000 lwz r4,0x0(r30) characterAtIndex:
+700 0006fba8 38a00011 li r5,0x11
+704 0006fbac 7c7b1b78 or r27,r3,r3

Going back a bit you will find this. First we know that it stores the index of the character it is going to get in
r5. So the index is 0x10 (16). It then calls -[r3 characterAtIndex:] and the character it gets is stored in r3. We
then see “or r27,r3,r3”. What basically does is moves the value in r3 to r27. So we now know that the 17th
character in the license code we entered is the X that got compared to 7.
Now getting back to that breakpoint...Now that we know what was expected at the character that was getting
compared we can either let gdb continue the execution of the app, get a beep because we entered an
incorrect license code, change the value to a correct one and click “License Now” to once again hit our
breakpoint, but this time have our entered character and the expected character to be the same.

Or..we can consume a little less time and let gdb help us:

gdb) set $r27 = $r3

This simple command in gdb will set the register r27 (our character) to have the same value as r3 (the
expected character). Doing this we wont have switch to the app and change the license code. Since weʼve
printed out the expected value earlier we can just write it down and then set r27 to be the same as r3 and
continue.

+1132 0006fd58 8041006c lwz r2,0x6c(r1)


+1136 0006fd5c 809e0000 lwz r4,0x0(r30) characterAtIndex:
+1140 0006fd60 7f43d378 or r3,r26,r26
+1144 0006fd64 7c131214 add r0,r19,r2
+1148 0006fd68 7c140214 add r0,r20,r0
+1152 0006fd6c 7ca0c896 mulhw r5,r0,r25
+1156 0006fd70 7c02fe70 srawi r2,r0,31
+1160 0006fd74 7ca51e70 srawi r5,r5,3
+1164 0006fd78 7ca22850 subf r5,r2,r5
+1168 0006fd7c 1ca50024 mulli r5,r5,0x24
+1172 0006fd80 7ca50050 subf r5,r5,r0
+1176 0006fd84 4bfeff03 bla 0xfffeff00 -[r3 characterAtIndex:]
+1180 0006fd88 7f961800 cmpw cr7,r22,r3
+1184 0006fd8c 409e01d8 bne cr7,0x6ff64 return;

Next up we get this. It looks familiar doesnʼt it? ;-) Yup, thats right. We have to repeat the same procedure
again, only a different character gets compared this time. In fact, going further down our output we see the
same procedure is gone through 10 times in total. So 10 characters of our entered serial will get compared to
expected values.

Depending on which method you used you should have ended up with either one of the following two license
codes:

PIXEL-100-XXXXX-77777-XXXXX-77777-XXXXX
PIXEL-100-ABCDE-7RG6F-KLMNO-VRG6F-UVWXY

Congrats! Both of these should be accepted as valid Pixelmator license codes. =)

Homework

1. Both of the license codes we sniffed are kinda “boring”. Sniff one that has a more “personal” touch to it.
Hereʼs an example: PIXEL-100-MATOR-V1VE4-KRACK-EN6V2-ISFUN (Easy)
2. Using what youʼve learned in this tutorial + looking up how different branches (beq, bne, ble, bgt, etc etc)
that are used in PPC asm work (use the internets for this!), you should be able to sniff a serial for
MacFamilyTree (http://www.synium.de/products/macfamilytree/) (Advanced)

This tutorial was written by Pushit in March 2008. I hope you liked it. Share The Wealth.

Anda mungkin juga menyukai