Page 2 of 3 FirstFirst 123 LastLast
Results 26 to 50 of 73

Thread: A Basic Updater Primer

  1. #26
    Join Date
    Apr 2016
    Posts
    31
    Mentioned
    0 Post(s)
    Quoted
    18 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    I now have methods, fields, multipliers (your scanner) and arithmetics. My search patterns does work much better now :-)

    Can you give me a hint about exeptions/try catch blocks and returns?

    I've read something about fake parameters (boolean?) that will prevent the code from throwing a exeption and that the exeption and the parameters are "fake" and that you can delete them. But how do I get to that exceptions?

    Thanks in advance,

    EvilID
    Fake parameters are always the last parameter in a method. They can take the form of almost any primitive. They can be checked multiple times in a method or never at all. You can delete these checks and change the method's description. Depending on what analysis you are doing, you may want to update the method calls and remove the fake parameters. I don't understand your question about exceptions.

  2. #27
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    Quote Originally Posted by maven View Post
    Fake parameters are always the last parameter in a method. They can take the form of almost any primitive. They can be checked multiple times in a method or never at all. You can delete these checks and change the method's description. Depending on what analysis you are doing, you may want to update the method calls and remove the fake parameters.
    Yeah that's correct.

    Quote Originally Posted by evilid View Post
    I now have methods, fields, multipliers (your scanner) and arithmetics. My search patterns does work much better now :-)

    Can you give me a hint about exeptions/try catch blocks and returns?

    I've read something about fake parameters (boolean?) that will prevent the code from throwing a exeption and that the exeption and the parameters are "fake" and that you can delete them. But how do I get to that exceptions?

    Thanks in advance,

    EvilID
    Not sure about your last part with the parameters and exceptions with them, but the basis of removing the try catch block is as follows:

    They follow a pattern similar to: ILOAD LDC IF NEW DUP INVOKESPECIAL ATHROW. Where the "IF" can be different conditionals, and the LDC can be LDC's or constants. You want to take the LabelNode from the "IF" and put it in a GOTO before the ILOAD. Then it is safe to remove the pattern.

    This was hugely important with making my patterns more solid, as the try catch's would screw up perfectly good patterns quite often. For the dummy param remover, I just brute force and check if the param is called, and if not I delete it. I don't remove the references to it, so my pack won't run when I do it. I only use it for my updater so it doesn't matter for me.
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  3. #28
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by Kyle View Post
    Here's mine:
    Code:
    GamePack downloading..
    Beginning Deob..
    Removed 2714 Dummy Methods (1159.17 ms)
    Reordered 3258 Multiplier Instructions (151.06 ms)
    Reordered 2853 Arithmetic Statements (1159.69 ms)
    Removed 4730 Exceptions (750.77 ms)
    Removed 1148 Opaque Predicates (167.09 ms)
    Removed 616 Dummy Parameters (254.59 ms)
    Total Deob took 3642.37 ms
    Deob Finished..

    I got (for Gamepack-113).

    Code:
    Deobfuscation Started..
    Removed Methods: 2769 of 4541
    Removed Fields: 638 of 2783
    Re-Ordered Multipliers: 3650 of 23826
    Re-Ordered Arithmetics: 2215 of 29676
    Removed Exceptions: 4730 of 5037
    Removed Returns: 1143 of 8723
    Removed TryCatchBlocks: 30 of 2475
    Removed Parameters: 669 of 1212
    Deobfuscation Finished..



    @evilid;

    For try-catches I do:

    Get the start, the handler, and the end of the try-catch. Find the first GOTO statement after the "start" of the try-catch block.

    Delete all instructions inside the block, delete the goto block, delete the goto statement, delete the frame.

    If the start index of the try block is shared with multiple catch statements or other try-catch statements, I delete the last try-catch first (iterating backwards through the nested try-catches).. then I back up one more and delete the next.

    Repeat until all is deleted.. That's just for the simple ones too. It can get much more complicated.
    I am Ggzz..
    Hackintosher

  4. #29
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    I've managed to get the 'labelnode' (of the try catch blocks) of the if statements, but can't figure out how to put it into a 'new' goto. How do I create a new GOTO and how do I put the 'labelnode' inside of it?

    Thanks in advance,

    EvilID

  5. #30
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    I've managed to get the 'labelnode' (of the try catch blocks) of the if statements, but can't figure out how to put it into a 'new' goto. How do I create a new GOTO and how do I put the 'labelnode' inside of it?

    Thanks in advance,

    EvilID

    You shouldn't have trouble creating new nodes.. But anyway, here is how (create a JumpInsnNode like shown below snippet):

    Java Code:
    int i = findNextException(method, pattern, exceptionName);

    if (i != -1) {
        LabelNode jmp = findNextJump(method, i, pattern.length);
        if (jmp != null) {
            method.instructions.insertBefore(method.instructions.get(i), new JumpInsnNode(Opcodes.GOTO, jmp));
        }
    }
    Last edited by Brandon; 04-28-2016 at 01:08 AM.
    I am Ggzz..
    Hackintosher

  6. #31
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Thanks for all the help!

    I have another question.

    I'm trying to detect the Walldecoration and BoundaryObject classes, but I can't figure out how to split them because they have the same properties.

    I'm now searching with te following pattern:
    Supername = java/lang/Object
    Rederable count = 2

    The script does find both of the classes.

    If I look for the fieldhooks, the patterns look like the same to.

    Can you give me a hand?

    Thanks in advance,

    EvilID

  7. #32
    Join Date
    Oct 2006
    Posts
    6,752
    Mentioned
    95 Post(s)
    Quoted
    532 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    Thanks for all the help!

    I have another question.

    I'm trying to detect the Walldecoration and BoundaryObject classes, but I can't figure out how to split them because they have the same properties.

    I'm now searching with te following pattern:
    Supername = java/lang/Object
    Rederable count = 2

    The script does find both of the classes.

    If I look for the fieldhooks, the patterns look like the same to.

    Can you give me a hand?

    Thanks in advance,

    EvilID
    Now you're getting to the fun part of making an updater! Once you get to any of the renderables classes and many others, you can't just really on a basic pattern like you described. You need to get more creative. For the wall decor and BoundaryObject, I count the amount of fields and the amount of renderable fields that are in the class. Be careful to check for your statics/non statics, since the static fields don't have to live in that class. I've used this pattern since like rev 50 and it's never broken.

    Good luck!
    “The long-lived and those who will die soonest lose the same thing. The present is all that they can give up, since that is all you have, and what you do not have, you cannot lose.” - Marcus Aurelius

  8. #33
    Join Date
    Jan 2012
    Posts
    10
    Mentioned
    0 Post(s)
    Quoted
    1 Post(s)

    Default

    Very ncie tnx

  9. #34
    Join Date
    Dec 2007
    Posts
    289
    Mentioned
    4 Post(s)
    Quoted
    86 Post(s)

    Default

    So I'm revisiting this and I can't believe how interesting I'm finding this learning experience.

    I'm only at the Node class (yes, the very beginning) and I've already encountered duplicate methods.
    I've actually executed the updater you attached to the original post and it appears to have broken. (or possibly the NodeAnalyser pattern used was never correct in the first place? Either way, no surprise considering how many revisions out of date it is).

    I figured I would share my discoveries thus far (as trivial as they may be)...

    Code:
    public class Node {
    
       public Node nextNode;
       public long id;
       Node previousNode;
    
       public boolean hasPrevious/isLinked() {
          return this.previousNode != null;
       }
    
       public boolean hasPrevious/isLinked() {
          return this.previousNode != null;
       }
    
       public void delete/unlink() {
          if(this.previousNode != null) {
             this.previousNode.nextNode = this.nextNode;
             this.nextNode.previousNode = this.previousNode;
             this.nextNode = null;
             this.previousNode = null;
          }
       }   
    
       public void delete/unlink() {
          if(this.previousNode != null) {
             this.previousNode.nextNode = this.nextNode;
             this.nextNode.previousNode = this.previousNode;
             this.nextNode = null;
             this.previousNode = null;
          }
       }
       
       protected Node() {
          try {
             super();
          } catch (RuntimeException var1) {
             throw ak.j(var1, "Node.<init>(" + ')');
          }
       }
    }
    I used https://github.com/kinztechcom/OSRS-.../src/Node.java to help me out.

    I found it rather interesting that the both the unlink/delete and hasPrevious/isLinked methods are both duplicated. I'm asumming that the duplicate methods are unused? The only way I can see myself finding out is by iterating through each class and seeing if it ever get's called. Does your own updater remove these duplicate methods?

    The NodeAnalyser in the original post identifies the nextNode field by searching for boolean methods and then the following opcode pattern {Opcodes.ALOAD, Opcodes.GETFIELD, Opcodes.IFNONNULL}. This will obviously identify the nextNode field as what is called the previousNode field in the refactored code above.

    I'm guessing it's just a case of getting next/previous muddled up when writing the example code?
    It also looks like you confused unlink/delete (a void method) with hasPrevious/isLinked (a boolean method). Although, my impression is that the pattern would work for both methods as the pattern exists in both.

  10. #35
    Join Date
    Jun 2014
    Location
    England
    Posts
    17
    Mentioned
    2 Post(s)
    Quoted
    10 Post(s)

    Default

    Most updaters you see do remove these, you have to be careful though with abstract methods and where they're used.

    Using a refactored client as a way to learn client structure is good, but basing your updater off it is bad. A refactored client has been change from what is represented by the bytecode to make it more readable. For example a decompile of the node class from the current client:
    Code:
    public class hd
    {
        public hd ea;
        public long ed;
        hd eu;
        
        public boolean iq() {
            return this.eu != null;
        }
        
        public void ia() {
            if (this.eu == null) {
                return;
            }
            this.eu.ea = this.ea;
            this.ea.eu = this.eu;
            this.ea = null;
            this.eu = null;
        }
        
        public boolean id() {
            return this.eu != null;
        }
        
        protected hd() {
            try {
                super();
            }
            catch (RuntimeException ex) {
                throw ak.j((Throwable)ex, "hd.<init>(" + ')');
            }
        }
        
        public void iy() {
            if (this.eu == null) {
                return;
            }
            this.eu.ea = this.ea;
            this.ea.eu = this.eu;
            this.ea = null;
            this.eu = null;
        }
    }
    This would use the ifnull opcode rather than ifnonnull in certain places where the refactor doesn't. In this situation it doesn't matter too much, else where you could come across issues.

  11. #36
    Join Date
    Dec 2007
    Posts
    289
    Mentioned
    4 Post(s)
    Quoted
    86 Post(s)

    Default

    Quote Originally Posted by Cov View Post
    Most updaters you see do remove these, you have to be careful though with abstract methods and where they're used.

    Using a refactored client as a way to learn client structure is good, but basing your updater off it is bad. A refactored client has been change from what is represented by the bytecode to make it more readable. For example a decompile of the node class from the current client:
    Code:
    -snip-
    This would use the ifnull opcode rather than ifnonnull in certain places where the refactor doesn't. In this situation it doesn't matter too much, else where you could come across issues.
    Oh don't get me wrong. The Node class I had written was derived by refactoring the current client's node (hd) class purely as a learning exercise.

    I found this tool https://github.com/Konloch/bytecode-viewer after a bit of searching and it shows the decompiled class (gives you the option of which decompiler to use, I prefer Fernflower) and the bytecode side by side.

    Code:
        public id() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnonnull L2
                 iconst_0
                 ireturn
             }
             L2 {
                 iconst_1
                 ireturn
             }
         }
    
         public iq() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnonnull L2
                 goto L3
             }
             L2 {
                 iconst_1
                 ireturn
             }
             L3 {
                 iconst_0
                 ireturn
             }
         }
    I suppose what you're saying is I need to be careful when one or both of those methods do not use the same underlying bytecode even if the end result is the same? In this case you're right, there's no difference in the pattern.

    In this fictional example for the node class, this could get a bit confusing I suppose?

    Code:
        public id() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnonnull L2
                 iconst_0
                 ireturn
             }
             L2 {
                 iconst_1
                 ireturn
             }
         }
    
         public iq() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnull L3
                 goto L2
             }
             L2 {
                 iconst_1
                 ireturn
             }
             L3 {
                 iconst_0
                 ireturn
             }
         }
    iq() uses IFNULL rather than IFNONNULL. How would I go about, using bytecode, identify that these two methods are essentially the same? Any tips would be much appreciated.

    Additionally, have you encountered scenarios where both versions of the duplicate methods are used?

    Interestingly (for me), when I used jd-gui to decompile the gamepack this is the result of the boolean methods in the Node class:
    Code:
      public boolean id()
      {
        if (this.eu == null) {
          return false;
        }
        return true;
      }
      
      public boolean iq()
      {
        return this.eu != null;
      }
    Without looking at the bytecode you might assume that they don't both use the ISNONNULL opcode (with iq() using ISNONNULL and id() using ISNULL). Fascinating.

  12. #37
    Join Date
    Jun 2014
    Location
    England
    Posts
    17
    Mentioned
    2 Post(s)
    Quoted
    10 Post(s)

    Default

    Quote Originally Posted by honeyhoney View Post
    Oh don't get me wrong. The Node class I had written was derived by refactoring the current client's node (hd) class purely as a learning exercise.

    I found this tool https://github.com/Konloch/bytecode-viewer after a bit of searching and it shows the decompiled class (gives you the option of which decompiler to use, I prefer Fernflower) and the bytecode side by side.
    Konloch's tool is great, for any jvm language it's the best thing out there for this sort of thing!!

    Quote Originally Posted by honeyhoney View Post
    I suppose what you're saying is I need to be careful when one or both of those methods do not use the same underlying bytecode even if the end result is the same? In this case you're right, there's no difference in the pattern.

    In this fictional example for the node class, this could get a bit confusing I suppose?

    Code:
        public id() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnonnull L2
                 iconst_0
                 ireturn
             }
             L2 {
                 iconst_1
                 ireturn
             }
         }
    
         public iq() { //()Z
             L1 {
                 aload0 // reference to self
                 getfield hd.eu:hd
                 ifnull L3
                 goto L2
             }
             L2 {
                 iconst_1
                 ireturn
             }
             L3 {
                 iconst_0
                 ireturn
             }
         }
    iq() uses IFNULL rather than IFNONNULL. How would I go about, using bytecode, identify that these two methods are essentially the same? Any tips would be much appreciated.
    Yes you have to be careful, with the code being reobfuscated each revision of runescape has the potential to have either the id or the iq version. I wouldn't take my word that this does happen, been a long time since I delved into the client for more than a few revisions.

    To get around this I'd probably build a control flow graph. Using that I could see that in either situation when the loaded field is null it returns false.

    For looking at how control flow graphs are generated https://github.com/lemonrs/LemonPick...onpicker/graph is a pretty good resource

    Quote Originally Posted by honeyhoney View Post
    Additionally, have you encountered scenarios where both versions of the duplicate methods are used?

    Interestingly (for me), when I used jd-gui to decompile the gamepack this is the result of the boolean methods in the Node class:
    Code:
      public boolean id()
      {
        if (this.eu == null) {
          return false;
        }
        return true;
      }
      
      public boolean iq()
      {
        return this.eu != null;
      }
    Without looking at the bytecode you might assume that they don't both use the ISNONNULL opcode (with iq() using ISNONNULL and id() using ISNULL). Fascinating.
    I haven't really encountered it, but there's always the potential for it depending on how hard the obfuscator goes on the code. Most duplicate methods are done by copying the instructions from the method into a new one with very little reordering. So you should be safe in assuming that they'll both be the same.

    Hope that helped a little

  13. #38
    Join Date
    May 2012
    Posts
    10
    Mentioned
    0 Post(s)
    Quoted
    3 Post(s)

    Default

    A few questions:
    - What is the point of de-obfuscating? Is it simply about making the analyse phase faster as less methods to process?
    - Are the names of the classes and fields arbitrary? As in, Actor is called Actor because I call it that. AnimationID could be called animId? etc
    - When I look at some hooks logs, people get different amounts of fields. For instance the Actor inside op post only has 2 fields, and one of them is SpokenText, however I don't see this field mentioned anywhere. How do I know what fields are available? How do I know what to look for. Obviously if I remove all the unused fields, the remaining fields must be for something. Is it a matter of trial and error accessing the fields via reflection and troubleshooting the value? Is there an updated list on what hooks are available (besides the output of other updaters)?
    Last edited by gmkizzle; 08-22-2016 at 05:55 AM.

  14. #39
    Join Date
    May 2012
    Posts
    10
    Mentioned
    0 Post(s)
    Quoted
    3 Post(s)

    Default

    Updated my above post. Can anybody help me with my questions?

  15. #40
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by gmkizzle View Post
    A few questions:
    - What is the point of de-obfuscating? Is it simply about making the analyse phase faster as less methods to process?
    - Are the names of the classes and fields arbitrary? As in, Actor is called Actor because I call it that. AnimationID could be called animId? etc
    - When I look at some hooks logs, people get different amounts of fields. For instance the Actor inside op post only has 2 fields, and one of them is SpokenText, however I don't see this field mentioned anywhere. How do I know what fields are available? How do I know what to look for. Obviously if I remove all the unused fields, the remaining fields must be for something. Is it a matter of trial and error accessing the fields via reflection and troubleshooting the value? Is there an updated list on what hooks are available (besides the output of other updaters)?

    Sorry, I didn't check this post in quite some time.. Anyway:


    1. The point of obfuscating is to make things HARDER in the first place. Not only is it harder to understand, the logic is harder to follow, the pattern changes, etc.. Deobfuscating thus has to be the opposite. Deobfuscating is to make things easier to find, understand, and write patterns for. If the client changes slightly in a newer revision, a deobfuscator would help your updater not break as easily. Patterns are easier to write. You don't have to write out every pattern possible for multipliers and other things. It's good practice to test your deobs on multiple revisions and run your updater on multiple revisions (I usually make sure mine works for 10-15 without fault).

    2. Actor is the same as Player/Character. It's not arbitrary. In game programming, a player is an actor or character. You customize your "character". An NPC is a Non-Player-Character (Computer, Player/Character that is not Human). Name it something that makes sense. Yes AnimationID can be called AnimID. It's still the same thing. If you called it playerID however, you'd be wrong.

    3. The fields on the OP is an EXAMPLE of a few fields my updater prints. There are MANY more fields that it prints but for the sake of simplicity of the tutorial, I chose 2 at random to make examples easier to deal with. If I explained every field of the Actor class, that'd be quite a long tutorial just for that ONE class. SpokenText not in any other updaters? Yes it is. Some people call it "OverheadText".

    How do you know what fields are available? You remove all unused fields which isn't many btw.. You've now narrowed down that the other fields are used. However, not all fields are USEFUL. You need to understand the client and understand what the fields do.

    For example, if I see a 2D array multiplied by a 2D array multiplied by another 2D array, I know that's the ModelViewProjection Matrix. If the result is then multiplied by a point, I know that point is being projected into 3D space from a 2D viewport.

    For example, if I see Strings in the player class, it could be a few things.. SpokenText, playerName, description, etc.. I can reflect those fields that are strings and print the values of them BEFORE adding them to my updater.. If it prints something useful, I add it. If it prints nothing useful, I check where it is used in the client. If I see it is important, I add it and figure out what the client is doing with it. You can replicate the client code and see what the field does, etc..

    There is so many ways to identify what fields do what. You can check Refactored clients too.. Others have already done quite a good job of showing what fields are what.
    Last edited by Brandon; 08-23-2016 at 01:14 AM.
    I am Ggzz..
    Hackintosher

  16. #41
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Quote Originally Posted by maven View Post
    Fake parameters are always the last parameter in a method. They can take the form of almost any primitive. They can be checked multiple times in a method or never at all. You can delete these checks and change the method's description. Depending on what analysis you are doing, you may want to update the method calls and remove the fake parameters. I don't understand your question about exceptions.
    Can you give me a hand about what to search for.

    For now I iterate trough all method instructions and I can remove every instruction I want.

    But I don't understand is how to remove the parameter. Do I have to remove te fieldcalls to that parameter in the instructions or is there more to do? I also don't understand how to detect if the parameter is used or not.

    Thanks in advance!
    Last edited by evilid; 10-15-2016 at 07:10 AM.

  17. #42
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    Can you give me a hand about what to search for.

    For now I iterate trough all method instructions and I can remove every instruction I want.

    But I don't understand is how to remove the parameter. Do I have to remove te fieldcalls to that parameter in the instructions or is there more to do? I also don't understand how to detect if the parameter is used or not.

    Thanks in advance!


    Fake parameters are parameters in a method where the last parameter is one of the following types: "I|S|B|Z". Next, you have to count the amount of VarInsnNode the signature has.

    If a method is static, it has 1 less parameter than a non-static method (that parameter is the "this" pointer). Write a function that counts the parameters in a method and the amount of space they take. A double and a long count as 2 VarInsnNode. All other parameters count as 1.


    Then you can do (check if the actual amount of VarInsnNode instructions match the amount of the signature):
    Java Code:
    Type[] types = Type.getArgumentTypes(method.desc);

            if (types.length > 0 && types[types.length - 1].toString().matches("I|S|B|Z")) {
                int lastParameterCount = getLastParameterCount(method); //Count actual method parameters.
                for (int i = 0; i < method.instructions.size(); ++i) {
                    if (method.instructions.get(i) instanceof VarInsnNode) {
                        int v = ((VarInsnNode) method.instructions.get(i)).var; //Count VarInsnNode.
                        if (v == lastParameterCount) {
                            return; //Parameter is used..
                        }
                    }
                }

                //Parameter is NOT used..
            }
    Last edited by Brandon; 10-15-2016 at 01:42 PM.
    I am Ggzz..
    Hackintosher

  18. #43
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Quote Originally Posted by Brandon View Post
    Fake parameters are parameters in a method where the last parameter is one of the following types: "I|S|B|Z". Next, you have to count the amount of VarInsnNode the signature has.

    If a method is static, it has 1 less parameter than a non-static method (that parameter is the "this" pointer). Write a function that counts the parameters in a method and the amount of space they take. A double and a long count as 2 VarInsnNode. All other parameters count as 1.


    Then you can do (check if the actual amount of VarInsnNode instructions match the amount of the signature):
    Java Code:
    Type[] types = Type.getArgumentTypes(method.desc);

            if (types.length > 0 && types[types.length - 1].toString().matches("I|S|B|Z")) {
                int lastParameterCount = getLastParameterCount(method); //Count actual method parameters.
                for (int i = 0; i < method.instructions.size(); ++i) {
                    if (method.instructions.get(i) instanceof VarInsnNode) {
                        int v = ((VarInsnNode) method.instructions.get(i)).var; //Count VarInsnNode.
                        if (v == lastParameterCount) {
                            return; //Parameter is used..
                        }
                    }
                }

                //Parameter is NOT used..
            }
    Got that! Do you know know if the client will run after the removal? I'd like to have the client working so I can use the getItemDefinition method for example without that it crashes every hook update because the client will ask for that fake parameter.

  19. #44
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    Got that! Do you know know if the client will run after the removal? I'd like to have the client working so I can use the getItemDefinition method for example without that it crashes every hook update because the client will ask for that fake parameter.

    After removing the parameter, you have changed the method's signature. You need to make sure that wherever that function is used, pushes the correct amount of parameters.

    For example, you have a function with 4 parameters and 1 is fake (3 real ones). Even though 1 is fake, the caller still has to push 4 parameters onto the stack. If you have modified the method to have the real signature (3 parameters), you thus need to find all usage of this function and only push 3 parameters on the stack. Otherwise you will have corruption and it will not run.


    Why do you want to use the modified deobfuscated client anyway? Your hook updater deobfuscates the jar and will always spit out the correct hook provided that you coded a stabled updater. If you did, then all you have to do is use the hooks your updater spit out. Not use the modified method. There's no need for that. You'll be playing quite a dangerous game with a modified client.
    Last edited by Brandon; 10-15-2016 at 03:08 PM.
    I am Ggzz..
    Hackintosher

  20. #45
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Well, the only thing I can't figure out about that is the following: if I use the parameter remover in my updater it spits out the method without the fake parameter. But if I want to invoke the method in the client than I need to pass that fake parameter because it won't work otherwise.

    Good one about editing the client, Jagex would not like that!

  21. #46
    Join Date
    Feb 2011
    Location
    The Future.
    Posts
    5,600
    Mentioned
    396 Post(s)
    Quoted
    1598 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    Well, the only thing I can't figure out about that is the following: if I use the parameter remover in my updater it spits out the method without the fake parameter. But if I want to invoke the method in the client than I need to pass that fake parameter because it won't work otherwise.

    Good one about editing the client, Jagex would not like that!

    Ahh you want to invoke the method. Uhh most of the time you can invoke it with a fake value for the last parameter OR have your updater find the value that is always passed in and pass that yourself. For example, you are identifying fake parameters by whether or not they are used. Since they aren't used, you can pass whatever you want for the fake value (with the right type of course [You won't pass a string where it expects an int]). Correct?

    Also, you already know what "Type" of fake parameters you are looking for. "I|S|B|Z" for example.
    Last edited by Brandon; 10-15-2016 at 03:56 PM.
    I am Ggzz..
    Hackintosher

  22. #47
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Quote Originally Posted by Brandon View Post
    Ahh you want to invoke the method. Uhh most of the time you can invoke it with a fake value for the last parameter OR have your updater find the value that is always passed in and pass that yourself. For example, you are identifying fake parameters by whether or not they are used. Since they aren't used, you can pass whatever you want for the fake value (with the right type of course [You won't pass a string where it expects an int]). Correct?

    Also, you already know what "Type" of fake parameters you are looking for. "I|S|B|Z" for example.
    Right now my hook updater adds a new field called 'dummy' to my Json output so I can parse that into my client when invoking the methods, is working like a charm :-)

    I have another question. My baseX and baseY keeps getting broken almost every hookupdate. Can you give me a hand on the right pattern to search for?

  23. #48
    Join Date
    Aug 2016
    Posts
    20
    Mentioned
    1 Post(s)
    Quoted
    6 Post(s)

    Default

    Quote Originally Posted by evilid View Post
    My baseX and baseY keeps getting broken almost every hookupdate. Can you give me a hand on the right pattern to search for?
    I don't know what kind of deob you do but this works for me.
    Code:
    rev 124 am.al(II)V
    
    GETSTATIC
    LDC
    IMUL
    ISUB
    BIPUSH
    ISHL
    
    
    static final void al(final int n, final int n2) {
        try {
            if (client.ar * -2085106287 != 2) {
                return;
            }
            fr.bc((client.aw * 1963721289 - ac.du * -1919225761 << 7) + client.at * 1280342549, client.aa * 1922336471 + (client.am * -786585365 - c.dv * 84272229 << 7), client.aq * 627759834, -1671205511);
            if (client.gu * 1718429031 > -1 && client.a * -1989590907 % 20 < 10) {
                ai.ea[0].i(client.gu * 1718429031 + n - 12, client.gn * -502901287 + n2 - 28);
            }
        }
        catch (RuntimeException ex) {
            throw w.e(ex, "am.al(" + ')');
        }
    }
    
    
      0 getstatic #109 <client/ar I>
      3 ldc #110 <-2085106287>
      5 imul
      6 iconst_2
      7 if_icmpeq 15 (+8)
     10 goto 14 (+4)
     13 return
     14 return
     15 getstatic #112 <client/aw I>
     18 ldc #113 <1963721289>
     20 imul
     21 getstatic #118 <ac/du I>
     24 ldc #119 <-1919225761>
     26 imul
     27 isub
     28 bipush 7
     30 ishl
     31 getstatic #122 <client/at I>
     34 ldc #123 <1280342549>
     36 imul
     37 iadd
     38 getstatic #126 <client/aa I>
     41 ldc #127 <1922336471>
     43 imul
     44 getstatic #129 <client/am I>
     47 ldc #130 <-786585365>
     49 imul
     50 getstatic #134 <c/dv I>
     53 ldc #135 <84272229>
     55 imul
     56 isub
     57 bipush 7
     59 ishl
     60 iadd
     61 getstatic #138 <client/aq I>
     64 ldc #139 <627759834>
     66 imul
     67 ldc #140 <-1671205511>
     69 invokestatic #146 <fr/bc(IIII)V>
     72 getstatic #149 <client/gu I>
     75 ldc #150 <1718429031>
     77 imul
     78 iconst_m1
     79 if_icmple 13 (-66)
     82 goto 85 (+3)
     85 getstatic #153 <client/a I>
     88 ldc #154 <-1989590907>
     90 imul
     91 bipush 20
     93 irem
     94 bipush 10
     96 if_icmpge 13 (-83)
     99 goto 102 (+3)
    102 getstatic #160 <ai/ea [Lcw;>
    105 iconst_0
    106 aaload
    107 getstatic #149 <client/gu I>
    110 ldc #150 <1718429031>
    112 imul
    113 iload_0
    114 iadd
    115 bipush 12
    117 isub
    118 getstatic #163 <client/gn I>
    121 ldc #164 <-502901287>
    123 imul
    124 iload_1
    125 iadd
    126 bipush 28
    128 isub
    129 invokevirtual #168 <cw/i(II)V>
    132 goto 13 (-119)
    135 new #69 <java/lang/StringBuilder>
    138 dup
    139 invokespecial #70 <java/lang/StringBuilder/<init>()V>
    142 ldc #170 <am.al(>
    144 invokevirtual #76 <java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;>
    147 ldc #77 <41>
    149 invokevirtual #80 <java/lang/StringBuilder/append(C)Ljava/lang/StringBuilder;>
    152 invokevirtual #84 <java/lang/StringBuilder/toString()Ljava/lang/String;>
    155 invokestatic #89 <w/e(Ljava/lang/Throwable;Ljava/lang/String;)Lez;>
    158 athrow

  24. #49
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Hmm.. New revision and now my invoke isn't working anymore.

    My updater found out:
    Code:
    Item : ar
    ItemID : ar.f * 986946269
    
    ItemDefinition : bv
    ItemName : u
    
    GetItemDefinition : au.f (II)Lbv;
    This is my invoke method: (removed dynamic hook loading for test purposes, I added the hooks straight away, but that also has to work):
    Code:
    int test = 0;
    return GlobalVariables.classLoader.loadClass("au").getMethod("f", int.class, int.class).invoke(null, itemID, test);
    ItemID is a parameter that is passed and that ID is correct.

    After all I receive a null object when I run that invoke.

    So when I try to print the item name, it will give the following error because the itemdefinition object is null:

    Code:
    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    	at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)
    	at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    Can someone maybe give me a hand?

    Thanks in advance!

    Edit:
    Fixed it myself. For everyone:
    The get itemdefinition method in class au (f) will throw a illegalstateException if the dummy parameter isn't a certain number:
    Code:
     if (-1303086541 * localbv.az != -1) { if (paramInt2 != -503467057) throw new IllegalStateException();
    Last edited by evilid; 10-22-2016 at 10:25 AM.

  25. #50
    Join Date
    Jun 2013
    Posts
    15
    Mentioned
    1 Post(s)
    Quoted
    12 Post(s)

    Default

    Can someone help me with the viewport height and width hook.

    I'm now searching for:
    getstatic client.or:int
    ldc 711889975 (java.lang.Integer)
    imul
    iconst_2
    idiv

    But in rev 119 for example it will give the viewportwidth, but in 125, 126 etc. it gives the viewportheight.

Page 2 of 3 FirstFirst 123 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •