View Full Version : Learn How 2 Crack Symbian Apps, THIS IS 4 YOU BRO!!!!!



NPOWERNX
20th November 2007, 14:02
Learn How 2 Crack Symbian Apps, THIS IS 4 YOU BRO!!!!!

I found this usefil topic from another froum , though i have been reposted here
for all who intrested in such a thing

Introduction:

I have seen many beginners' tutorials in the latest few months. Since I learned
cracking from one such tutorial, this is the payback
Learn How 2 Crack Symbian Apps!!

I found this usefil topic from another froum , though i have been reposted here
for all who intrested in such a thing


All tutorials I have read until now get a program from the Internet ... and by showing
you the exact location of where to crack that program, they finish the tutorial...
I will use a different approach in my tutorials series. This approach will be a result of my
look on cracking, or if you wish as some call it: reverse engineering ...
I see cracking as: Letting a program, which is on *your* computer behave as you want it
to behave and not behave as someone else (the programmer) wants.
Hey, it is your stuff right ? your numbers, your bits, you should be able to do anything
you wish to do with it

To learn cracking, you should know how programs work. If you know how to code a few
lines, it will be alot more easier to learn cracking. So if you really want to become
a cracker, go learn how to code first. You can also learn to code from cracking

My tutorials are currently ordered in grades of difficulty. They build up on eachother.
Each tutorial will teach you something new.
Almost all basics of cracking can be found here. Read good, just the basics

I have also put up a few appendices. These consist of questions I am asked frequently,
several routine handlings you have to perform frequently and some other usefull pieces
of text.

The programs I used to crack in this tutorials series are mostly small. If they are, you can
run them from within my tutorial interface. If they aren't you can download it from the internet.

If you really want to learn cracking, just follow the tutorials from beginning to the end.
If you don't understand the things you read, just go on reading... You will understand
later. Some things will make only sense after having done it several times

You need a few tools to follow these tutorials. The first one is w32dasm. A disassembler.
You can find it all over the internet. The second one is Hiew. A freeware editor. You can
download it from public ftp's.
To find these, find a crackers tools site and get all the tools you can get... Someday you
will need them, even though you don't know yet
Get win32Dasm from the following url: [Only registered and activated users can see links]
For the other tools you can go to the following site : [Only registered and activated users can see links]
Or try TEX member Kaparo’s Programmers Tools site at: [Only registered and activated users can see links]

To crack a program ( = to become a cracker ), you have to be patient, and wanting to do it.
If you want... really want something, you can always get it

Tutor1:

The target is a program I coded in c (pure win32 code). When you run it, it tells you that it is
unregistered, and that you should register it.

STEP 1:
Run the target program. And study what it looks like. Look what it does to tell you are not registered.
Look when certain messages pop up. Look what messages you get when you enter fake serials.

Let's run the target program. It just tells you that you should register, nothing more. There is no
option to enter a serial, no option to register.

STEP 2:
Disassemble the executable. First look if you can find the messages / nags you saw when you ran the
program. Then search the program for interesting things like unregistered, thank you for registering....

Now let's look at our nice program... how was it written? I made two different dialog boxes. One which
shows extensively that you are registered and thanks you very much. The other one shows you that you
are unregistered and that you should register your program. Here is the source code for it.

This is the main function of the program:

////////////////////// Code snip ///////////////////////////
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);
BOOL IsProgramRegistered(void);
char RegistrationString[30];

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// Application starts here
if (IsProgramRegistered()) // check if program is registered
{
strcpy(RegistrationString, "REGISTERED" ); // copy a string registered for later
DialogBox(hInstance, MAKEINTRESOURCE(IDD_REGDIALOG),
NULL, RegDlgProc); // show the registered dialog
}
else // our program is unregistered
{
strcpy(RegistrationString, "*UN*REGISTERED !!!"); // copy a string for later use
DialogBox(hInstance, MAKEINTRESOURCE(IDD_BADDIALOG),
NULL, RegDlgProc); // show the unregistered dialog
}
return FALSE; // give control back to windows
}
////////////////////// Code snip ///////////////////////////


Take a look at it and try to understand how it works ... On the first line, the program calls a function with the name:
IsProgramRegistered. And depending on the result of this program it shows you the Bad dialog (IDD_BADDIALOG)
or the registered dialog (IDD_REGDIALOG).

From the function definition above we see that the IsProgramRegistered function returns a Boolean value. That is a
true or a false. So the above code is pretty much like normal speaking language.... If program is registered then show
registered dialog, else show unregistered dialog...

Now, take the case that we coded this source code, and that we wanted to make sure that the registered dialog showed
up for us ... Then we would make sure that the first piece of the code would be executed. We could do this by for
example removing the if ... else construction with the checking call to IsProgramRegistered....

then our code would look like this

////////////////////// Code snip ///////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// Application starts here
strcpy(RegistrationString, "REGISTERED"); // copy a string registered for later
DialogBox(hInstance, MAKEINTRESOURCE(IDD_REGDIALOG),
NULL, RegDlgProc); // show the registered dialog

return FALSE; // give control back to windows
}
////////////////////// code snip ///////////////////////////


If we would want to keep the if .. else intact then we could do the following..


////////////////////// code snip ///////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// Application starts here
if (IsProgramRegistered()) // check if program is registered
{
strcpy(RegistrationString, "REGISTERED"); // copy a string registered for later
DialogBox(hInstance, MAKEINTRESOURCE(IDD_REGDIALOG),
NULL, RegDlgProc); // show the registered dialog
}
else // our program is unregistered
strcpy(RegistrationString, "REGISTERED"); // copy a string registered for later
DialogBox(hInstance, MAKEINTRESOURCE(IDD_REGDIALOG),
NULL, RegDlgProc); // show the registered dialog
}
return FALSE; // give control back to windows
}
////////////////////// Code snip ///////////////////////////


Now let's look at the disassembly. Open the executable program up in w32dasm. After you disassembled it, open up
the string references by choosing: Refs->String Data Reference from the Menu. When the String References Dialog
opens, you will see all the strings that were used in this program. And of course you will find our two little strings:
"REGISTERED" and "*UN*REGISTERED !!!" back in the disassembly. Now double click on "REGISTERED" and
close the string references dialog box. You will land here in the disassembly:

////////////////////// Code snip ///////////////////////////

ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:0040106E E88DFFFFFF call 00401000
:00401073 85C0 test eax, eax
:00401075 741F je 00401096

* Possible StringData Ref from Data Obj ->"REGISTERED"
|
:00401077 6844504000 push 00405044
:0040107C 68E05E4000 push 00405EE0
:00401081 E84A000000 call 004010D0
:00401086 83C408 add esp, 00000008
:00401089 6A00 push 00000000
:0040108B 6803104000 push 00401003
:00401090 6A00 push 00000000

* Possible Reference to Dialog: DialogID_0065
|
:00401092 6A65 push 00000065
:00401094 EB1D jmp 004010B3

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401075(C)
|

* Possible StringData Ref from Data Obj ->"*UN*REGISTERED !!!"
|
:00401096 6830504000 push 00405030
:0040109B 68E05E4000 push 00405EE0
:004010A0 E82B000000 call 004010D0
:004010A5 83C408 add esp, 00000008
:004010A8 6A00 push 00000000
:004010AA 6803104000 push 00401003
:004010AF 6A00 push 00000000

* Possible Reference to Dialog: DialogID_007B
|
:004010B1 6A7B push 0000007B

////////////////////// Code snip ///////////////////////////



What do we see here?

:0040106E E88DFFFFFF call 00401000 ; call IsProgramRegistered
:00401073 85C0 test eax, eax ; eax equal to zero ?
:00401075 741F je 00401096 ;if eax is equal to zero jump, else dont


There is a call made to address 401000. After this call the program checks if the value of eax is equal to zero.
Depending on this test, it decides to jump or decides not to jump to address 401096. Well if we look good, we
can recognize the if.. else construction in these three lines :-)

If we follow the jump to 401096 (you can do this in wdasm by double clicking on the line :00401075 and by choosing
Execute Text -> Execute Jump from the menu. ) We will see that we end up at the place where the "*UN*REGISTERED!!!" string shows. The thing is, we never want to get there! So what would be the most logical
thing to do? To make sure this jump was never executed. So if we removed this jump, our program would always
display the Registered dialog. That would be cool. Our program would look like the second version of the code we
wrote. If IsProgramRegistered Then ShowRegisteredDialog Else ShowRegisteredDialog :-)

So, we are going to remove the jump. It is not possible to just remove it. Instead in cracking we use some other tricks
to reach the same effect. The nicest to do in this case is replacing the JE instruction with NOPs. NOP stands for no
operation, so if this code is executed there will nothing happen (for +/-2 milliseconds) and the program will go on with
showing the Registered dialogbox :-)

STEP 3:
Open up a copy of the program in HIEW and patch the needed bytes. Drag a copy of the program you want to
crack on top of hiew and drop it. This will open the program in hiew. This can be done fastest if you have
a shortcut on your desktop. Every time you want to open a program in hiew, you drag it and drop it on top of the
shortcut to hiew, and the program to crack will open in hiew. Now switch back to wdasm. Go and stand on the line
you want to patch. Now look in the bottom (Status Bar) of w32dasm.

[Only registered and activated users can see links]

The important number here to remember is 475, the Offset number.
Now switch back to Hiew. Press Enter twice. This will get you into Decode mode of Hiew. (This mode can also be
accessed through choosing F4). Now you are in decode mode, you can type in the offset you want to go to. Push F5 and
type in 475. When you press enter you will land straight at the place you also saw in wdasm.


You should now stand right on this line in hiew:

ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

.00001075: 741F je .000001096 -------- (1)
.00001077: 6844504000 push 000405044
.0000107C: 68E05E4000 push 000405EE0
.00001081: E84A000000 call .0000010D0 -------- (2)
.00001086: 83C408 add esp,008
.00001089: 6A00 push 000
.0000108B: 6803104000 push 000401003


If you scroll up you will also see the call and the test. Now push F3 (Edit) and then F2 (Assemble). Now we are going
to assemble a new instruction instead of the JE instruction. Now type in NOP and press enter.

ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

00000475: 90 nop
00000476: 1F pop ds
00000477: 6844504000 push 000405044
0000047C: 68E05E4000 push 000405EE0
00000481: E84A000000 call 0000004D0
00000486: 83C408 add esp,008
00000489: 6A00 push 000
0000048B: 6803104000 push 000401003
00000490: 6A00 push 000
000
000 +- Pentium(R) Pro Assembler -------------------------------------+
000 ¦ pop ds________________________________________________ __ ¦
000 +----------------------------------------------------------------+
000


Hiew now assembled a nop instruction. But you see that not everything went the same as we wanted it to... The je
.000001096 went away ... but the side effect of this is that we got another instruction which wasn't meant to be there
and which unlike our nop instruction does something with the program memory.... If we look good, we can see that
the machine code of je is 741F .... However the machine code of nop is 90 ....... What happened when we assembled
the nop instruction instead of the je instruction ? The nop instruction replaced the 74 of the je instruction, but the rest
of the je (1F) remained intact and was reassembled into a pop ds instruction by hiew. To fix this unwanted side
effect, we assemble another nop instruction which overwrites the pop ds instruction. and we have the effect we want :-)

Now your code should look like this:

.00001075: 90 nop
.00001076: 90 nop
.00001077: 6844504000 push 000405044
.0000107C: 68E05E4000 push 000405EE0
.00001081: E84A000000 call .0000010D0 -------- (1)


Now, to get out of the assemble mode we push escape once. And to save the modification we press F9. Press F10 to
close hiew.

Now run the program and enjoy the power of letting your programs behave the way you want them to behave!


Tutor2:

In this tutorial we are going to start taking a look at registration possibilities...
We will again be looking at another program I coded.
Step 1 : Run the program
You will see a nice dino :-) Nothing says you are unregistered ... or tells you you are registered...
Well .. check out the help menu, ah... a register option :-) Select it ... and you will see another
dialog box pop up ... In this one you can enter your name and serial ....
Do so, enter your name and a random serial and press ok... hmmm.. it tells you that you entered
a wrong serial .... It also asks you to reenter it please ....

Step 2: Disassemble the program.
When you disassemble this program, and look in the string references, (Refs->String Data References)
you will see a few strings about registration... Some of em you already have seen... The one that complains
about a wrong serial name combination... But you see that there is a possibility to get a Thank you message :-)

Double click on the "you entered an invalid serial" string ... and you will land right in the middle of the
registration routine of the program.

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:004013B7 55 push ebp
:004013B8 89E5 mov ebp, esp
:004013BA 833D0020400000 cmp dword ptr [00402000], 00000000
:004013C1 7416 je 004013D9
:004013C3 6A40 push 00000040

* Possible StringData Ref from Data Obj ->"Registered"
|
:004013C5 68E8404000 push 004040E8

* Possible StringData Ref from Data Obj ->"Thank you for registering ..."
|
:004013CA 68F3404000 push 004040F3
:004013CF FF7508 push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:018Ah
|
:004013D2 E821030000 Call 004016F8
:004013D7 EB14 jmp 004013ED

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004013C1(C)
|
:004013D9 6A10 push 00000010

* Possible StringData Ref from Data Obj ->"Error in Entry "
|
:004013DB 686E404000 push 0040406E

* Possible StringData Ref from Data Obj ->"You entered an invalid serial "
->"/ name combination ...please check "
->"your entry thoroughly and try "
->"to reenter"
|
:004013E0 687E404000 push 0040407E
:004013E5 FF7508 push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:018Ah
|
:004013E8 E80B030000 Call 004016F8

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004013D7(U)
|
:004013ED 5D pop ebp
:004013EE C3 ret
////////////////////// Code snip ///////////////////////////


If you quickly look at this piece of disassembly, you will easily understand what
is going on ... A part of this code is able to tell you that you are registered, and thanks you for it.
The other part can tell you that you entered a wrong number / name combination.
In some pseudo-code it would look like this :

If correctserial then tell em thank you
else tell em wrong serial

The c-code looked as following :

////////////////////// Code snip ///////////////////////////
void DoFakeCheckRoutine(HWND hDlg)
{
if (registered ) MessageBox(hDlg, "Thank you for registering ...\r\n"
"We will be thankfull to you for the rest of our lives !",\
"Registered", MB_ICONINFORMATION);
else MessageBox(hDlg, "You entered an invalid serial / name combination ..."
"please check your entry thoroughly and try to reenter",
"Error in Entry ", MB_ICONERROR );
}
////////////////////// Code snip ///////////////////////////


No big deal right ? the thing is we have to find the place where the decision is made... That is luckily
not that different either ...

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS
:004013BA 833D0020400000 cmp dword ptr [00402000], 00000000
:004013C1 7416 je 004013D9
:004013C3 6A40 push 00000040

* Possible StringData Ref from Data Obj ->"Registered"
|
:004013C5 68E8404000 push 004040E8

* Possible StringData Ref from Data Obj ->"Thank you for registering ..."
////////////////////// Code snip ///////////////////////////

The je 004013D9 at address 4013C1 is the instruction that controls the flow of the program. If you manipulate
this instruction, you will have control over the code :-)
And now in simple English : If you make sure the processor never executes the je instruction, you will be registered :-)
to prevent this je instruction from occuring, the best way is to nop it.

Step 3: Open the program in Hiew and Patch it:
Drag and drop a copy of your tutor2.exe on top of hiew, so that it opens in hiew. Now go stand on address
[Only registered and activated users can see links]
Switch over to Hiew. Get into decode mode by pressing Enter twice. Now press F5 and enter 7C1 and you will land
right on top of the je instruction.
Modify the je instruction by first pressing F3 then F2 and then reassembling 2 NOP instructions. Press Esc once and then F9 to save your changes. Verify that your changes are correct ... Hiew should look like this :
////////////////////// Code snip ///////////////////////////
ADDRESS:MACHINE CODE ASSEMBLER INSTRUCTIONS

000013C1: 90 nop
000013C2: 90 nop
000013C3: 6A40 push 040
000013C5: 68E8404000 push 0004040E8
000013CA: 68F3404000 push 0004040F3
000013CF: FF7508 push d,[ebp][00008]
000013D2: E821030000 call .0000016F8 -------- (1)
000013D7: EB14 jmps .0000013ED -------- (2)
////////////////////// Code snip ///////////////////////////
Then press F10 to exit hiew.

Step 4: Verify your crack:

Run the program and go through help -> register and enter any name and serial ... and press enter ...
Look what happens :-)) And enjoy your power ... Enjoy the power to control !


Extra:
Do you think these first two programs I coded and we cracked are too easy ? They are nothing compared to real life programs ??
Believe me, if you have understood the last two tutorials, and successfully followed every step, you can crack 60% of
all shareware applications availble on the internet ... All you need is : a little practice ...
Don't you believe me ? Read the Next tutorials... We will be cracking a few shareware apps... And you will see that they are very much like the first two apps we cracked :-)


Tutor3:

Welcome to tutorial 3...
In this tutorial I will try to recapitulate the things we have learned in the first two tutorials...
Also we will be handling a few real world applications...

Recapitulation:

What did we learn in the previous tutorials?
That cracking is a way which lets you make programs on your computer behave as you want
it to behave ... and not as someone else wants...
That there are several steps to go through while cracking each program which are:

Watching the standard behavior of the program.
Disassembling the program.
Finding Strings in the disassembly that we recognize from phase 1
Finding the protection routine
'Understanding' the jumping mechanism of the protection
Changing the original program, so that it always behaves as you want it to
run it and feel the power you have ... The power knowledge gives you :-)

These are all steps which you have to go through... over and over again ... Until you get bored...
Untill you can dream of the sequence of key-strokes you have to perform while patching an exe..
Until you start feeling the protection routine ... It is the only way to become a good cracker...

The Target:

So for a little exercise, let's crack a few programs
The target is High Logic's Font Creator Program. ([Only registered and activated users can see links])

Step 1: Run the program:

Run it ...
You will see a cool splash....
then a dialog box ... It says: "This product is not registered"
Telling you how and where to register.... Lower right panel says 'Unregistered'....
That is interesting of course.

Now let's Check out for registration options....
Under help, you can select register...
Try to enter a fake name and serial ... look what it does....
"Registration Failed: Invalid Password ".
That is the exact message we get....
We know enough :-)
Close the program....


Step 2: Disassemble the program:

Make a copy of fcp.exe, and call it fcp.org (original)...
Fire up your W32Dasm and open FCP.ORG... It takes a while to decompile this baby...
When W32Dasm is done with disassembling, open the string references list...
(Refs-> String Data Refs or the "strn Ref" button)
Let's search for familiar strings, like: This product is unregistered, Registration Failed,
Thank you for registering....

Indeed, when we scroll down the alphabetically arranged string references, we come
across the string: Registration Failed.... Go stand on it ... and double click it...
Now you can close the string references window....

Step 3: Analyzing the protection routine.... / Understanding the jumping Mechanism...

When we scroll up a bit, we see another string: "Thank you for registering..." right above
this we see a call at line 0048AD23 ... Right after this call, we see a jne command....
go stand on it, and execute the jump ... You see that it lands right on the line which
says you are unregistered. Now press the [ret jmp] button to return to the previous place....
We see that if the code does not jump, it thanks you for registering. If it jumps, it shows
you, you entered an invalid serial...

We found the code that is executed so we see the dialog box that pops up when we type in
an invalid serial.... This code also shows there is a dialog box that pops up when a valid serial
is entered.... We want this piece of code to behave as following: Show registered when valid
serial is typed and show registered when invalid serial is typed...

Now let's take a closer look at the disassembly....

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:0048AD23 E8FC90F7FF call 00403E24
:0048AD28 7524 jne 0048AD4E
:0048AD2A 6A00 push 00000000
:0048AD2C 668B0D9CAD4800 mov cx, word ptr [0048AD9C]
:0048AD33 B202 mov dl, 02

* Possible StringData Ref from Code Obj ->"Thank you for registering the "
->"Font Creator Program."
|
:0048AD35 B8A8AD4800 mov eax, 0048ADA8
:0048AD3A E8D97EFBFF call 00442C18
:0048AD3F 8B45FC mov eax, dword ptr [ebp-04]
:0048AD42 C7805001000001000000 mov dword ptr [ebx+00000150], 00000001
:0048AD4C EB22 jmp 0048AD70

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0048AD28(C)
|
:0048AD4E 6A00 push 00000000
:0048AD50 668B0D9CAD4800 mov cx, word ptr [0048AD9C]
:0048AD57 B201 mov dl, 01
* Possible StringData Ref from Code Obj ->"Registration failed: Invalid Password"
|
0048AD59 B8E4AD4800 mov eax, 0048ADE4
////////////////////// Code snip ///////////////////////////

A translation that is the same looks like this...
__________________________________________________ _________________________
call IsSerialValid
jne serial_not_valid
call MessageBox_Thanks_for_registering
jmp End

serial_not_valid:
call MessageBox_Serial_Invalid

End:
__________________________________________________ _________________________
In plain human language this would be like:

If Serial Is Not Valid, Tell Serial Is Invalid,
else Thank You For Registering...

Since we want it to Thank us for registering always, we make sure the jne Serial_Not_Valid
jump is never executed .....
when we do this te pseudocode will look like this:
__________________________________________________ _________________________
call IsSerialValid
XXX xxxxxxxxxxxxxx ; serial_not_valid removed ...
call MessageBox_Thanks_for_registering
jmp End

serial_not_valid:
call MessageBox_Serial_Invalid

End:
__________________________________________________ _________________________

The call at 0048AD23 is executed, after this, there will never be a chance to jump to the
invalid serial messagebox :-)


Step 4: Changing the original program...

Same as before: Load FCP.exe in HIEW.... Press enter twice so you get into disassembly mode.
push F5 to enter the address ... and when you are there, change the JNE into two NOP commands
Now press F9 to save and F10 to exit....

Step 5: Run the program, and register with any name and serial :-))
Do you feel it? Do you feel the power it gives you?



__________________________________________________ _________________________

Extra !

When we were looking through the string references list, we also saw the other unregistered
string we had paid attention to ... The "This product is not registered" string we saw in
the dialog box that pops up at startup.... Since we are here to learn, and we don't want to
miss any opportunity, let's take a closer look at it....

Locate the string again in the String references in hiew...
"This product is not registered." Double click it and you will land in the code below....

////////////////////// Code snip ///////////////////////////

ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:00476565 E836DFFAFF call 004244A0
:0047656A A10CB54B00 mov eax, dword ptr [004BB50C]
:0047656F 83781800 cmp dword ptr [eax+18], 00000000
:00476573 753B jne 004765B0

* Possible StringData Ref from Code Obj ->"This product is not registered."
|
:00476575 BADC694700 mov edx, 004769DC
:0047657A 8B45FC mov eax, dword ptr [ebp-04]
:0047657D 8B800C020000 mov eax, dword ptr [eax+0000020C]
:00476583 E818DFFAFF call 004244A0

* Possible StringData Ref from Code Obj ->"Registration fee is US $20 for "
->"a single license."
|
:00476588 BA046A4700 mov edx, 00476A04
:0047658D 8B45FC mov eax, dword ptr [ebp-04]
:00476590 8B8010020000 mov eax, dword ptr [eax+00000210]
:00476596 E805DFFAFF call 004244A0

* Possible StringData Ref from Code Obj ->"Read the helpfile for more |
:0047659B BA406A4700 mov edx, 00476A40
:004765A0 8B45FC mov eax, dword ptr [ebp-04]
:004765A3 8B8024020000 mov eax, dword ptr [eax+00000224]
:004765A9 E8F2DEFAFF call 004244A0
:004765AE EB13 jmp 004765C3

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00476573(C)
|
* Possible StringData Ref from Code Obj ->"This product is registered to:"
|
:004765B0 BA706A4700 mov edx, 00476A70

////////////////////// Code snip ///////////////////////////

"Play" again with the jumps and you will see what happens with the jumps...
When you are done jumping and looking a bit at the disassembly, you should be able
to see that the disassembly can be brought back to the simple pseudo code below....
__________________________________________________ _________________________
CODE COMMENT

Call Is_Program_Registered
cmp memory location , 0000 ; compare memory location to zero
jne Program_Is_Registered ; jump to program is registered label

Print_Program_Is_Not_Registered
Print_Registration_Is_20$_Only
Print_Read_Help_for_More_Info
jmp Finish ; jump to where the finish label is


Program_Is_Registered: ; this is just a label / an address ...
Print_Program_IS_Registered
Print_Registered_to

Finish: ; this is the finish label ...
__________________________________________________ _________________________


This pseudo-code is a lot more readable for us newbies ;-)
Well... what happens is: there is again a check ... If the program is registered...
After that it compares a memory location to zero.... hmmm.. Why would it do something
like this? We'll see that in a second ... Then it jumps if this memory location is
not equal to zero, and it doesn't jump when it is zero...
What would this mean for us crackers? Yup... this memory location should *always*
be unequal to zero :-) That means it should contain a value like 1, 2 or 1000...
not the value 0....


The source would have looked something like this:


////////////////////// Code snip ///////////////////////////

BOOL programregistered; // a boolean variable ...
// these variables contain a true or a
// false value ... ( a 0 or a 1 )

programregistered = IsProgramRegistered(); // a function call ...
// the function returns its value to
// the boolean variable programregistered

if (programregistered = TRUE)
DoNotNag() ;
else
DoNag();

////////////////////// Code snip ///////////////////////////


This piece of code shows us that programs can set a memory location ( the programregistered
bool variable is a memory location) to determine the state of your registration....
That is what happens in this piece of code ... And also what happens in the real program...

Now we do understand that the memory location above is equal to 1 if you are registered, and
is equal to zero if you are not registered.... To crack this piece of code = to make it
always think it is registered, we could change the memory location to 1, so the program
always thinks we are registered.... Is this very easy to do? Well.... Not now :-)
I will show it to you in tutor 3...

The easiest would be to modify the "jne Program_Is_Registered" in such a way that
the program always thinks we are registered... No matter what the call Is_Program_Registered
puts in memory location that has to be equal to something NOT zero...
The easiest way to do this would be to change the jne into a jump instruction.
And this is a piece of cake :-))

Open the program in hiew; Go to the right offset in the program.... Change the jne into a
jmp.... What happened?
__________________________________________________ _________________________
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

ORIGINAL

00476573: 753B jne .0004765B0 -------- (1)
00476575: BADC694700 mov edx,0004769DC ;" Gi_"
0047657A: 8B45FC mov eax,[ebp][-0004]
0047657D: 8B800C020000 mov eax,[eax][00000020C]
00476583: E818DFFAFF call .0004244A0 -------- (2)
00476588: BA046A4700 mov edx,000476A04 ;" Gj "

PATCHED

00476573: E938000000 jmp .0004765B0 -------- (1)
00476578: 47 inc edi
00476579: 008B45FC8B80 add [ebx][0808BFC45],cl
0047657F: 0C02 or al,002 ;" "
00476581: 0000 add [eax],al
00476583: E818DFFAFF call .0004244A0 -------- (2)
00476588: BA046A4700 mov edx,000476A04 ;" Gj "
__________________________________________________ _________________________


The jmp hiew assembled, looks a bit weird ... It needed 3 extra bytes....

753B jne .0004765B0 <<-- jne (2 bytes 75 3B)
E938000000 jmp .0004765B0 <<-- assembled jmp(5 bytes E9 38 00 00 00 )




That is not so nice :-( Now we altered some code we did not want to alter at all...
The mov edx, 0004769DC line of code is gone.... And something else has come in place...
Well ... Actually there is no need to worry....
The code we altered here will *never* be executed.... We made sure that it would never be ;-)
We made sure that anything that comes to line 476573 jumps *DIRECTLY* to line 4765B0 :-))
so the code at the lines between 476578 and 4765B0 are never executed ... Those are the lines
which tell us we are not registered :-)


There may be several things you haven't fully understood but that's not important here, you will
as we do more tutorials together.


__________________________________________________ _________________________


What we did in this tutorial?

We saw that there are several standard steps that you will have to go through while cracking.
-- watching a program in action
-- disassembling the program and looking for familiar strings
-- finding and analyzing the protection routine of the program
-- Modifying the program so it does the thing you want.
While going through these steps we make extensively use of our Tools: Hiew and WDasm...
-- Disassembling and Finding string references. Simulating the jumps which take place during execution
of the program.
-- Finding the corresponding address in Hiew, assembling assembler instructions in Hiew.
We also saw that programs can keep a boolean value in memory to determine if you are registered or not.



Tutor4:

We need some more practice:-)
Let's remember the to do routine stuff again....

watching a program in action
disassembling the program and looking for familiar strings
finding and analyzing the protection routine of the program
Modifying the program so it does the thing you want.

Well... The essence of cracking brought back to 4 sentences ;-) Let's do another one...

The program we are going to take a closer look at this time will be: Sweet Little Piano [Only registered and activated users can see links]

Step 1: Run the program:
Run it.
Cool. Fast and small
Bah. Two text files ...
A very big Unregistered Shareware on the caption bar...
Check out the Help menu for registration options ... Hmm... a Password option... Select it and enter just something
to see what happens ... Click on OK.. nothing....
Maybe it accepted it? hmm.. no ... the caption bar still says Unregistered....
Ok close it ... bah ... more text files ... and a notification that the settings are not saved in the unregistered version ... well ... kind of irritating those text files !
Let's fix it :-)


Step 2: Disassemble the program:
Disassemble the program. Good, small is fast :-) Always....
Now, we don't have any strings that pop up when we want to register something...
Let's browse for strings like registered, unregistered, the string about the unsaved settings.
hmm... evaluation time left ... password.txt.... passworddialog....
sweet little piano - Unregistered <<-- looks like our caption bar ;-) go on...
Thanks for registering ... cool! So it thanks you anyway :-)
Let's jump to the place ... Double click on it an we will land right on top of the registration registration routine...

Step 3: Analyzing the protection routine.... / Understanding the jumping Mechanism...
Let's analyze the protection routine.

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

* Possible Reference to Dialog: PASSWORDDIALOG, CONTROL_ID:0064, ""
|
:00401715 6A64 push 00000064
:00401717 53 push ebx

* Reference To: USER32.GetDlgItemTextA, Ord:0000h
|
:00401718 E8A5B50000 Call 0040CCC2
:0040171D E822FFFFFF call 00401644
:00401722 85C0 test eax, eax
:00401724 741E je 00401744
:00401726 6A30 push 00000030

* Possible StringData Ref from Data Obj ->"SweetPiano"
|
:00401728 6866D24000 push 0040D266

* Possible StringData Ref from Data Obj ->"Thanks for registering!"
|
:0040172D 68FED14000 push 0040D1FE
:00401732 53 push ebx

////////////////////// Code snip ///////////////////////////

PasswordDialog ... a call to GetDlgItemTextA ... Another call.... a test...
and depending on the test a je.... The je jumps over the thank you ...
And just ends the dialog box ... without telling you that you entered something wrong...
So this is right ... we did indeed not see that we typed something wrong ... but apparently we are supposed to see
if we type something right :-)

Again execute the je jump, and look where it goes to ... return from the jump....
Now lets try to rewrite what goes on here...

__________________________________________________ _________________________
call ShowPasswordDialog
call GetEnteredText
call IsEnteredTextGood
test value in eax
je QuietExit

ShowThanksForRegistering

QuietExit:
__________________________________________________ _________________________

the source code must have looked like this :
__________________________________________________ _________________________
GetDlgItemText(_ID_Serial);
if (EnteredTextGood) ShowThanksForRegistering

// else nothing....
__________________________________________________ _________________________

This is another interesting piece of code.... test eax, eax ... This assembler instruction tests if the value of eax is equal to itself ... If it is it is equal ... so a je instruction jumps ... if it is not equal, it does not jump....
To crack this program we can change the je instruction into two nop instructions... and we are done...



We have seen here, that the call has put a value in eax.... something which is not equal to zero or a zero... In our
previous example we saw that the called Is_Serial_Valid call set some value in memory ... Here we see that the called
Is_Serial_Valid call sets the eax register of our processor to some value....

Step 4: Changing the original program...
So modify it :-)
Open Hiew ... you know the rest by now...


Tutor5

In the previous 4 tutorials we have handled the basics of cracking ...
We have summarized the basics of cracking into the following few points:
Watching a program in action
Disassembling the program and looking for familiar strings
Finding and analyzing the protection routine of the program
Modifying the program so it does the thing you want.

In this tutorial I will show you how to insert your own code into the original programs code, so that the
program does exactly what you want it to do ;-)

To show you how to do it, I have again written my own program. First I will show you how to crack the
program I made, afterwards, we will together crack a commercial program, which has almost the same
protection as my little 20 kb exe ;-)

We will again do the cracking as we have learned ... systematically.

Step 1: Run the program:
Our cool dino again :-) but what do we see there ? A very ugly caps:
**UNREGISTERED EVALUATION** - Tutorial 3 ...
Man I hate caps ;-)

Let's explore the file menus…
Hmm.. The Help menu has a register option. Select it. Enter a fake name and a Serial. Press Ok.
Hmm.. An ugly error message :-)
Let's fix it …

Step 2: Disassemble the program:
When we disassemble and look at the string references, we see a few of the strings that we can
recognize. The big ugly caps Unregistered string, the error while entering password string….
Let's select the: Error entering name / password, string…. We will land in the following piece of
disassembly:


////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00401521(C)
|

* Possible StringData Ref from Data Obj ->"**UNREGISTERED EVALUATION** - "
->"Tutorial 5"
|
:00401546 68E6404000 push 004040E6
:0040154B FF7508 push [ebp+08]

* Reference To: USER32.SetWindowTextA, Ord:020Ch
|
:0040154E E8D1020000 Call 00401824
:00401553 6A10 push 00000010

* Possible StringData Ref from Data Obj ->"ERROR"
|
:00401555 6840404000 push 00404040
You will land here
* Possible StringData Ref from Data Obj ->"Error entering name / password, "
->"please retry "
|
:0040155A 6846404000 push 00404046
:0040155F FF7508 push [ebp+08]

* Reference To: USER32.MessageBoxA, Ord:018Ah
|
:00401562 E899020000 Call 00401800
////////////////////// Code snip ///////////////////////////

Step 3: Analyzing the protection routine.... / Understanding the jumping Mechanism...

Let's try to understand this piece of code…..
The code is executed after a jump from address 401521. What it does is: setting the text
UNREGISTERED EVALUATION. After it has done this, it pops up a Message box telling you
that you have entered the wrong name / password combination.
Well … Let's go back to where the decision was made … Address 401521 ….
Go to code location 401521 (see Appendix 1 for how to).

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:0040150E 89D7 mov edi, edx
:00401510 09C0 or eax, eax ; length of entered name zero ?
:00401512 7459 je 0040156D
:00401514 FF7508 push [ebp+08]
:00401517 E8CFFEFFFF call 004013EB ; check something
:0040151C 83C404 add esp, 00000004
:0040151F 09C0 or eax, eax ; is eax zero ?
:00401521 7423 je 00401546 <<-- You will land here …
; jump to unregistered dialog…

* Possible StringData Ref from Data Obj ->"Registered Version - Tutorial 5 "
|
:00401523 680F414000 push 0040410F

////////////////////// Code snip ///////////////////////////
__________________________________________________ _________________________

What we see here is pretty familiar to us by now. This je jumps over the piece of code, which tells
us that we are registered. After this, the other code is executed.
In pseudo-code the above piece of code would look something like the following :
__________________________________________________ _________________________

if SerialIsValid ShowThankYouForRegistering
else ShowWrongSerial
__________________________________________________ _________________________

We know now what to do :-)… Let's change the jump to NOP's. Then this program will always
show us that we are registered :-) easy huh ?

Step 4: Changing the original program...
Open a copy of the program in hiew and change the je you see into two nops. Just as we did in our very first tutorial.
Piece of cake…..

Step 5: Testing your cracked program...
Let's run it. Go to the registration dialog box. Enter a fake name and serial combination.
Yes !! we are done :-)
It registered us ….Look how nice the ugly caps disappeared from the title bar…. It now says registered version :-)
I hear you think… Was it this easy ?? Is Intern not going to learn us anything new this tutorial ??
Well … In fact you are learning now … That you always should test your crack before spreading it / giving it away to others.
Ok close the program. And restart it… :-( Look … The ugly caps is still there …..
How depressing …. Probably we overlooked something while analyzing our routine …
Let's look a little bit close at the disassembly …
__________________________________________________ _________________________

Step 3, Second Try : Analyzing the protection routine.... / Understanding the jumping Mechanism...

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:0040150E 89D7 mov edi, edx
:00401510 09C0 or eax, eax ; length of entered name zero ?
:00401512 7459 je 0040156D
:00401514 FF7508 push [ebp+08]
:00401517 E8CFFEFFFF call 004013EB ; check something
:0040151C 83C404 add esp, 00000004
:0040151F 09C0 or eax, eax ; is eax zero ?
:00401521 7423 je 00401546 <<--You will land here …
; jump to unregistered dialog…

* Possible StringData Ref from Data Obj ->"Registered Version - Tutorial 5 "
|
:00401523 680F414000 push 0040410F

////////////////////// Code snip ///////////////////////////

This code looks something like this in c :

////////////////////// Code snip ///////////////////////////

if (strlen(name) != 0 ) {
if ( CheckTheSerialAndName() == TRUE ){
MessageBox( "Thank you for registering ");
}
else{
MessageBox( "Entered a wrong serial");
}
}

////////////////////// Code snip ///////////////////////////
__________________________________________________ _________________________
Well … you probably did notice that the call at address 401517, which I commented as :
Check Something is the CheckTheSerialAndName function …

We made this check for name serial combination totally useless after we removed the jump at
address 401521. But what happens here is, this function is also called at another time from another
place. Programmers write a function like this once, and like to call it at times when they need to
decide whether you are a registered or an unregistered user. These moments are usually at the
moment you try to register with a name and a serial number. And the next moment is when the
program starts, when it wants to display a nag, or wants to set title bars or wants to determine if
your trial time is up ….
This type of functions you will encounter very often.

Let's trace into the call. At the beginning of the function you will see this:

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

* Referenced by a CALL at Addresses:
|:00401292 , :00401517
|
:004013EB 55 push ebp
////////////////////// Code snip ///////////////////////////


This means this function is called from two adressess… from : 00401292 and from 00401517.
If you push the ret button, to go back to the place we traced into the call, you will see that the call
that we see is at 401517. That means this function is also called from address 401292.
Let's go to this address.

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:00401292 E854010000 call 004013EB ; isnameserialvalid ?
:00401297 83C40C add esp, 0000000C
:0040129A 09C0 or eax, eax ; eax = 0 ?
:0040129C 740D je 004012AB ; jump to not registered

////////////////////// Code snip ///////////////////////////

hmm… see … This piece of code is almost the same :-)

If we nop out the je here, we will be done… let's do it.
Step 4, second try: Changing the original program...
Load the program in hiew, and nop the je instruction …

Step 5, second try: Testing your cracked program...
Run it … and yup :-) It works ….
We did it …

__________________________________________________ _________________________
Afterthoughts :

In this case we had to nop two jumps. Sometimes some programmers call the IsSerialValid routine
several times …Sometimes you will see a list of 20 references :-) ( just seen it once )
We could try to locate all the separate jumps, and noping them … But a cleaner and much more
elegant way of fixing this small problem would be the following :

Writing your own code :-)
How ?
We know that the functions of this type usually return a value back. A value like false or true…
In the disassemblys you will see that after a call, one of the registers is being checked. ( see also
tutorial 3 ). In this program the register eax is checked. And you will see that in almost all cases the
eax register is checked. So a function call like : IsSerialValid returns a value in eax. A zero or a one.
What we can do to fix the problem is making this function return the value we want in eax :-)

To do this you have to assemble a few assembler instructions in Hiew. Let's practice on this program.
Delete your cracked version, and make a copy of tutorial5.exe
Open it in hiew. Go to the beginning of the call at address 4013EB.

Now enter assemble mode, and assemble the following instructions.

////////////////////// Code snip ///////////////////////////

mov eax, 1 ; make eax equal to 1
ret ; return to caller

////////////////////// Code snip ///////////////////////////

Apply the changes, save the file and run it.

Cool huh ? we have a registered version now. The function always returns a 1 in eax now meaning
the serial is valid !
And you only had to patch it at one address :-)

What happens now is this, the function is called, and it immediately returns a 1 in eax without doing
its usual complicated stuff to check the entered serial.

In this tutorial we have seen that you always have to check if the patch you applied works.
We also saw that registration routines are written once, but used often by programmers. ( they call it
code-reuse, but we call it lazy programmers ;-) ) Usually such registration routines will be called at
program startup and while checking an entered name / serial combination.
Finally we saw that we can write our assembler code into the original exe, to finally let the program
behave the way we want :-) Here we assigned a value to one of the registers, and made the procedure
return to its caller, without performing any code that was meant to be performed :-)


Tutor6

In the previous tutorial I explained you how to crack a program by modifying the heart of
the protection : Its serial validation routine. This kind of protections are used very often. In
this tutorial I will demonstrate one :-)

The program we are going to crack here, is a website mirroring / web spidering program.
It is called Aeria Leech version 1.00. You can download it from : [Only registered and activated users can see links]
I released a keygenerator for this program and it took me about 1 week to figure out how the
key generation routine worked. But it is so easy to crack :-) We will do it together …
In just a few minutes.
Let's get going ;-)

Step 1: Run the program:
Run it. In the help menu you have the option to register.
Enter any number and press ok.
You get an error message : The key is not a valid license key for this product.
Ok. Let's go on to the next step

Step 2: Disassemble the program:
Disassemble, and look for the string you see above.
Found.
This string reference brings us to the next step.

Step 3: Analyzing the protection routine.... / Understanding the jumping Mechanism...
Let's analyze the protection routine.

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00405E11(C)
|
:00405F28 E86F8C0300 call 0043EB9C
:00405F2D 8B4004 mov eax, dword ptr [eax+04]
:00405F30 6A10 push 00000010

* Possible StringData Ref from Data Obj ->"Invalid License Key"
|
:00405F32 6808844500 push 00458408

* Possible StringData Ref from Data Obj ->"The key is not a valid license "
->"key for this product."
|
:00405F37 68D0834500 push 004583D0
////////////////////// Code snip ///////////////////////////


Well ... This piece of code sure looks familiar :-)
This code is reached after a jump at address : 405E11. The reference shows that.
Let's go back to address 405E11.


////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

:00405E04 83C408 add esp, 00000008
:00405E07 E864380000 call 00409670
:00405E0C 83C404 add esp, 00000004
:00405E0F 84C0 test al, al
:00405E11 0F8411010000 je 00405F28
////////////////////// Code snip ///////////////////////////


This jump at address 405E11 jumps over all the piece of code that tells us that we are
registered. So nopping this jump away would make us display the nice registered dialog box :-)
But luckily we worked through the previous tutorial. and we first try to analyze this code.


////////////////////// Code snip ///////////////////////////
call 409670 ; isregistered ?
test al, al ; result of the call is in eax :-)
; ( al is the lower part of eax, not important now)
je ; if eax = 0 then jump ! if eax is 1 don't jump !
////////////////////// Code snip ///////////////////////////

Well ... this code is clear not ?
The call checks the entered serial. And if the serial is ok, it returns 1 in eax, else it returns a zero
in eax.
Let's trace into the call at address 409670.


////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS

* Referenced by a CALL at Addresses:
|:004014BF , :00405E07
|

* Possible Reference to Dialog: DialogID_00CB, CONTROL_ID:00FF, ""
|
:00409670 6AFF push FFFFFFFF
:00409672 68F8424400 push 004442F8
:00409677 64A100000000 mov eax, dword ptr fs:[00000000]
////////////////////// Code snip ///////////////////////////

And yes ... We were right :-)
This call is referenced twice. Once at startup and once while entering the serial :-)


Step 4: Changing the original program...

Since we analyzed the jumping mechanism carefully, we can change the original program.
Open the program in hiew after making a backup copy of it.
Get to the beginning of the call at address 409670.

Change the beginning of the call into the following :
////////////////////// Code snip ///////////////////////////

mov eax, 1 ; 1 means serial is ok
ret ; return to the caller.
////////////////////// Code snip ///////////////////////////

It will look like the following:

////////////////////// Code snip ///////////////////////////
ADDRESS MACHINE CODE ASSEMBLER INSTRUCTIONS
00009670: B801000000 mov eax,000000001
00009675: C3 retn
00009676: 0064A100 add [ecx][00000],ah
////////////////////// Code snip ///////////////////////////


Save your patched program and exit hiew.

Step 5: Testing your cracked program...
Run Leech. It will still tell you that you are unregistered in the about box.
Register it with any number, and it will happily accept your serial :-)

Do not forget to close the program and restart it. You will see that it is still happy with the
provided serial :-)

NOTES

Frequently Used Terms :

An exe file consists of alotof characters / numbers.

These are interpreted by the processor. When the exe file is fed to the processor, it recognizes certain combinations of numbers as a command... And it performs the command it is expected to do.
The numbers I am talking about, is the machine code. The command the processor sees in it interpreted for human language is assembler instructions.
Disassemblers (like W32Dasm) play for processor, and read in all the numbers and try to make a corresponding interpretation of the numbers. This is called a disassembly.


Example:


Numbers: 99 96 8F 29 00 01 76 CA
Mach.Code:
99
96
8F29
0001
76CA

Assembler Instructions :
99 cdq
96 xchg esi, eax
8F29 pop dword ptr [ecx]
0001 add [ecx], al


To make assembler listings faster understandable, we comment it. This is done by putting a ';' at the end of the line, and write whatever you want.
Like this:

99 cdq
96 xchg esi, eax ; exchange value in esi with eax
8F29 pop dword ptr [ecx]
0001 add [ecx], al ; add value in al to address in ecx




Basic Assembler

Code Flow:
When analyzing a piece of code, you should realize that the processor is dumb and it just follows one line after the other... It does anything the code tells it to do.

To do this, the processor has an instruction pointer. With it, it points to the instruction it wants to execute.

The processor also executes instructions that change the flow of the code.

When trying to understand a piece of code, try to be the processor....
Compare registers, compare variables, execute jumps, and execute calls. This is the best way to understand a piece of code.

Registers:
Registers are variables the processor uses. The most used ones are : eax, ebx, ecx and edx. You will also see edi, esi, esp, ebp.

These registers which start with an e, are all 32 bits registers. The 16 bit equivalents of these registers you will also see here and there. These are actually the same registers, but the variable size is only 16 bits. These registers are: ax, bx, cx, dx, di, si, sp, bp.

While we are at it, there are also 8 bit values of some of the registers.
You might see the following 8 bit registers: al, ah, bl, bh, cl, ch, dl, dh.
Here the l stands for the lower and h for the higher 8 bits of a 16 bit register.

Flags:
Flags are boolean variables the processor uses for itself to check what the result of a logical instruction was. The most important flag is the Zero Flag. Its value can be zero or non-zero.

Frequently seen Assembler instructions:


cmp xxx, yyy This instruction compares value xxx with value yyy.
if they are equal, the zero flag is set.

test xxx, xxx Compares if value xxx is equal to zero. If it is, the zero
flag is set.

jmp <address> Unconditional jump. Jumps always. Not important for crackers

jz <address> jump if Zero flag is set. Same as je
jnz <address> jump if Zero flag is Not set. same as jne

jxx <address> jump if <condition>greater, less, greater or equal, less or
equal.

call <address> The Processor saves the address of the next instruction, then
it jumps to address <address>.
Executes all lines until it counters a ret instruction. After
the ret instruction it returns to the line of next instruction
These are subroutines / procedures / functions.

push <variable> This moves a value into the memory the processor uses. This is
usually done before a call is executed. The parameters of the
function are 'pushed'. The values are moved into memory so that the subroutine can access them easily.

Frequently Used Terms :

An exe file consists of alotof characters / numbers.

These are interpreted by the processor. When the exe file is fed to the processor, it recognizes certain combinations of numbers as a command... And it performs the command it is expected to do.
The numbers I am talking about, is the machine code. The command the processor sees in it interpreted for human language is assembler instructions.
Disassemblers (like W32Dasm) play for processor, and read in all the numbers and try to make a corresponding interpretation of the numbers. This is called a disassembly.


Example:


Numbers: 99 96 8F 29 00 01 76 CA
Mach.Code:
99
96
8F29
0001
76CA

Assembler Instructions :
99 cdq
96 xchg esi, eax
8F29 pop dword ptr [ecx]
0001 add [ecx], al


To make assembler listings faster understandable, we comment it. This is done by putting a ';' at the end of the line, and write whatever you want.
Like this:

99 cdq
96 xchg esi, eax ; exchange value in esi with eax
8F29 pop dword ptr [ecx]
0001 add [ecx], al ; add value in al to address in ecx

-=[tp12]=-
20th November 2007, 14:08
That is really big post...:lol:
Will be here for few days for some comments before moving it to How to section...

himandrake
20th November 2007, 14:15
thanks buddy awsome share +rep first for this :)

swankyleo
20th November 2007, 14:36
Buddy thanks for this tutorial, but lets be very clear, it is in no way related to hacking symbian applications but only Win32 code...any programmers in here would certainly agree. This forum is dedicated for symbian apps and I don't think its the right place.

ghostinio
20th November 2007, 14:39
I have 2 say 1 thing after this tutorial, I respect more those who do this job !

subrata
20th November 2007, 14:44
I think this is not possible to do crack of any application without know about programing language. first i need to learn make something and then edit. where as i dont know how to make how can i edit or crack ? anyway may be this can help our programer brother.
Thanks for share

jackass17
20th November 2007, 14:44
stick this post

albertobom
20th November 2007, 15:11
Yes it's cool but I prefer to leave this to the pro guys like Team BINPDA ;-)!

xone
20th November 2007, 15:25
nice! many thanks! +rep :D

lzb_j77
20th November 2007, 15:55
very useless post. nothing about symbianos and ARM.

naibmys
20th November 2007, 16:40
very useless post. nothing about symbianos and ARM.

i agree.................

gallo55
20th November 2007, 22:08
Thanks man very usefull!

evil_night
20th November 2007, 22:45
thats a nice tutorial mate, now we can know that how much pro's like Binpda are doing a gr8 job!!! :)

mua30
20th November 2007, 22:50
man!! many thanks, it gave me an idea how to start programming symbian apps.
thx very much

cowhead
21st November 2007, 00:57
I am going to plough thru' the codes. Great!

benzas
21st November 2007, 02:22
looks easy .................................................. lol

lil2pac
29th March 2008, 03:18
wow made my eyes hurt just reading it, so am just gonna leave it to the pros.

opicks
29th March 2008, 04:57
More respect to binPDA,sympda,hspda,cepteam,and other cracker team. They do a great job. Better to leave this one for the Pro.. A very big tutorial

-=[tp12]=-
29th March 2008, 05:25
Thread move to how to section...

Monyozt
29th March 2008, 07:05
that's a confunsing tutorial :(

a-h-t1
11th April 2008, 04:05
thanx for the tutorial , but i must agree that this tutorial is for win32 applications not for symbain applications , add more its too complicated for my mind ,

thanx anyway

WBR

nicesoni_ash
29th May 2008, 18:45
Well how much I know about cracking and about symbian cracking specially....you need to have some good knowledge about ams language...so called machine language...coz most of the app files of these applications, i mean packed under sis files...are can only be modified through this language..though many of the softwares and disassemblers are available on the net..and so many tutorials about asm language are too available on net....though this is a nice guide, but to some extend only it will tell you about how this particular language work...moreover you need to learn asm language still..

though I will appreciate his work...keep up the good work... i will try to post some tutorials just to let it go through some more in deep...tc

nicesoni_ash
2nd June 2008, 12:44
Well I have some info, which I would like to share with you people, but before that I would really suggest you people to get some books on Disassembling subject and related.... you can get many of them on net, like "A-List Publishing Disassembling Code Ida Pro And Softice" is one of them... A really good one...

Ok now most of the Data I will put down, I got that from this site only when it was iphone-forum.org, so I doubt that giving direct link will help you anyhow though I am putting that link here....

[Only registered and activated users can see links] (The second page of that turorial)

Now if somehow you dont get to this page, here is the total output of it.....

Before I will go further, Let me tell you something more about it, See CRACKING isnt all about Symbian but cracking is applicable to everything. It is only a peice of code you play with.

Reverse Engineering or Cracking is just modifying or transforming the APP or whatever file to your evil needs..

Reverse engineering is machine dependant meaning it depends on you machine (more specific, your CPU: Central Processing Unit, the processor ).

For most of machines you disassemble (transform from machine language to assembly language) to Intel set of instructions. That is not the case for symbian APP file since you disassemble to ARM set of instructions. You will find such similarity between them (Intel and ARM) cause assembly in general deal with the hardware.

In order to change the BAD line of code you do not want, you have to have a hex editor (at least in my time). You first disassemble the file and get the address (the nasty addess ) you want to fix and you then enter it in the hex editor and do the required change. When you are cracking PC files (your computer not your cell phone) you have to know about protection routines employed in the file. Protection routines are block of code that are used to protect the program from nasty people (the crackers). In cell phone cracking you have less protection routines since devolopers have to consider the memory and storage limitation.

You need these programs to start Cracking:

1. UnmakeSIS (to unpack the sis EPOC Package into files and get the APP file)
2. Makesis (to repack to sis after modifying the APP file).
3. IDA Pro disassembler v4.+ (to disassembe the APP file of course).
4. Any Hex editor (to do modifications to the APP file).

I heard that the new version of IDA will allow you to change the code so probably you won't need the Hex editor.

Dont ask me about these softwares as most of them you can find here in this forum, and IDA is such a big program, So I cant upload it somewhere but if you try to search it you will find it..or I will try to put a link to it soon..


Now after you got the program, there are some needs to fulfill, you can quickly do a short learning and start cracking the apps, though it wont be as easy so I suggest you to thoroughly go ahead and complete the requirements I am telling you next ---->

1. Learn some high level language (i suggest C++) and master the part concerning loops and jumps.
2. After you have done first requirement you need to know how the PC works (CPU and Memory).
3. If you have done two, then you know about the registers (hint: Register=Variables, what we call variables in HLL like c++, we call them Register in Machine language like ASM and their work is to hold some data, sometimes temporarily or permanently).
4. You have to study assembly language (intel set of instructions I suggest), you can find so many tutorials, I will try to put that here one by one.
5. If you reached here then you must know about the jumps and mov instructions and yeah base conversions (to be able to convert between binary, decimal and hexdecimal).
6. Study the ARM set of instructions (if you have done 4, this is a peice of cake).


I know that these requirements seems way too long but you will find easy if you have some free time. If you love the tech world you would learn faster, believe me. Some people will tell you to skip some of these steps but believe me you have to go throught those steps thoroughly.

nicesoni_ash
2nd June 2008, 12:44
Let me put a simple tutorial as my first tutorial to crack SymbianWare Stacker v2.02, and please understand that whatever I am writing here isnt at all written by me, I am just putting it here gathering this info from somewhere else, till my knowledge this tutorial is written by atzplzw (Member of 18+2 Group)

Tools:
------
IDA Pro v4.04 or higher, I use ver 4.30
Hex Editor, I prefer WinHex


Target:
-------
SymbianWare Stacker v2.02

"Stacker is a fully automatized and reliable compression system for your Nokia 7650.
Stacker doubles the size of your entire drives and works invisible behind the scene.
When you start an application it becomes decompressed in background automatically
and it becomes compressed again when you close it."

Copied from [Only registered and activated users can see links] (slidely edited)

Recommended:
------------
A little knowledge in ARM assembler... ([Only registered and activated users can see links])
If not, at least you have to know how to use IDA and a Hex Editor and how to transfer
files between the PC and your phone.

Introduction:
-------------
I have choosen SymbianWare Stacker because it's really easy to understand and to
crack. In my opinion all SymbianWare progs are easy to crack. You may find it
difficult in the beginning, but it isn't.

Also (till now, all) SymbianWare progs are compiled with full ARM instructions set.

Here we go:
-----------
First, of course, run the app. Look at the nag screen. Test all things.
After that...

Open stacker.app in the Hex Editor and look through the wired numbers and ascii
letters. In the first line at offset 0x10 you will find "EPOC" which means that
this is an EPOC file for use with the Symbian OS.

Scroll down and you will find some Unicode strings between offset 0x76C0 and
0x7FA0.

What do we read here?? Isn't it the text from the About Box and other Messages?
Yes, it is.

Now we take a closer look at offset 0x7F18:

00007F18 U.n.r.e.g.i.s.t.e.r.e.d.!. .T.r.i.a.l. .i.s. .o.v.e.r....... ....... .d.
00007F60 a.y.s. .l.e.f.t. .t.o. .e.x.p.i.r.e.....U.n.r.e.g.i.s.t.e.r.e.d.


Woohh! We found the text of the nag box when the app is started. Write this offset
down and go fast to IDA...


Open stacker.app. It suggests that it is a EPOC file as we already found out.
Mark Load resources. And press OK! Now you will be informed that the ARM processor
has two instruction sets but this is irrelevant for now.

Now IDA presents you the disassembled ARM instruction code. You may also turn on
Options/General/Auto Comments for better understanding of the code...
For those of you who are not familiar with IDA it is important to know that in the
status line at the bottom the offset is displayed. (tooltip: Current position in
the input file, means offset)

Now scroll all the way down until you will find the offset we wrote down. IDA
displays this mess:

.text:10007E9C dword_0_10007E9C DCD 0x6E0055, 0x650072, 0x690067, 0x740073,
.text:10007E9C 0x720065, 0x640065 ; DATA XREF: .text:10005830
.text:10007E9C DCD 0x200021, 0x720054, 0x610069, 0x20006C, 0x730069,
.text:10007E9C DCD 0x6F0020, 0x650076, 0x2E0072, 0
.text:10007ED8 dword_0_10007ED8 DCD 0xA0020, 0 ; DATA XREF: .text:100058A4


Now just right click on a number, choose Undefine and your mind will be cleared up:


.text:10007E9C unk_0_10007E9C DCB 0x55 ; U ; DATA XREF: .text:10005830o
.text:10007E9D DCB 0 ;
.text:10007E9E DCB 0x6E ; n
.text:10007E9F DCB 0 ;
.text:10007EA0 DCB 0x72 ; r
.text:10007EA1 DCB 0 ;
.text:10007EA2 DCB 0x65 ; e
.text:10007EA3 DCB 0 ;
.text:10007EA4 DCB 0x67 ; g
.text:10007EA5 DCB 0 ;
.text:10007EA6 DCB 0x69 ; i
.text:10007EA7 DCB 0 ;
.text:10007EA8 DCB 0x73 ; s
.text:10007EA9 DCB 0 ;
.text:10007EAA DCB 0x74 ; t
.text:10007EAB DCB 0 ;
.text:10007EAC DCB 0x65 ; e
.text:10007EAD DCB 0 ;
.text:10007EAE DCB 0x72 ; r
.text:10007EAF DCB 0 ;
.text:10007EB0 DCB 0x65 ; e
.text:10007EB1 DCB 0 ;
.text:10007EB2 DCB 0x64 ; d
.text:10007EB3 DCB 0 ;
.text:10007EB4 DCB 0x21 ; !
.text:10007EB5 DCB 0 ;
...............................................(sh ortend)



The Unicode string we saw in the Hex Editor, right? Now we want to know when the
string is used in the code. So right click on "DATA XREF: .text:10005830o",
choose Jump to cross reference and click OK. You will land here:

.text:10005830 off_0_10005830 DCD loc_0_10007E9C ; DATA XREF: .text:1000580Cr


Do it again, right click on "DATA XREF: .text:1000580Cr", choose Jump to cross
reference and click OK. Finally you arrive in the code:

.text:1000580C LDR R1, =dword_0_10007E9C ; Load from Memory


LDR is the instruction to load the string from memory. This string is displayed
afterwards. But we don't want to see it because it's so annoying.
So we scroll a little bit up and look at the code. What did it before?


.text:100057BC BL sub_0_1000538C ; Branch with Link
.text:100057C0 CMP R0, #0 ; Set cond. codes on Op1 - Op2
.text:100057C4 BNE loc_0_100058B0 ; Branch <<<<<<<
.text:100057C8 MOV R0, R4 ; Rd = Op2
.text:100057CC BL loc_0_100054C4 ; Branch with Link
.text:100057D0 SUBS R7, R0, #0 ; Rd = Op1 - Op2
.text:100057D4 BEQ loc_0_10005834 ; Branch <<<<<<<
.text:100057D8 BL loc_0_10006168 ; Branch with Link
.text:100057DC LDR R1, =0x5BED5021 ; Load from Memory
.text:100057E0 LDR R2, =0x5BED5020 ; Load from Memory
.text:100057E4 BL loc_0_100064A8 ; Branch with Link
.text:100057E8 MOV R0, R4 ; Rd = Op2
.text:100057EC BL loc_0_10005230 ; Branch with Link
.text:100057F0 MOV R0, R4 ; Rd = Op2
.text:100057F4 BL sub_0_1000538C ; Branch with Link
.text:100057F8 CMP R0, #0 ; Set cond. codes on Op1 - Op2
.text:100057FC BNE loc_0_100058B4 ; Branch <<<<<<<
.text:10005800 BL loc_0_10006168 ; Branch with Link
.text:10005804 MOV R4, R0 ; Rd = Op2
.text:10005808 ADD R0, SP, #0x20 ; Rd = Op1 + Op2
.text:1000580C LDR R1, =dword_0_10007E9C ; Load from Memory <--- Stupid String
.text:10005810 BL loc_0_10005B48 ; Branch with Link


As you see from the code snip there are three conditional branches to avoid that
the string is loaded. I marked them with <<<<<<<. For me it seems that the prog is
testing if we registered it and if not it loads the string "unregistered".

Now we are on the move: It is clear that we have to examine the BL's before the
branches. Why? I'll explain the code:


.text:100057BC BL sub_0_1000538C ; Branch with Link

A branch (call) to another function. (BL's always return back to the next instruction)
Also they may give results in one or more of the registers back.

.text:100057C0 CMP R0, #0 ; Set cond. codes on Op1 - Op2

The register R0 is compared with 0 (null).

.text:100057C4 BNE loc_0_100058B0 ; Branch if not equal

If R0 is not 0 the branch is taken, if R0 is 0 nothing happens.



So we have to ensure that the result from the functions call (BL) is not 0. Then the
branch is taken and we have a registered prog.

If you are with me you will now have a good question! Which of the three branches with
the BL's before the string we will exam?
In reality you will have to exam all three and look at the code. But I will just
explain the first, because that's the right one...

OK. Let's start with the one at .text:100057C4! Right click on BL sub_0_1000538C,
choose jump immediate and you will see that:



.text:1000538C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:1000538C
.text:1000538C sub_0_1000538C ; CODE XREF: sub_0_100003F8+480p
.text:1000538C ; sub_0_100050CC+188p ...
.text:1000538C STMFD SP!, {R4,LR} ; Store Block to Memory
.text:10005390 SUB SP, SP, #8 ; Rd = Op1 - Op2
.text:10005394 MOV R4, R0 ; Rd = Op2
.text:10005398 LDR R3, [R4,#0xF8] ; Load from Memory
.text:1000539C CMP R3, #0 ; Set cond. codes on Op1 - Op2
.text:100053A0 BEQ loc_0_100053C4 ; Branch
.text:100053A4 MOV R0, SP ; Rd = Op2
.text:100053A8 LDR R1, =dword_0_10007D64 ; Load from Memory
.text:100053AC BL loc_0_10005B48 ; Branch with Link
.text:100053B0 MOV R0, R4 ; Rd = Op2
.text:100053B4 MOV R1, SP ; Rd = Op2
.text:100053B8 BL loc_0_10005C48 ; Branch with Link
.text:100053BC CMP R0, #0 ; Set cond. codes on Op1 - Op2
.text:100053C0 BNE loc_0_100053D0 ; Branch
.text:100053C4
.text:100053C4 loc_0_100053C4 ; CODE XREF: sub_0_1000538C+14j
.text:100053C4 MOV R0, #0 ; Rd = Op2
.text:100053C8 B loc_0_100053EC ; Branch
.text:100053C8 ; ---------------------------------------------------------------------------
.text:100053CC off_0_100053CC DCD dword_0_10007D64 ; DATA XREF: sub_0_1000538C+1Cr
.text:100053D0 ; ---------------------------------------------------------------------------
.text:100053D0
.text:100053D0 loc_0_100053D0 ; CODE XREF: sub_0_1000538C+34j
.text:100053D0 MOV R0, R4 ; Rd = Op2
.text:100053D4 MOV R1, R4 ; Rd = Op2
.text:100053D8 BL sub_0_100050CC ; Branch with Link
.text:100053DC LDR R3, [R4,#0xF8] ; Load from Memory
.text:100053E0 CMP R0, R3 ; Set cond. codes on Op1 - Op2
.text:100053E4 MOVNE R0, #0 ; Rd = Op2
.text:100053E8 MOVEQ R0, #1 ; Rd = Op2
.text:100053EC
.text:100053EC loc_0_100053EC ; CODE XREF: sub_0_1000538C+3Cj
.text:100053EC ADD SP, SP, #8 ; Rd = Op1 + Op2
.text:100053F0 LDMFD SP!, {R4,LR} ; Load Block from Memory
.text:100053F4 BX LR ; Branch to/from Thumb mode


This is our function. Here it is decided if the prog is registered or not. Also there
are several Code XREFs in the first line which means that this function can be or is
called more than once.

Now remember: 0 is not registered, not equal 0 is registered. So lets see when another
number then 0 is put in register R0. Found it?

.text:100053E8 MOVEQ R0, #1 ; move if equal

If the cmp instruction before this move is equal a 1 is put in R0.


But we have also two instructions where 0 is put in R0.

.text:100053C4 MOV R0, #0 ; move
.text:100053E4 MOVNE R0, #0 ; move if not equal


What should we do? When you look at the code flow you'll also notice that there are two
way's to get to the end. One is over this location

.text:100053C4 loc_0_100053C4 ; CODE XREF: sub_0_1000538C+14j


the other over this

.text:100053D0 loc_0_100053D0 ; CODE XREF: sub_0_1000538C+34j


It is decided on runtime which way to get. One is always taken!! The other not!! And we
can't decide what the prog does here. So let's make up our mind and think, think, think!

We need a strait way to the end and also there has to be a 1 in register R0. Let's do it
this way:

Change

.text:100053A0 BEQ loc_0_100053C4 ; Branch if equal

to

.text:100053A0 B loc_0_100053C4 ; Branch always

so that this branch is always taken. And change

.text:100053C4 MOV R0, #0 ; R0 = 0

to

.text:100053C4 MOV R0, #1 ; R0 = 1

so that 1 is moved into register R0!


The flow of our code would now be

.text:1000538C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
.text:1000538C
.text:1000538C
.text:1000538C sub_0_1000538C ; CODE XREF: sub_0_100003F8+480p
.text:1000538C ; sub_0_100050C8+18Cp ...
.text:1000538C STMFD SP!, {R4,LR} ;
.text:10005390 SUB SP, SP, #8 ;
.text:10005394 MOV R4, R0 ;
.text:10005398 LDR R3, [R4,#0xF8] ;
.text:1000539C CMP R3, #0 ;
.text:100053A0 B loc_0_100053C4 ; Branch always <<<<<<< Changed
.text:100053A4 ; ---------------------------------------------------------------------------
.text:100053A4 MOV R0, SP ; .............All
.text:100053A8 LDR R1, =dword_0_10007D64 ; .......these
.text:100053AC BL loc_0_10005B48 ; .............instructions
.text:100053B0 MOV R0, R4 ; .............are
.text:100053B4 MOV R1, SP ; .............never
.text:100053B8 BL loc_0_10005C48 ; .............executed!!!
.text:100053BC CMP R0, #0 ; .............
.text:100053C0 BNE loc_0_100053D0 ; .............
.text:100053C4
.text:100053C4 loc_0_100053C4 ; CODE XREF: sub_0_1000538C+14j
.text:100053C4 MOV R0, #1 ; move R0 = 1 <<<<<<<< Changed
.text:100053C8 B loc_0_100053EC ;
.text:100053C8 ; ---------------------------------------------------------------------------
.text:100053CC off_0_100053CC DCD dword_0_10007D64 ; DATA XREF: sub_0_1000538C+1Cr
.text:100053D0 ; ---------------------------------------------------------------------------
.text:100053D0
.text:100053D0 loc_0_100053D0 ; CODE XREF: sub_0_1000538C+34j
.text:100053D0 MOV R0, R4 ; .............
.text:100053D4 MOV R1, R4 ; .............
.text:100053D8 BL loc_0_100050CC ; .............These
.text:100053DC LDR R3, [R4,#0xF8] ; .............also!
.text:100053E0 CMP R0, R3 ; .............
.text:100053E4 MOVNE R0, #0 ; .............
.text:100053E8 MOVEQ R0, #1 ; .............
.text:100053EC
.text:100053EC loc_0_100053EC ; CODE XREF: sub_0_1000538C+3Cj
.text:100053EC ADD SP, SP, #8 ;
.text:100053F0 LDMFD SP!, {R4,LR} ;
.text:100053F4 BX LR ; back



We are nearly finished to crack this one! We have decided what to change. Now write the
offsets from the two instructions down.
The first one (branch) is at 0x541C, the second (move) is at 0x5440.

Go to the Hex Editor and look at the first offset:

0000541C 07 00 00 0A ã.... <<< this is the branch if equal instruction

change 0A to EA

0000541C 07 00 00 EA ã...ê <<< this means branch always


The second instruction we have to change is at

00005440 00 00 A0 E3 .. ã <<< move R0, 0

change first 00 to 01

00005440 01 00 A0 E3 .. ã <<< move R0, 1


YeaaHH! We got it!!!!!
Send the file to your phone and you have a registered Stacker!!!

Conclusion:
-----------
Not as easy as you and I thought? But I hope that if you succeed in this, you feel good..hmmm...

Now wait for my second tutorial... I will put it here soon....take care

nicesoni_ash
2nd June 2008, 12:46
Here I am putting the second tutorial I found on the net and this is also written by the same member who wrote the first one...

This time the target us CellPoker...

Tools:
------
IDA Pro v4.04 or higher, I use the Advanced Ver but the normal would do also
Hex Editor, I prefer WinHex


Target:
-------
"CellPoker is a networked multi-player poker game for the Nokia 7650. The game can be played as multiplayer over Bluetooth or single player mode..."

Copied from [Only registered and activated users can see links]


Recommended:
A little knowledge in ARM assembler... ([Only registered and activated users can see links])
If not, at least you have to know how to use IDA and a Hex Editor and how to transfer
files between the PC and your phone.

Introduction:
-------------
I choose Cellpoker because it's actually a good Nokia game.
It's not the easiest program to crack, but a good target following on from
atzplzw original tutorial.

Here we go:
-----------
First, of course, run the app. Look at the nag screen. Test all things.
After that...

Open poker.app in the Hex Editor and look through the wierd numbers and ascii
letters. In the first line at offset 0x10 you will find "EPOC" which means that
this is an EPOC file for use with the Symbian OS.

Scroll down and you will find some semi readble strings between offset 0x1B0C0
and 0x1CA70.

What do we read here?? Isn't it the text from the game?
Yes, it is.

Now we take a closer look at offset 0x1C934:

01C920 ····w·i·n···w·i·n···C·e·l·l·P·o·k·e·r· ·d·e·m·o·:···D·a·y·s· ·l·
01C960 e·f·t· ·····N·o· ·s·a·v·e·d· ·g·a·m·e···C·e·l·l·P·o·k·e·r· ·d·e·
01C9A0 m·o·············7·······mr··············.·······C· :·\·s·y·s·t·e·


Woohh! We found the text of the nag box when the app is started.
Write this offset down and startup IDA...


Open poker.app. It suggests that it is a EPOC file as we already found out.
Mark Load resources. And press OK! Now you will be informed that the ARM processor
has two instruction sets but this is irrelevant for now.

Now IDA presents you the disassembled ARM instruction code. You may also turn on
Options/General/Auto Comments for better understanding of the code...
For those of you who are not familiar with IDA it is important to know that in the
status line at the bottom the offset is displayed. (tooltip: Current position in
the input file, means offset)

Now scroll all the way down until you will find the offset we wrote down. IDA
displays this mess:

.text:1001C8B8 dword_0_1001C8B8 DCD 0x650043, 0x6C006C, 0x6F0050, 0x65006B, 0x200072, 0x650064
.text:1001C8B8 ; DATA XREF: sub_0_1000EC6C+148o
.text:1001C8B8 DCD 0x6F006D, 0x3A


Now just right click on a number, choose Undefine and your mind will be cleared up:


.text:1001C8B8 unk_0_1001C8B8 DCB 0x43 ; C ; DATA XREF: sub_0_1000EC6C+148o
.text:1001C8B9 DCB 0 ;
.text:1001C8BA DCB 0x65 ; e
.text:1001C8BB DCB 0 ;
.text:1001C8BC DCB 0x6C ; l
.text:1001C8BD DCB 0 ;
.text:1001C8BE DCB 0x6C ; l
.text:1001C8BF DCB 0 ;
.text:1001C8C0 DCB 0x50 ; P
.text:1001C8C1 DCB 0 ;
.text:1001C8C2 DCB 0x6F ; o
.text:1001C8C3 DCB 0 ;
.text:1001C8C4 DCB 0x6B ; k
.text:1001C8C5 DCB 0 ;
.text:1001C8C6 DCB 0x65 ; e
.text:1001C8C7 DCB 0 ;
.text:1001C8C8 DCB 0x72 ; r
.text:1001C8C9 DCB 0 ;
.text:1001C8CA DCB 0x20 ;
.text:1001C8CB DCB 0 ;
.text:1001C8CC DCB 0x64 ; d
.text:1001C8CD DCB 0 ;
.text:1001C8CE DCB 0x65 ; e
.text:1001C8CF DCB 0 ;
.text:1001C8D0 DCB 0x6D ; m
.text:1001C8D1 DCB 0 ;
.text:1001C8D2 DCB 0x6F ; o
.text:1001C8D3 DCB 0 ;
.text:1001C8D4 DCB 0x3A ; :
.text:1001C8D5 DCB 0 ;
.text:1001C8D6 DCB 0 ;
.text:1001C8D7 DCB 0 ;
...............................................(sh ortend)



The string we saw in the Hex Editor, right? Now we want to know when the
string is used in the code. So right click on "DATA XREF: sub_0_1000EC6C+148o",
choose Jump to cross reference and click OK. You will land here:

text:1000EDB4 off_0_1000EDB4 DCD loc_0_1001C8B8 ; DATA XREF: sub_0_1000EC6C+BCr


Do it again, right click on "DATA XREF: sub_0_1000EC6C+BCr", choose Jump to cross
reference and click OK. Finally you arrive in the code:

.text:1000ED28 LDR R1, =loc_0_1001C8B8 ; Load from Memory


LDR is the instruction to load the string from memory. This string is displayed
afterwards. But we don't want to see it because it's so annoying.
So we scroll a little bit up and look at the code.


.text:1000EC6C sub_0_1000EC6C ; CODE XREF: sub_0_1000EBF8+64p
.text:1000EC6C STMFD SP!, {R4-R7,LR} ; Store Block to Memory
.text:1000EC70 SUB SP, SP, #0xC0 ; Rd = Op1 - Op2
.text:1000EC74 MOV R6, R0 ; Rd = Op2
.text:1000EC78 LDR R0, [R6,#0x17C] ; Load from Memory
.text:1000EC7C CMP R0, #0 ; Set cond. codes on Op1 - Op2 <<<<<<<<<<
.text:1000EC80 LDRNE R3, [R0] ; Load from Memory
.text:1000EC84 MOVNE R1, #3 ; Rd = Op2
.text:1000EC88 LDRNE R12, [R3,#8] ; Load from Memory
.text:1000EC8C MOVNE LR, PC ; Rd = Op2
.text:1000EC90 TEQNEP PC, R12,LSL PC ; Set cond. codes on Op1 ^ Op2
.text:1000EC94 MOV R5, #0 ; Rd = Op2
.text:1000EC98 STR R5, [R6,#0x17C] ; Store to Memory
.text:1000EC9C ADD R7, R6, #0x180 ; Rd = Op1 + Op2
.text:1000ECA0 MOV R0, #0x88 ; Rd = Op2
.text:1000ECA4 BL loc_0_100164D8 ; Branch with Link
.text:1000ECA8 SUBS R4, R0, #0 ; Rd = Op1 - Op2
.text:1000ECAC BEQ loc_0_1000ECFC ; Branch <<<<<<<<<<



What we are looking for is "CMP" compares i.e. Compare Todays Date with Expiry Date etc..
And BEQ/BNE... conditional branches.
(BEQ/BNE/BHI/B... are like PC JMP's (JZ,JNZ,JBE...) opcodes...)

I marked them with <<<<<<<. Is the program testing it's expiry and if not it loads the string "Cell Poker: Days Left XX" message.


Now we are on the move: What we have to try, is altering the branches to see if we can get the program to run longer than the expiry....

If you are still with me you will now have a good question!
- Which of the branches before the string we will exam?
In reality you will have to exam all of them!


For the purposes of this tutorial I will show you how to change one and test it...

OK. Let's start with the one at .text:1000ECAC!
Now write the offsets of the BEQ instructions down. Note: 0xED28.

Shutdown IDA (don't save), then goto the Hex Editor and look at the first offset:

0000ED28 12 00 00 0A ?.... <<< this is the branch if equal instruction

change 0A to EA

0000ED28 12 00 00 EA ?...ê <<< this means branch always

Save it, relauch IDA and check your BEQ has changed to a B. Yes, then upload the POKER.APP
to your phone and test it. Did it work No, Crash!!!! Ok, it's the wrong jump.
- Restore the original working copy of the poker.app

After testing a couple of branches, It still doesn't work.....we think all is lost...


No, lets follow the code back....
At the top of the piece of code that load's the "CellPoker Demo:" text, there is a "XREF"

.text:1000ECFC loc_0_1000ECFC ; CODE XREF: sub_0_1000EC6C+40j <<<<<<
.
.
.
.
.
.text:1000ED28 LDR R1, =dword_0_1001C8B8 ; Load from Memory

Right click on "CODE XREF: sub_0_1000EC6C+40j",
choose Jump to cross reference and click OK. You will land here:

.text:1000ECAC BEQ loc_0_1000ECFC ; Branch

Now this is the one we have already modified.....so let's find another

So goto the top of that text block until you find the XREF again:

text:1000EC6C sub_0_1000EC6C ; CODE XREF: sub_0_1000EBF8+64p


Right click on "CODE XREF: ......", choose Jump to cross reference and click OK.
You will land here:

.text:1000EC5C BL sub_0_1000EC6C ; Branch with Link

Now what you will need to do, is keep testing (Change "BL" to: "B" or "NOP"), util somthing happens.

Finally after 5 Xref jumps, and changing code, your notice the nag goes away!!!!!

.text:1000EAE8 BL sub_0_1000EBF8 ; Branch with Link


Good? - No, even though the nag has gone away, after some testing the program still expires
after ten days has past. Time to re-look at the code. Remeber after NOP'ing the fith XREF
the NAG went away... have a look at the code a couple of lines above:

.text:1000EADC CMP R0, #9 ; Set cond. codes on Op1 - Op2 <<<<<<
.text:1000EAE0 BHI loc_0_1000EB44 ; Branch <<<<<
.text:1000EAE4 MOV R0, R6 ; Rd = Op2
.text:1000EAE8 BL sub_0_1000EBF8 ; Branch with Link

Why would the program check to see if R0 = 9? Thats right, after ten days (0=Day1, 9=Day10)
Branch if higher than 9 (days) would be true!



Ok, so lets NOP this out as well. Note the offset: EB5c

Shutdown IDA (don't save), then goto the Hex Editor and look at the first offset:

0000EB5C 17 00 00 8A ?.... <<< this is the branch if higher instruction

change to:

0000EB5c 12 00 00 EA ...áß <<< this means mov r0,r0 or NOP

Send the poker.app to your phone and you have a No Nag, No Expiry!!!


Conclusion:
I dont know may be you feel good after completing this...meanwhile wait for my third tutorial if you feel good, but if you doing all this without learning the basic concepts I would still request you to go step by step, and make your basic skills more stronger....

Take care..

nicesoni_ash
2nd June 2008, 12:49
Meanwhile I am putting a simple application, that will test your asm programs, you can say an ASM Emulator...try it ...its really usefull..

darylcc
10th July 2009, 19:18
now thats what i call a genius!!..a big respect for you man