|
|||
|
(2nd revision)
Since I figured it was time I gave something back to the forum I decided I'd write a fairly straightforward guide to cr*cking JavaME games - aimed at someone who may perhaps have a little experience with java/windows asm, programming in general, etc.. We'll start with the game SandME, a little app where you draw lines.. then pour sand on them.. fan-bloody-tastic !... eh.. Anyhoo, You're going to need the following tools: SandME : [Only Registered users can see links . Click Here To Register...] DJ Java Decompiler : [Only Registered users can see links . Click Here To Register...] 'fix' for DJ Decompiler... [Only Registered users can see links . Click Here To Register...] Hex Workshop: [Only Registered users can see links . Click Here To Register...] 'fix' for Hex workshop... 90481-408176-E94B And this bytecode reference list: [Only Registered users can see links . Click Here To Register...] And Optionally: JADMaker: [Only Registered users can see links . Click Here To Register...] Java Wireless Toolkit for CLDC: [Only Registered users can see links . Click Here To Register...] Okay! The good news is that you probably spent more time downloading those tools than you will *****ing.. Straight to it, get your SandME.jar, and unzip it to c:\SandME or something, you'll have A.class -> F.class, a manifest folder, and whatever else... Just don't delete anything. Note: The files being named a.class etc is a result of the .java sources having been run through an 'obfuscation filter' which basically mangles the source, so that when you try to decompile/read it, it's a bit tougher. Actually, it's not *that* useful at all.. So, here's a pointer.. open DJ java decompiler, and drag 'd.class' in.. Ordinarily, you'll open first the file referenced in Manifest.MF, and work your way through, or search for specific string references, but I'm speeding this along... it's in d.class... You'll see a bunch of nondescript functions, such as ___ public final class d extends Form implements CommandListener, ItemCommandListener { public d(boolean flag) { super("Register"); if(flag) flag = new StringItem(null, "Your sand is over. Register for more sand at ", 0); else flag = new StringItem(null, "Register at ", 0); ___ So, it's fair to assume, that something somewhere makes a call to 'd(boolean);' which interrupts your sand... grrrr! Now below are the register screen codes, and a little further down, the actual algorithm to decode a saved key... I've cr*cked these, but really.. it's not necessary.. All we have to do is find the area of code that calls d() with a boolean value to interrupt our sand.. *hinthint* It's in 'c.class'.. just to save you searching them all Now drag c.class into DJ, and let's see what we can find... Hit Ctrl+F, and search for 'd(' (the letter D and an openbracket..) Some way down, you'll bump into __ c6 = this; int i3 = 0; if(!c6.t && c6.r >= 500) { if(!c6.s) { c6.a(true); c6.s = true; (new d(true)).a(); } __ Scrolling up, we'll find that it's below a section making a call to the timer: __ long l1 = System.currentTimeMillis(); synchronized(this) { c c6; b b1 = (c6 = this).h; __ in a function called: __ public final void run() { __ This looks like a good indication of what calls our function, right? So to sum it up in pseudocode if(!c6.t && c6.r >= 500) is roughly equal to if( (not game registered) and ( game time greater than 500) ) then Call AnnoyingScreen(true) We'll be wanting to alter this.. Let's not cr*ck it completely now, but pretend we're checking that gametime>=500 is actually correct? It's good practice, work it through with me.. OKay copy all your decompiled text for 'c.class' into Wordpad (trust me), and save it.. Now switch DJ to bytecode view, and paste that into another Wordpad too.. Or open more DJ's, but it's easier in wordpad if you're gonna be hexing the files, and deleteing the .decompilation files later... The 500 is a constant value, which should make it a little easier to find the area in the actuall .class file. Now flick over to the bytecode view and hunt for the value 500.. Ctrl+F, hunt for 500, and you'll find the command _ Sipush 500 on line 217.. _ followed by: _ icmplt 486 _ Basically, 'Pop the number 500 onto the stack, and compare it to the current time..' So check the link I gave you above: [Only Registered users can see links . Click Here To Register...] For the bytecode value for sipush.. sipush length:3 opcode:11 type:int2 description: push 2-bytes value And the next for icmplt length:1 opcode:A1 type ffset2 description: conditional goto So it's a good guess that when we open c.class in hex workshop, we'll find opcode 11, followed by a 2 byte addres, followed by opcode A1, right? Open c.class and see.. Hit Ctrl+F and hunt for opcode 11, i.e. '11' in hex.. Towards the end at Address ~ 1050h: __ 11 01F4 A1 __ Looks like we found our code segment.. Now opening windows calc and entering the value 500, you should convert it to hex to see it is indeed 1F4.. Let's change it to EEEE , since it's a nice sound, and much larger than 500.. If you know your way from here on in, then you can go ahead and see how your changes are working, but stick around for the final change, and explanation of how to recompile the whole package.. So fine, we have more time, but after a long while, the game will still pop up a 'register meh' notice.. But we know which code causes this, right? ___ if(!c6.t && c6.r >= 500) ___ Not only is the time checked, but there's that annoying 'is the game registered' check before the double ampersand '&&'... We can change it! Flicking back to our bytecode view, just above where we worked before, we should find another 'if' style statment.. ___ 'ifne 486' on line 214 (which is 'if(!c6.t' ) ___ We'll want to reverse this action so it only pops up if we bothered to register... So fire open the bytecode reference list again, and type in ifne: ifne length:3 opcode:9A type ffset2 description: conditional goto Yarrr.. let's change that to 'ifeq' the exact opposite.. So flick back to hex workshop, where you were editing in c.class (around offset 1050) and search back a few bytes for opcode 9A... and replace it with the bytecode 99... Now the register screen will only pop up if you've actualyl registered, right? After saving, it's time to repackage the whole thing, and test it out.. You can check your new code by re-opening c.jar with DJ, and checking that the code changes have worked. ____ if(c6.t && c6.r >= 6166) ___ Should be something like this, perhaps with a larger number. Repacking: Delete any stray .jar or .jad files in your c:\SandME directory, and select everything, Ctrl+A.. add them to a zip file .. *important* Select all the files in the directory itsself, not the actual directory. Rename the archive from Sandme.zip to SandME.jar. At this point drag the .jar file onto your fone and give it a shot, or follow these steps to use the emulator... Use Jadmaker to create a .jad for your .jar (drag and drop really... lol) And use the 'Run MIDP application' from the java wireless toolkit... Point it to your SandME.jad file and enjoy.. Excessive time, and no nag screen. Enjoy ^^ Hope this has been a good intro to java *****ing, it's been pretty rushed, and well... no thought was given to layout or aesthetics, but the info's all there. I look forward to reading your comments. =) Feel free to redistribute this guide. |
| Sponsored Links |
|
|||
|
Hmm... Good work. I doubt many people will get into the bytecode level when dealing with these Klassmaster obfuscated games. I myself have been amassing a bunch of Klassmaster examples that I know work. Maining stuff like how to reconstruct and recognize an obfuscated if-then, do-while and case-switch structure. But I do plan on uploading it in the coming months.
|
|
|||
|
Heh, well.. for all the searching I've done, there were no real bytecode tutorials, and once decompiled.. a lot of .classes simply can't be recompiled
![]() Your idea is very intriguing though. I just wish there was a .class disassembler more akin to your standard debugger/w32dasm/ollydbg layout.. y'know.. with the ability to soarch for the paterns like you said then alter them directly. Looking forward to seeing your idea ^^ |
|
||||
|
Thanks! Hope this guide works!
Oh, corrected DJ Java decompiler link: [Only Registered users can see links . Click Here To Register...]
__________________
If you like this post please add rep by clicking this icon->
and then write something useful and press add to reputation.![]() ![]() [Only Registered users can see links . Click Here To Register...] |
![]() |
| Bookmarks |
| Thread Tools | |
| Display Modes | |
|
|