Jump to content

[How & Why] Mouse Algorithm Alternative! [Make your scripts less detectable!]


NotoriousPP

Recommended Posts

Well I thought today I would release some of my private collection of different classes/snippets hopefully help new writers learn a little bit, and to maybe see a rise in quality of scripts throughout this forum.

For my fifth release is another great learning experience I undertook last month, creating a mouse movement algorithm using a bézier curve algorithm I created with the help of Google, a tutorial on here, and @Merccy & @Swizzbeat helping me understand how the mouse interacts with the canvas, how to send my own events to the canvas.

The reason I'm releasing this is because of the rise in bans as of recent, and I feel mouse movement plays a significant role in bans, though some people doubt this. I have to admit I didn't always think this was true either, and like some that still don't believe, I thought of profiling mouse movements as completely impossible due too the extensive resources that it would take to profile each player, though I will post some quotes from respected members of RS Hacking community that completely changed my thoughts about this. (Posting in text to avoid subliminal advertisement)

#1

pyroryan

Botwatch operates in specifically designated regions. Once a player is identified as a bot (whether that be manual or automatic), the system can analyze that player's actions and automatically ban others that may be using the same script (behaving similarly). I'm certain that mouse biometrics plays a role as well. To the extent of my knowledge, these bans are automatic.
As for dungeoneering and LRC, it's probably because Botwatch isn't set to it at the moment. If you based the lack of bans for dungeoneering off p****bot's scripts, then it's because Botwatch isn't set to it.
Regarding mouse biometrics, it's actually not a very CPU intensive process. As Method stated earlier, the cost for transmitting the mouse clicks is minimal, they could actually add angular based biometrics to it. The cost of that would be ~12 bytes total (an increase in 6 bytes). There was a paper published on the topic that used a Pentium 4 Xeon 3.0Ghz processor. They used angular based biometrics and were able to build profiles for 1000 users that inputted ~5000 clicks in 20 seconds. Once that profile was built, they claimed to be able to verify 5800 clicks in 230ms. Even if this is was exaggeration on the part of the researchers, the cost to verify a profile is still quite low.
Given the size of Jagex's servers and the skills of their employees, I wouldn't doubt their ability to build a profile for a bot (like p****bot) and use that profile to find users of the bot (which would only involve verification, thus not consume nearly as many resources). A few of the Fellows from p****bot apparently proved the concept and hence, forced the changes in p****bot's mouse. Obviously Jagex can't build a profile for all of it's users given the size of the game, but they can certainly target bots with a mouse implementation that very rarely resembles human behavior.

TL;DR: A Pentium 4 Xeon 3.0Ghz processor was able to profile 1000 people, click at a rate of ~5000 in 20 seconds, using angular based biometrics. We all know Jagex has much much much more at their disposal than a single Pentium 4...



#2

pplsuqbawlz

Don't believe the hype about them recording your mouse and crap?
 

    if (MOUSEBUTTON_LAST != 0) {
                    anInt2363++;
                    long when = ((MOUSEPRESS_WHEN - aLong1203) / 50L);
                    aLong1203 = MOUSEPRESS_WHEN;
                    int x = MOUSEPRESS_X;
                    int y = MOUSEPRESS_Y;

                    if (x >= 0) {
                        if (x > 764) {
                            x = 764;
                        }
                    } else {
                        x = 0;
                    }

                    if (y >= 0) {
                        if (y > 502) {
                            y = 502;
                        }
                    } else {
                        y = 0;
                    }

                    int rightclick = 0;
                    if (MOUSEBUTTON_LAST == 2)
                        rightclick = 1;

                    if (when > 4095L)
                        when = 4095L;

                    int time = (int) when;
                    int loc = y * 765 + x;
                   
                    out.writeFrame(234);
                    out.writeIntInverse((rightclick << 19) + (time << 20) + loc);
                }
Mrr. I showeth some pr00f, now bow!

 

This was posted in 2006... So we know this has been going on a lot longer than most of you have realized.



#3

unlimitedorb (Quoted, unknown original)


Primitive programs typically recognize the object, but click the same spot (often the same pixel.) This immediately raises the alarm if it is done consistently. Most programs do not do this, though, but rather have an "area of uncertainty" where the click will randomly fall in. This is still easy to detect. There is accuracy, and precision. These programs do not replicate human precision. Consider the dartboard as an example: The goal is to simply "hit it." A human will still aim for the bullseye, to increase the chance of hitting the dartboard. Thus hits will be concentrated towards the bullseye, but there will still be hits nowhere close, and some misses too.

A macro does not have human flaws, and can always hit the dartboard. However, if randomized in the "area of uncertainty" there is no such pattern." This will also raise the alarm. More advanced yet, some macros will actually form concentric regions of where the clicks will land. Still, we're always ahead of rulebreakers. Our final line of defense in this criteria is to analyze the regions most commonly clicked.

A macro tends to click in a perfect square, circle, or sometimes the shape of an interface icon. Sometimes even the region is randomized. Human behavior is not truly random however. The region most commonly clicked is related to placement, which is all I know about this. Highly advanced bots have made an attempt to replicate even this, but we have not seen anything convincing yet. Admittedly, we're disadvantaged in this aspect, so we cannot fully rely on simple movement and accuracy to detect a macro program.

The next criteria is the actual sequence of actions. A player that decides to cut some trees for logs, and sell them for profit actually has a longer list of actions to perform than you'd think. The efficiency of which this is completed can be analyzed, and much more easily compared to the behavior of a macro programs' attempt to replicate it. If each step is merely randomized with the same bounds of uncertainty like virtually all bots seem to do today, the actual time it takes to execute the actions in all converges to a specific value! It's similar to flipping a fair coin multiple times, and converging to a frequency of outcomes (namely 50%.) Humans are generally much less consistent, and once the consistency falls within a certain range, the alarm is raised.

One more of many criteria is the effect of total gameplay time. As expected, exhaustion will set in for most players and slow down their actions. This is not a completely reliable method, since some players have been able to keep up their concentration for remarkably long periods of time."

"The last criteria I really know of is probably the most obscure and advanced. Human players tend to have much better object recognition capabilities than a macro program, and the limitations of the procedure can be exploited. While a human may be able to recognize a tree at a very unusual and discrete angle, many macros lack this capability, and thus keep the camera angle within a certain range. Some fail to change it entirely. Macros tend to locate objects that are far out of reach by going close to the area in question, and then finding it. Normal players tend to look ahead first. There are probably many more techniques employed, and the genius and innovative capability of my coworkers is simply amazing. I am very confident in their ability to enforce the rules, and keep RS a fair, and equal environment. The detection system is definitely conducive to such, but that is not our only method.


The next is abuse reports. There are many new and better bots, just written, that can avoid at a few of the criteria, and not be flagged. The intuition of a human being can never be surpassed, and abuse reports give us an all seeing eye that brought many rule breakers to justice. Abuse reports are also helpful for locating the archives, and comparing the new behavior of the new macro that was previously able to avoid detection. We can update accordingly. We highly encourage abuse reporting, and we will not punish players who send in reports with a reasonable cause to suspect the player in question is using a macro.

Circumstances (such as the usual range of playing time) is taken into account as well.

Literally one of the best breakdowns of the process of bans I have read to date, it may be old, but old habits die hard, and I seriously doubt have changed their tactics terms of bans much.
TL;DR: A lot of factors go into bans, more than most users think.



Those excerpts from above are some of the better material I have found regarding bans, but there is much much more on the topic, just a matter of digging deep enough to find it! Though a mouse change alone won't completely remove the chances of a ban, it gives you a better chance of going undetected. Now lets get started!
 
What does this actually do?
Well simply make your mouse completely different, using a bézier curve algorithm I created using a framework Swizzbeat and Merccy supplied me with.
The final result, should look somewhat like this:


(This is just set on a random to show trails of the mouse; as a test go to your bot, turn on mouse trails, and see the difference; it will be surprising!)
3512ec8a18637635fa5dc0343b56ff0b.gif


 
Though this could be highly improved upon, it is a huge improvement to the default, and there are also other mouse controllers such as the SRL Mouse and WindMouse which are available on Google, just may require some porting over.
 
How does is work?
 
Well when creating this instead of starting by looking through RS examples, I instead went and study the math behind bézier curves, to find out they were quite simple to grasp. Then after seeing a idea for a mouse controller posted that I thought would be suited perfect for my use, I decided to replicate it. This is the basic guideline I followed when creating this.


trig1.png
(Though I chose to use cubic curve which uses 4 control points instead of 3, like this quadratic displayed)


 
Finally, how the hell do I use this?:
 
Well even though I took out most of the work, it still takes some on your side, just mostly copy/pasting, thought I recommend that you edit this mouse algorithm because the more similar patterns the more chances of you being detected.
 
Well this tutorial will partially coincide with @Merccy's tutorial on Creating your own Mouse Controller, though I have made edits and extended some other areas he did not.

  • First off we need to create a interface which we can use later to create new mouse algorithms easily and making changing them a snap.


    package tools.api.methods.input.mouse.algos;
    
    import org.osbot.script.mouse.MouseDestination;
    
    public abstract interface Mouse
    {
    public abstract boolean moveMouse(MouseDestination paramMouseDestination, boolean paramBoolean)
    throws InterruptedException;
    
    public abstract boolean moveMouse(MouseDestination paramMouseDestination, boolean paramBoolean1, boolean paramBoolean2)
    throws InterruptedException;
    
    public abstract boolean moveMouse(int paramInt1, int paramInt2, MouseDestination paramMouseDestination, boolean paramBoolean, double paramDouble)
    throws InterruptedException;
    
    public abstract boolean moveMouse(int paramInt1, int paramInt2, MouseDestination paramMouseDestination, boolean paramBoolean1, double paramDouble, boolean paramBoolean2)
    throws InterruptedException;
    
    public abstract boolean moveMouseTo(MouseDestination paramMouseDestination, boolean paramBoolean1, boolean paramBoolean2, boolean paramBoolean3)
    throws InterruptedException;
    }
    


     

  • In Merccy's tutorial he creates a MouseController class which handles moveMouse and moveMouseTo methods, though this is also where we assign our new MouseController as well.


    (EDITED: 5:44PM GMT -8 5/30/2014) Changed 'super' to 'mouse' variable!

    import java.applet.Applet;
    import java.awt.*;
    
    public class ModifiedMouseController extends MouseController {
    
        Script sI;
        NotoriousMouse mouse;
    
        public ModifiedMouseController(Script sI, Applet applet, Canvas canvas) {
            super(sI.bot, applet);
            try {
                this.mouse = new NotoriousMouse(sI, canvas); //The mouse controller
                this.sI = sI;
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        
        @Override
        public boolean moveMouse(MouseDestination destination, boolean drag) throws InterruptedException {
            return mouse.moveMouse(destination, drag);
        }
    
        @Override
        public boolean moveMouseTo(MouseDestination destination, boolean drag, boolean click, boolean rightClick) throws InterruptedException {
            return mouse.moveMouse(destination, drag, click, rightClick);
        }
    
    }
    
    


     

  • We are adding this class becasue it seems that Merccy didn't mention it, though we need a class that can send our new mouse events to the canvas to have it move the mouse.


    package tools.api.methods.input.mouse;
    
    import java.awt.Component;
    import java.awt.event.MouseEvent;
    import org.osbot.engine.Bot;
    import org.osbot.engine.input.BotEvent;
    
    public class ModifiedMouseEvent extends MouseEvent implements BotEvent {
    
        public ModifiedMouseEvent(Component source, int id, long when, int modifiers, int x, int y, int clickCount, boolean popupTrigger, int button) {
            super(source, id, when, modifiers, x, y, clickCount, popupTrigger, button);
        }
    
        public int getParentId() {
            return 0;
        }
    
        public void setParentId(int i){
        }
    
        public void setChildId(int i){
        }
    
        public int getChildId(){
            return 0;
        }
    
        public void pushEvent(Bot bot) throws InterruptedException {
        }
    
        public long getExecutionTime(){
            return 0L;
        }
    
        public int compareTo(Object o){
            return 0;
        }
    }
    
    


     

  • Now we Object hold this new mouse we created, so for this I created ModMouse, which basically reflects and sets our mouse controller to replace the original. This is similar to Merccy's though we also set our MouseEvent as well.


    import org.osbot.engine.Bot;
    import org.osbot.engine.input.MouseController;
    import org.osbot.script.Script;
    
    import java.applet.Applet;
    import java.awt.*;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * Created with IntelliJ IDEA.
     * User: NotoriousPP
     * Date: 4/18/14
     * Time: 10:06 AM
     */
    public class ModMouse  {
    
        private Script script;
    
        public ModMouse(Script script) {
            this.script = script;
            setModMouseController(script);
        }
    
        private Applet getApplet() throws IllegalAccessException {
            for (Field current : MouseController.class.getDeclaredFields()) {
                if (current.getType().equals(Applet.class)) {
                    current.setAccessible(true);
                    return (Applet)current.get(this.script.bot.getMouse());
                }
            }
            return null;
        }
    
        private Canvas getCanvas() throws InvocationTargetException, IllegalAccessException {
            for (Method current : Bot.class.getMethods()) {
                if (Canvas.class.isAssignableFrom(current.getReturnType())) {
                    return (Canvas)current.invoke(this.script.client.getBot());
                }
            }
            return null;
        }
    
        public boolean setModMouseController(Script s) {
            Applet app = null;
            s.log("Trying to find RS Applet.");
            try {
                for (Field f : MouseController.class.getDeclaredFields()) {
                    if (f.getType().equals(Applet.class)) {
                        s.log("[SUCCESS] Found RS Applet.");
                        app = (Applet) f.get(s.bot.getMouse());
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            if (app == null) {
                s.log("[ERROR] Couldn't find the RS Applet.");
                return false;
            }
    
            ModifiedMouseController myController = null;
            try {
                myController = new ModifiedMouseController(s, getApplet(), getCanvas());
                s.log("Created ModifiedMouseController.");
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            if (myController == null) {
                s.log("ModifiedMouseController couldn't be created.");
            }
    
            for (Field f : Bot.class.getDeclaredFields()) {
                try {
                    if (f.getType().equals(MouseController.class)) {
                        s.log("Found MouseController, Attempting to modify...");
                        f.setAccessible(true);
                        s.log("Field is accessible");
                        try {
                            f.set(s.bot, myController);
                        } catch (Exception e) {
                            s.log("Error setting the MouseController to the ModifiedMouseController.");
                            return false;
                        }
                        s.log("Successfully changed field, making it private again.");
                        f.setAccessible(false);
                        s.log("Done injecting.");
                        return true;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return false;
        }
    }
    
    
    
     


     

  • Finally we have everything we need to set use our own mouse algorithm, but we need a Mouse algorithm to use it! I named this NotoriousMouse purely to change the name other a Mouse controller sent by Swizz beat, which I then ripped all the internals out and rewrote using the new found knowledge I learned while studying bézier curves! This may not be the best, but it's a big step up!


    import org.osbot.script.MethodProvider;
    import org.osbot.script.Script;
    import org.osbot.script.mouse.MouseDestination;
    import org.osbot.script.mouse.RectangleDestination;
    import tools.api.methods.input.mouse.ModifiedMouseEvent;
    
    import java.awt.*;
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    
    public class NotoriousMouse {
    
        private final char[] USER_HASH;
        private final int CANVAS_WIDTH = 502;
        private final int CANVAS_HEIGHT = 765;
        private int mouseSpeed;
        private Random random;
        private Script sI;
        private Canvas canvas;
    
    
        public NotoriousMouse(Script sI, Canvas canvas){
            this.sI = sI;
            this.canvas = canvas;
            this.USER_HASH = hash(sI.myPlayer() != null ? sI.myPlayer().getName() : sI.bot.getUsername()).toCharArray();
            this.mouseSpeed = 10;
            this.random = new Random();
        }
    
        public boolean moveMouse(MouseDestination destination, boolean drag) throws InterruptedException {
            Point endPoint = getRandomPoint(destination);
            if (this.sI.client.isMouseOutsideScreen()) {
                placeMouseOnCanvas((int)(1.0D + random(5.0D)));
            }
            if (drag) {
                this.sI.client.pressMouse();
            }
            handleMouseMovement(sI.client.getMousePosition(), endPoint);
            if (drag) {
                this.sI.client.releaseMouse();
            }
            return true;
        }
    
        public boolean moveMouse(MouseDestination destination, boolean drag, boolean click, boolean rightClick) throws InterruptedException {
            Point endPoint = getRandomPoint(destination);
            if (this.sI.client.isMouseOutsideScreen()) {
              placeMouseOnCanvas((int)(1.0D + random(5.0D)));
            }
            if (drag) {
              this.sI.client.pressMouse();
            }
            handleMouseMovement(sI.client.getMousePosition(), endPoint);
            if (drag) {
              this.sI.client.releaseMouse();
            }
            if (click) {
              this.sI.client.clickMouse(rightClick);
            }
            return true;
        }
    
        private void placeMouseOnCanvas(int side) {
            switch (side) {
                case 1:
                    sendEvent(new Point(0, (int)(1.0D + random(765.0D))));
                    break;
                case 2:
                    sendEvent(new Point((int)(1.0D + random(765.0D)), 0));
                     break;
                case 3:
                    sendEvent(new Point(502, (int)(1.0D + random(765.0D))));
                    break;
                case 4:
                    sendEvent(new Point((int)(1.0D + random(502.0D)), 765));
                    break;
            }
        }
    
        private void handleMouseMovement(Point startPoint, Point endPoint) throws InterruptedException {
            Point[] controlPoints = generateControlPoints(startPoint, endPoint);
            List<Point> mousePoints = new ArrayList<>();
            for (double t = 0.0D; t <= 1.0D; t += .1) {
                mousePoints.add(calculateBezierPoint(t, startPoint, controlPoints[0], controlPoints[1], endPoint));
            }
            for (Point point : mousePoints) {
                int random = MethodProvider.gRandom(mouseSpeed, 2);
                sI.sleep(mouseSpeed + Math.abs(random));
                sendEvent(point);
            }
            if (!this.sI.client.getMousePosition().equals(endPoint)){
                sendEvent(endPoint);
            }
        }
    
        private void sendEvent(Point point) {
            this.canvas.dispatchEvent(new ModifiedMouseEvent(this.canvas, 503, System.currentTimeMillis(), 0, point.x, point.y, 0, false, 0));
        }
    
        private Point[] generateControlPoints(Point startPoint, Point endPoint) {
            RectangleDestination startBoundingBox = createRectangle(getTPoint(gRandom(0.4D - hexToInt(this.USER_HASH[37]) / 100, 0.2D + hexToInt(this.USER_HASH[0]) / 100), startPoint, endPoint), this.random.nextInt(86 + hexToInt(this.USER_HASH[1])) + 15 + hexToInt(this.USER_HASH[2]), this.random.nextInt(30 + hexToInt(this.USER_HASH[3])) + 15 + hexToInt(this.USER_HASH[4]));
            RectangleDestination endBoundingBox = createRectangle(getTPoint(gRandom(0.7D - hexToInt(this.USER_HASH[36]) / 100, 0.2D + hexToInt(this.USER_HASH[5]) / 100), startPoint, endPoint), this.random.nextInt(86 + hexToInt(this.USER_HASH[6])) + 15 + hexToInt(this.USER_HASH[7]), this.random.nextInt(100 + hexToInt(this.USER_HASH[8])) + 20 + hexToInt(this.USER_HASH[9]));
            return new Point[] { getRandomPoint(startBoundingBox), getRandomPoint(endBoundingBox) };
        }
    
        private RectangleDestination createRectangle(Point center, int desiredWidth, int desiredHeight) {
            Rectangle rectangle = new Rectangle(center.x - desiredWidth / (this.random.nextInt(hexToInt(this.USER_HASH[10])) + 1), center.y - desiredHeight / (this.random.nextInt(hexToInt(this.USER_HASH[11])) + 1), desiredWidth, desiredHeight);
            if (rectangle.x < 0) {
              rectangle.x = 0;
            }
            if (rectangle.y < 0) {
              rectangle.y = 0;
            }
            return new RectangleDestination(rectangle);
        }
    
        private double calculateDistance(Point start, Point end) {
            return Math.hypot(end.getX() - start.getX(), end.getY() - start.getY());
        }
    
        private double getThetaIncrement(Point p1, Point p2, Point p3, Point p4) {
            double lineOneLength = calculateDistance(p1, p2);
            double lineTwoLength = calculateDistance(p2, p3);
            double lineThreeLength = calculateDistance(p3, p4);
            return 1.0D / (lineOneLength + lineTwoLength + lineThreeLength);
        }
    
        public Point calculateBezierPoint(double t, Point p0, Point p1, Point p2, Point p3) {
            return new Point(calcCurveAxis(t, p0, p1, p2, p3, true),calcCurveAxis(t, p0, p1, p2, p3, false));
        }
    
        public int calcCurveAxis(double t, Point p0, Point p1, Point p2, Point p3, boolean getX){
            double u = 1 - t;
            double tt = Math.pow(t, 2.0D);
            double uu = Math.pow(u, 2.0D);
            double uuu = Math.pow(u, 3.0D);
            double ttt = Math.pow(t, 3.0D);
            int i = (int)(uuu * (getX ? p0.getX() : p0.getY())); //first term
            i += (int)(3 * uu * t * (getX ? p1.getX() : p1.getY())); //second term
            i += (int)(3 * u * tt * (getX ? p2.getX() : p2.getY())); //third term
            i += (int)(ttt * (getX ? p3.getX() : p3.getY())); //fourth term
            return i;
        }
    
        private Point getTPoint(double t, Point p1, Point p2) {
            int x = (int)((1.0D - t) * p1.x + t * p2.x);
            int y = (int)((1.0D - t) * p1.y + t * p2.y);
            return new Point(x, y);
        }
    
        private Point getRandomPoint(MouseDestination destination) {
            Rectangle rectangle = destination.getBoundingBox();
            int x = -1;
            int y = -1;
            if(rectangle != null){
                while (!rectangle.contains(x, y)) {
                  x = (int)gRandom(rectangle.getX() + rectangle.getWidth() * Math.random(), hexToInt(this.USER_HASH[38]));
                  y = (int)gRandom(rectangle.getY() + rectangle.getHeight() * Math.random(), hexToInt(this.USER_HASH[39]));
                }
            }
            return new Point(x, y);
        }
    
        private double random(double max) {
            return Math.random() * max;
        }
    
        private double gRandom(double mean, double variance) {
            return mean + this.random.nextGaussian() * variance;
        }
    
        private int hexToInt(char c) {
            return Integer.parseInt(String.valueOf(c), 16);
        }
    
        public void setMouseSpeed(int mouseSpeed){
        this.mouseSpeed = mouseSpeed;
        }
    
        //Thank Merccy for this, a hash value random seed based system, to kinda have each user a unique profile!
        private String convertToHex(byte[] data) {
            StringBuilder buf = new StringBuilder();
            for (byte b : data) {
                int halfByte = b >>> 4 & 0xF;
                int twoHalf = 0;
                do {
                    if ((0 <= halfByte) && (halfByte <= 9))
                        buf.append((char)(48 + halfByte));
                    else
                        buf.append((char)(97 + (halfByte - 10)));
                    halfByte = b & 0xF;
                }while (twoHalf++ < 1);
            }
            return buf.toString();
        }
    
        public String hash(String text) {
            MessageDigest md = null;
            try {
                md = MessageDigest.getInstance("SHA-1");
            }
            catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            byte[] sha1hash = new byte[40];
            if(md != null){
                try {
                    md.update(text.getBytes("iso-8859-1"), 0, text.length());
                }
                catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                sha1hash = md.digest();
            }
            return convertToHex(sha1hash);
        }
        //-----------
    }
    
    
    


     

  • So we have all these files ready to go, and you should have something looking like this:
    46c9c029af.png
     
  • For the hardest part of all is implementing it, please pay attention as this may be difficult for some to understand.
        @Override
        public void onStart() {
            new ModMouse(this);
        }
    
    Done. If you manage to follow all the directions and copy/pasted everything just right you should have a whole new mouse in your script!

    You now are on the road to having a more diverse mouse controller, though please be warned this is only for OSBot1, I have already tried implementing this into OSBot2 but the mouse methods are now declared as final and are no longer able to be overridden (If there's another way please let me know).

    I really hope you enjoyed the read, and I hope it helps all of you! smile.png

    I would post my sources and references but I withheld from doing so in fear of ban due to accidentally advertising, though I'm sure could be found with someone interested in the subject.

Questions/Comments?:
If you see anything I messed up on, or should be improved, please let me know, but be respectful about it, we have too many keyboard warriors thinking their hot shit, yet do nothing but bash others and never give any useful resources.
Even if you have a question, free to ask me, just please refrain from asking me blatant obvious questions, or ones you did little to no research on before asking, I'm not here to spoon feed you, though I am willing to help someone is trying.

Edited by NotoriousPP
  • Like 17
Link to comment
Share on other sites

Nice read. I remember the windmouse created by Ben for SRL wich was quite amazing. I have already  seen a similar code in pascal but I am gonna take a closer look at your new implentation that I bet will be teh shit.

 

 

 

 It was about time that someone started discussing about the obvious problem that the

 

 actual OSbot mouse represents.

 

 

Most interesting post I have read on this forum since I joined.

Edited by denoxum
  • Like 2
Link to comment
Share on other sites

You should probably add a part regarding correctly sending events. It's probably very easy to detect a bot if you press the mouse using default API methods, and then suddenly start sending MOUSE_MOVED events instead of MOUSE_DRAGGED or something similar which should normally be happening.

 

Great guide nonetheless mate <3

  • Like 1
Link to comment
Share on other sites

Amazing read. I think mouse movements are a crucial part of Jagex's bot watch. Since all scripts use the same API methods with the same mouse controller, all bots would have the same profile. If, according to your first quote, it would be possible for Jagex to compare profiles of different players, it would explain why Jagex is so good at detecting bots nowadays.

 

What I think that needs to be implemented in OSBot: let all accounts have different bot profiles (different mouse speed, accuracy and mouse movement patterns). What also would be a nice addition, is that each bot could change its behavior at random times. For example, sometimes your concentration is good, at other moments you like to afk a lot or you are tired (thereby decreasing your mouse speed and accuracy).

 

I thought about writing my own mouse controller too, but I failed (seeing your code, I can imagine why). So an amazing thanks for these snippets. I personally had the idea of recording my own mouse movements (say 300+ different paths). Then every time the bot moves the mouse, a random path is picked based on the distance that needs to be covered. Of course you will need to rotate and scale this path, but that's not a problem. Add some extra randomization and you would have amazingly realistic and undetectable mouse movements.

  • Like 1
Link to comment
Share on other sites

Amazing read. I think mouse movements are a crucial part of Jagex's bot watch. Since all scripts use the same API methods with the same mouse controller, all bots would have the same profile. If, according to your first quote, it would be possible for Jagex to compare profiles of different players, it would explain why Jagex is so good at detecting bots nowadays.

 

What I think that needs to be implemented in OSBot: let all accounts have different bot profiles (different mouse speed, accuracy and mouse movement patterns). What also would be a nice addition, is that each bot could change its behavior at random times. For example, sometimes your concentration is good, at other moments you like to afk a lot or you are tired (thereby decreasing your mouse speed and accuracy).

 

I thought about writing my own mouse controller too, but I failed (seeing your code, I can imagine why). So an amazing thanks for these snippets. I personally had the idea of recording my own mouse movements (say 300+ different paths). Then every time the bot moves the mouse, a random path is picked based on the distance that needs to be covered. Of course you will need to rotate and scale this path, but that's not a problem. Add some extra randomization and you would have amazingly realistic and undetectable mouse movements.

 

IMHO,mouse movements are not cause of bans. The cause o ban are hot spots where you click.

If you ban 100 bots you and you have recorded their mouse hot spots, you can easily ban another 100 comparing them.

The thing is to make mouse not herping derping around one point.

 

  • Like 2
Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...