Black magic time - Lowlevel control over events - answer to protection vault

Discussion in 'Plugin Development' started by RawCode, Apr 14, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    RawCode

    You must know how misc.Unsafe works in order to understand what this post about.
    This is sample, in real cases you shoud inject directly with help of ASM.

    Custom implementation of event with code you want.
    Ever if you going rogue and hack deep, you will need code vessel by hand.

    Code:
    public class BlockPlaceEventEx extends BlockPlaceEvent
    {
    	public BlockPlaceEventEx(Block placedBlock, BlockState replacedBlockState, Block placedAgainst,
    			ItemStack itemInHand, Player thePlayer, boolean canBuild) {
    		super(placedBlock, replacedBlockState, placedAgainst, itemInHand, thePlayer, canBuild);
    	}
    	
    	@Override
    	public void setCancelled(boolean b)
    	{
    		System.out.println(Reflection.getCallerClass());
    //and wont actually cancell event
    	}
    }
    
    Code above will report class name that invoked "setCancelled()", if you need method and linenumber you can extract this data from "stackframe" (not real stackframe).

    Testcase classes A B C

    Code:
    public class RandomClassA implements Listener
    {
    	public RandomClassA()
    	{
    		Bukkit.getPluginManager().registerEvents(this, Loader.INSTANCE);
    	}
    	
    	@EventHandler()
    	public void OnBlockPlaceEvent(BlockPlaceEvent e)
    	{
    		if (Math.random() > 0.5)
    		{
    			e.getPlayer().sendMessage("Cancelled by class A");
    			e.setCancelled(true);
    		}
    	}
    }
    
    If you compare traces of both objects (you will notice structure of object 05 00 00 00 locks(locked to main thread) 00 00 00 00 SO ME ID ID of same size.
    This is memory layout of object, second and third words are class references, changing them changes class of object (OMG THEY KILLED TYPE PROTECTION).
    If you attempt to cast objects of different size you well get random issues over time, i will post sample later (safe only inside offheap memory or if you place multiple objects into same space)
    Code:
    		UnsafeImpl.Object2Trace(e);
    		System.out.println("BODYBREAK");
    		UnsafeImpl.Object2Trace(new BlockPlaceEventEx(null, null, null, null, null, false));
    
    Class C will implement this feature
    Code:
    	@EventHandler(priority = EventPriority.LOWEST)
    	public void OnBlockPlaceEvent(BlockPlaceEvent e)
    	{
    		//this class a bit different, it have lower priority and wont attempt to cancell anything
    		//instead it will alter class of event passed into it
    		int REF = UnsafeImpl.unsafe.getInt(new BlockPlaceEventEx(null, null, null, null, null, false), 8l);
    		UnsafeImpl.unsafe.putInt(e, 8l, REF);
    	}
    
    (8l is version platform dependant, check trace for proper id)
    (REF can be cached or extracted from BlockPlaceEventEx.class)
    Now lets see what we will have...
    Event changed it's class and does not cancell anything and display to console who invoked setCancelled().

    This can be used versus ANY object, including ability to change methods and fields that not possible to change in vanilla implementation.
    Also you can hijack packets and any internal objects with this.
     
    KingFaris11 likes this.
  2. Offline

    KingFaris11

    Don't know what the hell you just wrote, ignored the warning about knowing whatever, just saw the end and was like "*like*".
     
    Garris0n likes this.
  3. Offline

    RawCode

    forgot about repo link at the end
    https://github.com/RawCode/UBT/tree/master/src/rc/ubt

    KingFaris11
    This is sample about casting existing objects from one class to another ignoring some of rules, this can be used to replace methods of existing objects.
    Using this you may replace some method for CraftPlayer or CraftWorld without altering server jar.
     
    KingFaris11 likes this.
  4. Offline

    xTrollxDudex

    RawCode
    Where exactly in the trace can you find "8l"?
     
  5. Offline

    RawCode

    8l is offset to class OOP reference, real offset is 4l but with compressed OOPS top word always zero.

    00 01 02 03
    04 05 06 07
    08 09 0A 0B

    most effective way to understand how it works - compare trace from Long and Integer
     
Thread Status:
Not open for further replies.

Share This Page