Modification of games on the example of Arcanoid

    Good day!

    Introduction


    For some time I watched the Assembler blog on a hub because more than excellent articles on the analysis of various keygen'ov and "reverse engineering" began to appear there. I have long wanted to do something similar and modify some kind of game on J2ME. I surfed the Internet for a long time in search of a good, but at the same time easy to understand (in terms of analysis) game. Once, I delved into the site of my friend a programmer (by the way, he also writes programs for J2ME. Who used ProPaintMobile knows who I'm talking about. And I found it - it was a simple Arkanoid. Apparently, it was someone's homework , or he was written just “just for fun”, but nevertheless this game turned out to be exactly what you need.


    What do we need


    In order to make a modification, we need the following components:
    1. A decompiler that would give us the source code to make it easier to navigate in the process of changing the byte code. Personally, I use the Java Decompiler for these purposes , which you can get here ;
    2. The disassembler of the virtual machine bytecode that this very bytecode will give us is JavaByte , which can be downloaded here ;
    3. Subject himself - Arcanoid ;
    4. Well, it would also be nice to get acquainted with the specification, which sets out the instructions for the virtual machine, which you can read here .

    Perhaps everything. In fact, the choice of software is an individual matter, and I would say intimate. Therefore, you can easily use, for example, Jasmin instead of the Java Decompiler .

    What do we do now


    Step one

    First, we should open the enemy machine this very game and see what can be modified there. Since we don’t have the source jar file, but there are verified classes and MANIFEST.MF, let's pack our game. No sooner said than done.


    The structure of our archive should look exactly as indicated above. It remains only to redo the extension - from zip to jar and ...

    Second step

    And run our game. Let's play a little.


    We continue to play ...


    Oops. Okay, two more lives left. We play further.


    Everything, played out. There is something to be done about it.

    Step three

    We are doing something with it, namely decompiling. No problems. We rummage through the sources and understand that the most interesting is stored in the GCanvas.java file . Let's take a closer look at what's what:



    Here, we see the constructor, variables, and methods.

    It is worth recalling that we are looking with you where our lives are being reduced. Let's look for the mention of live or lives . Here we are lucky. Since the game is not obfuscated, we see with you variables and methods with more or less real names. And then our view immediately rushes to this line at the very beginning of the source file:

    
    int m_m_LivesII;
    


    Comments are redundant. This is the counter of our lives. It remains only to find where this variable decreases. And here is where, as the decompiler points out, this is line 170:

    
    this.m_m_LivesII -= 1;
    


    Let's examine this piece of code:

    
    while (this.m_m_goGameZZ)
        {
          if (!this.m_m_playGameZZ)
          {
            if (this.m_m_boomZZ)
            {
              this.m_m_ballcBallcBall.setVisible(false);
               _AnimateBoomcGraphicsV(g);
                 this.platform.setVisible(false);
                   this.m_m_LivesII -= 1;
    


    Here, we can say, we are given full instructions: if the variable m_m_goGameZZ , which is Boolean, is set to true , then the game is on. In a collision, the same boolean variable named m_m_playGameZZ becomes false , then the explosion of the platform is animated ( _AnimateBoomGraphics ), then the platform becomes invisible ( platform.setVisible (false) ) and then life is taken away from us, which you can see in the code which is higher. Of course, the first thing that comes to mind is instead of from the variable m_m_LivesIIsubtract the unit, you need to modify the code to add it. But this is not Feng Shui somehow. Then we simply equate the variable to unity. And recompile? This needs to be recompiled, classes verified, and then reassemble everything into the archive. No, I'm too lazy. But there is a way to simply correct the bytecode of the class and then we will not need to perform the first two steps. Moving on ...

    What is our step there? Oh yes fourth

    In order to edit the bytecode, we have JavaBite . So let's use it.
    Let's open our class ( Classes -> Add Java Class and see this picture:



    I hope you remember where the piece of code that interests you is? Exactly, this is the run method . Let's look into it:



    Let's run through the instructions from the very beginning. Stop! Nothing doesn’t remind?



    Yes, this is exactly what we need. Through the instruction down, you will notice the isub instruction - this is it!
    In general, in Russian, this instruction means that we subtract something from the variable m_m_LivesII. We need this variable to always be equal to one. This is very easy to achieve. Let's change the isub statement to nop . Right-click and select Edit Instructions . Here, even screenshots are not necessary. As a result, the instructions will look like this:



    Let's drop our already non-original class with the replacement of the old one and try to open our game, but instead of playing it, we get this error message:



    Debriefing

    From this message, we can understand that the class contains an error. Yes, cap!
    But which one? The thing is that nop in this case will cause an imbalance in the stomach of the stack, and in order to solve the problem we also need to nop the instruction iconst_1 . Why? I will leave this for you as homework. This instruction is at arm's length immediately after our nop . By the way, here she is:



    Actually, we are doing what we should have done with her yesterday . Voila!



    Now let's rebuild our game. And finally, let's play it.




    Now, when we miss our ball outside the platform, we will always see:



    We are not afraid of a gray wolf. Now you can safely play the game before losing your pulse (although it will bore you after a minute, because there are only two levels) and not be afraid of death!

    Conclusion


    In fact, I did this experiment for a long time, when I was a beginner and only mastered in all these instructions. Once for me they, and the assembler himself, were a nightmare. However, time passes - views change, we change. I hope you found this tutorial useful.

    See you soon!

    PS During this experiment, no arkanoid was injured!

    Also popular now: