Thread: Decoding buttons with the interface id and interface cheat protection

Page 1 of 2 12 LastLast
Results 1 to 10 of 12
  1. #1 Decoding buttons with the interface id and interface cheat protection 
    Endeavor

    Mikey`'s Avatar
    Join Date
    Dec 2007
    Posts
    4,434
    Thanks given
    715
    Thanks received
    1,435
    Rep Power
    1202
    Basically what we are doing here is modifying the client to send every button click packet with the parent interface id, and we're installing a system to control how buttons are processed. This will also prevent players from faking clicks/item actions on any interface they aren't actually viewing. You will need to track sidebars too, but I'll leave that to you.

    The base is: http://www.rune-server.org/runescape...8-14-13-a.html, but can adapted.

    Server sided

    First we add this class:
    Code:
    package org.model.actor.player.inter;
    
    import org.model.actor.player.Player;
    
    /**
     * Processes interface clicking.
     * 
     * @author Michael Sasse
     *
     */
    public interface InterfaceAction {
    	
    	/**
    	 * Actions to take when a button is clicked
    	 * @param p
    	 * 			the (@Player)
    	 * @param id
    	 * 			the button id
    	 */
    	public void click(Player p, int id);
    	
    	/**
    	 * Do an item action on an interface
    	 */
    	public void doItemAction(Player p, int slot, int id, int amount);
    }
    then this class:
    Code:
    package org.model.actor.player.inter;
    
    import org.model.actor.player.inter.impl.*;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Constants for user interfaces
     * 
     * @author Michael Sasse
     *
     */
    public class InterfaceConstants {
    	
    	/**
    	 * A map of (@InterfaceAction)s
    	 */
    	private static final Map<Integer, InterfaceAction> actions = new HashMap<Integer, InterfaceAction>();
    	
    	/**
    	 * The default interface manager.
    	 */
    	public static final DefaultInterfaceAction DEFAULT_ACTIONS = new DefaultInterfaceAction();
    	
    	/**
    	 * The bank interface id
    	 */
    	public static final int BANK = 5292;
    	
    	/**
    	 * Sets the interface actions
    	 */
    	static {
    		actions.put(BANK, new BankInterfaceAction());
    	}
    	
    	/**
    	 * Gets the (@InterfaceButton) for the id
    	 */
    	public static final InterfaceAction getInterfaceManager(int id) {
    		return actions.get(id);
    	}
    }
    then this class:

    Code:
    package org.model.actor.player.inter;
    
    import static org.model.actor.player.inter.InterfaceConstants.*;
    
    import org.RuntimeConstants;
    import org.model.actor.player.Player;
    
    /**
     * Controls client actions based on the current user interface.
     * This could be adapted to work with the cache later, for further verification of client actions.
     * 
     * @author Michael Sasse
     *
     */
    ///TODO: using items with these interfaces adapted to this
    public class Interfaces {
    	
    	/**
    	 * The current interface id
    	 */
    	private int current = -1;
    	
    	/**
    	 * The current sub-interface id
    	 */
    	private int sub = -1;
    	
    	/**
    	 * Item actions on an interface
    	 */
    	public void onItemAction(Player p, int slot, int id, int amount, int inter) {
    		if (inter == current || inter == sub) {
    			InterfaceAction manager = getInterfaceManager(inter);
    			
    			if (manager != null)
    				manager.doItemAction(p, slot, id, amount);
    		} else {
    			DEFAULT_ACTIONS.doItemAction(p, slot, id, amount);
    		}
    		
    		if (RuntimeConstants.DEBUG)
    			p.getActionSender().sendMessage("item action interface: " + inter);
    	}
    	
    	/**
    	 * Actions to do when clicking a button
    	 * 
    	 * @param id
    	 * 		the button id
    	 * @param inter
    	 * 		the interface id
    	 */
    	public void onButton(Player p, int id, int inter) {
    		if (inter == current || inter == sub) {
    			InterfaceAction manager = getInterfaceManager(inter);
    			
    			if (manager != null)
    				manager.click(p, id);
    		} else {
    			DEFAULT_ACTIONS.click(p, id);
    		}
    		
    		if (RuntimeConstants.DEBUG) {
    			p.getActionSender().sendMessage("button: " + id + ", interface: " + inter);
    		}
    	}
    	
    	/**
    	 * Sets the current interface id
    	 */
    	public void setCurrent(int current, int sub) {
    		this.current = current;
    		this.sub = sub;
    	}
    	
    	/**
    	 * Resets the current interface to none
    	 */
    	public void reset() {
    		current = -1;
    		sub = -1;
    	}
    
    }
    and here's two implementations for reference:
    Code:
    package org.model.actor.player.inter.impl;
    
    import org.model.actor.player.Player;
    import org.model.actor.player.inter.InterfaceAction;
    
    /**
     * Bank interface actions.
     * 
     * @author Michael Sasse
     *
     */
    public class BankInterfaceAction implements InterfaceAction {
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.model.actor.player.inter.InterfaceButton#click(org.model.actor.player.Player, int)
    	 */
    	@Override
    	public void click(Player p, int id) {
    		
    	}
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.model.actor.player.inter.InterfaceAction#doItemAction(org.model.actor.player.Player, int, int, int)
    	 */
    	@Override
    	public void doItemAction(Player p, int slot, int id, int amount) {}
    }
    Code:
    package org.model.actor.player.inter.impl;
    
    import org.model.actor.player.Player;
    import org.model.actor.player.inter.InterfaceAction;
    
    /**
     * Actions that are either always executable or undefined.
     * 
     * @author Michael Sasse
     *
     */
    public class DefaultInterfaceAction implements InterfaceAction {
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.model.actor.player.inter.InterfaceButton#click(org.model.actor.player.Player, int)
    	 */
    	@Override
    	public void click(Player p, int id) {
    		switch (id) {
    		case 9154:
    			p.logout();
    			break;
    		case 153:
    			p.getMovement().setRun(true);
    			break;
    		case 152:
    			p.getMovement().setRun(false);
    			break;
    		}
    	}
    
    	/*
    	 * (non-Javadoc)
    	 * @see org.model.actor.player.inter.InterfaceAction#doItemAction(org.model.actor.player.Player, int, int, int)
    	 */
    	@Override
    	public void doItemAction(Player p, int slot, int id, int amount) {
    	}
    }
    Now you will have to adapt your send interface packet to set the current interface id like so:

    Code:
    client.getPlayer().getInterfaces().setCurrent(id, -1);
    And when you send interfaces that also display an interact-able inventory:
    Code:
    client.getPlayer().getInterfaces().setCurrent(id, inventoryId);
    And this is how you decode the button:
    Code:
    	player.getInterfaces().onButton(player, NetConstants.hexToInt(in.readBytes(2)), in.readShort(StreamBuffer.ValueType.A));
    The final thing you need to do is make the packet size for opcode 185 4 bytes long:
    Code:
    /**
    	 * Lengths for the various packets.
    	 */
    	public static final int PACKET_LENGTHS[] = {
    		0, 0, 0, 1, -1, 0, 0, 0, 0, 0, // 0
    		0, 0, 0, 0, 8, 0, 6, 2, 2, 0, // 10
    		0, 2, 0, 6, 0, 12, 0, 0, 0, 0, // 20
    		0, 0, 0, 0, 0, 8, 4, 0, 0, 2, // 30
    		2, 6, 0, 6, 0, -1, 0, 0, 0, 0, // 40
    		0, 0, 0, 12, 0, 0, 0, 0, 8, 0, // 50
    		0, 8, 0, 0, 0, 0, 0, 0, 0, 0, // 60
    		6, 0, 2, 2, 8, 6, 0, -1, 0, 6, // 70
    		0, 0, 0, 0, 0, 1, 4, 6, 0, 0, // 80
    		0, 0, 0, 0, 0, 3, 0, 0, -1, 0, // 90
    		0, 13, 0, -1, 0, 0, 0, 0, 0, 0,// 100
    		0, 0, 0, 0, 0, 0, 0, 6, 0, 0, // 110
    		1, 0, 6, 0, 0, 0, -1, 0, 2, 6, // 120
    		0, 4, 6, 8, 0, 6, 0, 0, 0, 2, // 130
    		0, 0, 0, 0, 0, 6, 0, 0, 0, 0, // 140
    		0, 0, 1, 2, 0, 2, 6, 0, 0, 0, // 150
    		0, 0, 0, 0, -1, -1, 0, 0, 0, 0,// 160
    		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170
    		0, 8, 0, 3, 0, 4, 0, 0, 8, 1, // 180
    		0, 0, 12, 0, 0, 0, 0, 0, 0, 0, // 190
    		2, 0, 0, 0, 0, 0, 0, 0, 4, 0, // 200
    		4, 0, 0, 0, 7, 8, 0, 0, 10, 0, // 210
    		0, 0, 0, 0, 0, 0, -1, 0, 6, 0, // 220
    		1, 0, 0, 0, 6, 0, 6, 8, 1, 0, // 230
    		0, 4, 0, 0, 0, 0, -1, 0, -1, 4,// 240
    		0, 0, 6, 6, 0, 0, 0 // 250
    	};
    Client sided

    replace the button sending packets (should be 2) with this:
    Code:
    clientOutputStream.createFrame(185);
    clientOutputStream.writeWord(k);
    clientOutputStream.method432(RSInterface.interfaceCache[k].parentID);
    And finally enjoy. I hope someone actually uses this.
    Reply With Quote  
     

  2. Thankful users:


  3. #2  
    Donator


    Join Date
    Jul 2011
    Posts
    921
    Thanks given
    199
    Thanks received
    178
    Rep Power
    189
    Not bad, gj.
    Reply With Quote  
     

  4. #3  
    Theory Wins?
    Greyfield's Avatar
    Join Date
    Nov 2008
    Age
    32
    Posts
    1,585
    Thanks given
    61
    Thanks received
    265
    Rep Power
    310
    Great work on this. Innovative too.



    Reply With Quote  
     

  5. Thankful user:


  6. #4  
    Registered Member
    Join Date
    Nov 2012
    Posts
    22
    Thanks given
    7
    Thanks received
    0
    Rep Power
    11
    Convert it to PI
    then i might use it..
    Reply With Quote  
     

  7. #5  
    Endeavor

    Mikey`'s Avatar
    Join Date
    Dec 2007
    Posts
    4,434
    Thanks given
    715
    Thanks received
    1,435
    Rep Power
    1202
    Quote Originally Posted by aeriungames View Post
    Convert it to PI
    then i might use it..
    Yeah, I'll get right on that
    Reply With Quote  
     

  8. Thankful user:


  9. #6  
    Community Veteran

    mige5's Avatar
    Join Date
    Aug 2008
    Posts
    5,528
    Thanks given
    573
    Thanks received
    1,410
    Rep Power
    2114
    u know u could load the interface data server-sided and check the parentid?? - if u do it client-sided some1 could just edit the info being sent.
    Number of page #1 releases with most views & posts: (Updated: 2023)
    RS2 server section: 1
    RS2 client section: 2
    Reply With Quote  
     

  10. Thankful users:


  11. #7  
    Registered Member

    Join Date
    Feb 2012
    Posts
    901
    Thanks given
    96
    Thanks received
    480
    Rep Power
    654
    Cache definitions of interfaces contain the entire parent > child hierarchy, no need to send information that is already in the server's possession (if you load those definitions, that is).
    Chris Fletcher
    Economist & Hobbyist Developer
    Reply With Quote  
     

  12. #8  
    Endeavor

    Mikey`'s Avatar
    Join Date
    Dec 2007
    Posts
    4,434
    Thanks given
    715
    Thanks received
    1,435
    Rep Power
    1202
    Quote Originally Posted by Chris Fletcher View Post
    Cache definitions of interfaces contain the entire parent > child hierarchy, no need to send information that is already in the server's possession (if you load those definitions, that is).
    Quote Originally Posted by mige5 View Post
    u know u could load the interface data server-sided and check the parentid?? - if u do it client-sided some1 could just edit the info being sent.
    You'd still have to do something similar to this to verify actions even with cache loading. But I do agree you need to go further to full-proof this, which is what I mentioned in the documentation.
    Reply With Quote  
     

  13. #9  
    Registered Member

    Join Date
    Feb 2012
    Posts
    901
    Thanks given
    96
    Thanks received
    480
    Rep Power
    654
    Quote Originally Posted by Mikey` View Post
    You'd still have to do something similar to this to verify actions even with cache loading. But I do agree you need to go further to full-proof this, which is what I mentioned in the documentation.
    Actually, it doesn't take much (I understand your point though). Using the parent id that is loaded from the cache, you can simply check whether or not the player currently has that interface opened. Remember that everything has its unique interface id, including buttons, inventories, etcetera. Nearly all of them have a parent id that is directly linked to an "openable" interface (e.g. the buttons within the bank window have the id of the bank window itself as their parent:

    Code:
    InterfaceDefinition def = InterfaceDefinition.forId(event.getInterfaceId());
    if (!player.getInterfaceSet().isOpened(def.getParentId()) {
        ctx.breakHandlerChain();
        return;
    }
    That's a simple outline of how it can be done (Apollo).
    Chris Fletcher
    Economist & Hobbyist Developer
    Reply With Quote  
     

  14. #10  
    Endeavor

    Mikey`'s Avatar
    Join Date
    Dec 2007
    Posts
    4,434
    Thanks given
    715
    Thanks received
    1,435
    Rep Power
    1202
    Quote Originally Posted by Chris Fletcher View Post
    Actually, it doesn't take much (I understand your point though). Using the parent id that is loaded from the cache, you can simply check whether or not the player currently has that interface opened. Remember that everything has its unique interface id, including buttons, inventories, etcetera. Nearly all of them have a parent id that is directly linked to an "openable" interface (e.g. the buttons within the bank window have the id of the bank window itself as their parent:

    Code:
    InterfaceDefinition def = InterfaceDefinition.forId(event.getInterfaceId());
    if (!player.getInterfaceSet().isOpened(def.getParentId()) {
        ctx.breakHandlerChain();
        return;
    }
    That's a simple outline of how it can be done (Apollo).
    I implemented a system like that for my server a few days ago. The only problem I ran into was custom interfaces, since most idiots just put the parent id as the id of whatever they're currently building (buttons, sprites, etc). But I did get it working for every action and it should prevent cheating on interfaces entirely (when I fix the parent IDs for custom interfaces).
    Reply With Quote  
     

Page 1 of 2 12 LastLast

Thread Information
Users Browsing this Thread

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


User Tag List

Similar Threads

  1. Replies: 1
    Last Post: 06-07-2011, 09:43 PM
  2. Replies: 6
    Last Post: 05-20-2011, 05:17 AM
  3. Alch with a staff Id and Gfx
    By Sir Zap in forum Configuration
    Replies: 12
    Last Post: 04-02-2011, 12:12 AM
  4. Messed around with the second region..and.
    By solcrystal in forum Help
    Replies: 8
    Last Post: 05-11-2010, 03:43 AM
  5. Showing interface IDs and Child IDs with RSBot?
    By Virus X3 in forum RuneScape Underground
    Replies: 3
    Last Post: 05-28-2009, 02:41 AM
Posting Permissions
  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •