Advertisement
Guest User

Untitled

a guest
Jan 2nd, 2014
1,085
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.18 KB | None | 0 0
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Text;
  4.  
  5. namespace Addon
  6. {
  7.     static class Extensions
  8.     {
  9.         #region Delegates
  10.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  11.         private delegate void CloneBrushModelToScriptModelFuncDelegate(IntPtr scriptModelEntity, IntPtr brushModelEntity);
  12.  
  13.         [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  14.         private delegate int LoadFxFuncDelegate(string fxName);
  15.  
  16.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  17.         private delegate void PlayFxFuncDelegate(int fxNum, ref Vec3 origin, IntPtr forward, IntPtr up);
  18.  
  19.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  20.         private delegate void SvLinkEntityDelegate(IntPtr entityAddress);
  21.         #endregion
  22.  
  23.         #region Stub
  24.         [DllImport("kernel32.dll", SetLastError = true)]
  25.         static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
  26.  
  27.         private const uint MEM_COMMIT = 0x1000;
  28.         private const uint MEM_RESERVE = 0x2000;
  29.         private const uint PAGE_EXECUTE_READWRITE = 0x40;
  30.  
  31.         private static readonly byte[] GetEspValueStub = new byte[]
  32.         {
  33.             0x8B, 0x04, 0x24, // mov eax, [esp]
  34.             0xC3 // retn
  35.         };
  36.  
  37.         private static readonly byte[] CloneBrushModelToScriptModelFuncStub = new byte[]
  38.         {
  39.             0x55, // push ebp
  40.             0x8B, 0xEC, // mov ebp, esp
  41.             0x53, // push ebx
  42.             0x56, // push esi
  43.             0x57, // push edi
  44.             0x60, // pushad
  45.             0x8B, 0x75, 0x08, // mov esi, [ebp+8]
  46.             0x8B, 0x45, 0x0C, // mov eax, [ebp+C]
  47.             0x8B, 0xF8, // mov edi, eax
  48.             0xE8, 0x00, 0x00, 0x00, 0x00, // call <relative distance>
  49.             0x83, 0xC0, 0x0E, // add eax, 0xE
  50.             0x50, // push eax
  51.             0x8B, 0xC7, // mov eax, edi
  52.             0x56, // push esi
  53.             0x57, // push edi
  54.             0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp [address containing value]
  55.             0x61, // popad
  56.             0x5F, // pop edi
  57.             0x5E, // pop esi
  58.             0x5B, // pop ebx
  59.             0x5D, // pop ebp
  60.             0xC3 // retn
  61.         };
  62.  
  63.         private static readonly byte[] LoadFxFuncStub = new byte[]
  64.         {
  65.             0x55, // push ebp
  66.             0x8B, 0xEC, // mov ebp, esp
  67.             0x51, // push ecx
  68.             0x57, // push edi
  69.             0xC7, 0x45, 0xFC, 0x80, 0x42, 0x4B, 0x00, // mov dword ptr [ebp-8], 4B4280
  70.             0x8B, 0x7D, 0x08, // mov edi, [ebp+8]
  71.             0xFF, 0x55, 0xFC, // call [ebp-4]
  72.             0x5F, // pop edi
  73.             0x8B, 0xE5, // mov esp, ebp
  74.             0x5D, // pop ebp
  75.             0xC3 // retn
  76.         };
  77.  
  78.         private static readonly byte[] PlayFxFuncStub = new byte[]
  79.         {
  80.             0x55, // push ebp
  81.             0x8B, 0xEC, // mov ebp, esp
  82.             0x51, // push ecx
  83.             0xC7, 0x45, 0xFC, 0xB0, 0x0B, 0x4A, 0x00, // mov dword ptr [ebp-4], 4A0BB0
  84.             0x8B, 0x45, 0x10, // mov eax, [ebp+10]
  85.             0x8B, 0x4D, 0x08, // mov ecx, [ebp+8]
  86.             0xFF, 0x75, 0x14, // push [ebp+14]
  87.             0xFF, 0x75, 0x0C, // push [ebp+C]
  88.             0xFF, 0x55, 0xFC, // call [ebp-4]
  89.             0x83, 0xC4, 0x08, // add esp, 8
  90.             0x8B, 0xE5, // mov esp, ebp
  91.             0x5D, // pop ebp
  92.             0xC3 // retn
  93.         };
  94.  
  95.         private static readonly byte[] SvLinkEntityFuncStub = new byte[]
  96.         {
  97.             0x55, // push ebp
  98.             0x8B, 0xEC, // mov ebp, esp
  99.             0x56, // push esi
  100.             0x8B, 0x75, 0x08, // mov esi, [ebp+8]
  101.             0xC7, 0x45, 0xFC, 0x30, 0x38, 0x50, 0x00, // mov dword ptr [ebp-4], 503830
  102.             0xFF, 0x55, 0xFC, // call [ebp-4]
  103.             0x5E, // pop esi
  104.             0x8B, 0xE5, // mov esp, ebp
  105.             0x5D, // pop ebp
  106.             0xC3 // retn
  107.         };
  108.         #endregion
  109.  
  110.         [StructLayout(LayoutKind.Sequential)]
  111.         struct Vec3
  112.         {
  113.             public float X;
  114.             public float Y;
  115.             public float Z;
  116.  
  117.             public static implicit operator Vec3(Vector vector)
  118.             {
  119.                 return new Vec3 { X = vector.X, Y = vector.Y, Z = vector.Z };
  120.             }
  121.  
  122.             public static implicit operator Vector(Vec3 vector)
  123.             {
  124.                 return new Vector(vector.X, vector.Y, vector.Z);
  125.             }
  126.         }
  127.  
  128.         private static IntPtr _cloneBrushModelToScriptModelFuncAddress = IntPtr.Zero;
  129.         private static IntPtr _loadFxFuncAddress = IntPtr.Zero;
  130.         private static IntPtr _playFxFuncAddress = IntPtr.Zero;
  131.         private static IntPtr _getEspValueAddress = IntPtr.Zero;
  132.         private static IntPtr _svLinkEntityAddress = IntPtr.Zero;
  133.         private static string _lastMapName = string.Empty;
  134.         private static int _lastAirdropCrateCollisionId = -1;
  135.  
  136.         private static CloneBrushModelToScriptModelFuncDelegate _cloneBrushModelToScriptModelFunc;
  137.         private static LoadFxFuncDelegate _loadFxFunc;
  138.         private static PlayFxFuncDelegate _playFxFunc;
  139.         private static SvLinkEntityDelegate _svLinkEntityFunc;
  140.  
  141.         private static readonly IntPtr EntityAddress = (IntPtr)0x01918900;
  142.         private static readonly IntPtr JmpDestination = (IntPtr)0x4AFEC8;
  143.         private static readonly IntPtr D3DBspEntsPointer = (IntPtr)0x17A1C54;
  144.         private static readonly IntPtr MapNameDvarPointer = (IntPtr)0x57877B8;
  145.         private static readonly IntPtr ScriptFailuireByteCheckAddress = (IntPtr)0x1CD5724;
  146.  
  147.         private static IntPtr GetEntityFromNum(int entityNum)
  148.         {
  149.             return (IntPtr)(EntityAddress.ToInt32() + entityNum * 0x274);
  150.         }
  151.  
  152.         public static int SetContents(Entity entity, int contents)
  153.         {
  154.             var entityAddress = GetEntityFromNum(entity.EntityNum);
  155.             var oldContents = Marshal.ReadInt32(entityAddress, 0x11C);
  156.             Marshal.WriteInt32(entityAddress, 0x11C, contents);
  157.  
  158.             if (_svLinkEntityAddress == IntPtr.Zero)
  159.             {
  160.                 _svLinkEntityAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)SvLinkEntityFuncStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  161.                 if (_svLinkEntityAddress == IntPtr.Zero)
  162.                     return oldContents;
  163.                 Marshal.Copy(SvLinkEntityFuncStub, 0, _svLinkEntityAddress, SvLinkEntityFuncStub.Length);
  164.                 _svLinkEntityFunc = (SvLinkEntityDelegate)Marshal.GetDelegateForFunctionPointer(_svLinkEntityAddress, typeof(SvLinkEntityDelegate));
  165.             }
  166.  
  167.             _svLinkEntityFunc(entityAddress);
  168.             return oldContents;
  169.         }
  170.  
  171.         public static void Show(Entity entity)
  172.         {
  173.             IntPtr entityAddress = GetEntityFromNum(entity.EntityNum);
  174.             Marshal.WriteInt32(entityAddress, 0x8, Marshal.ReadInt32(entityAddress, 0x8) & ~0x20);
  175.             Marshal.WriteInt32(entityAddress, 0xFC, 0);
  176.         }
  177.  
  178.         public static void Hide(Entity entity)
  179.         {
  180.             IntPtr entityAddress = GetEntityFromNum(entity.EntityNum);
  181.             Marshal.WriteInt32(entityAddress, 0x8, Marshal.ReadInt32(entityAddress, 0x8) | 0x20);
  182.             Marshal.WriteInt32(entityAddress, 0xFC, -1);
  183.         }
  184.  
  185.         public static Vector GetAngles(ServerClient client)
  186.         {
  187.             return GetAngles(client.ClientNum);
  188.         }
  189.  
  190.         public static Vector GetAngles(Entity entity)
  191.         {
  192.             return GetAngles(entity.EntityNum);
  193.         }
  194.  
  195.         private static Vector GetAngles(int entityNum)
  196.         {
  197.             int entityAddress = GetEntityFromNum(entityNum).ToInt32();
  198.             return (Vec3)Marshal.PtrToStructure((IntPtr)(entityAddress + 0x3C), typeof(Vec3));
  199.         }
  200.  
  201.         public static void SetAngles(ServerClient client, Vector angles)
  202.         {
  203.             SetAngles(client.ClientNum, angles);
  204.         }
  205.  
  206.         public static void SetAngles(Entity entity, Vector angles)
  207.         {
  208.             SetAngles(entity.EntityNum, angles);
  209.         }
  210.  
  211.         private static void SetAngles(int entityNum, Vector angles)
  212.         {
  213.             int entityAddress = GetEntityFromNum(entityNum).ToInt32();
  214.  
  215.             var angle = new Vec3 { X = angles.X, Y = angles.Y, Z = angles.Z };
  216.             Marshal.StructureToPtr(angle, (IntPtr)(entityAddress + 0x144), false);
  217.             Marshal.StructureToPtr(angle, (IntPtr)(entityAddress + 0x3C), false);
  218.         }
  219.  
  220.         public static int LoadFX(string fxName)
  221.         {
  222.             // Allocate the stub/function.
  223.             if(_loadFxFuncAddress == IntPtr.Zero)
  224.             {
  225.                 _loadFxFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)LoadFxFuncStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  226.                 if (_loadFxFuncAddress == IntPtr.Zero)
  227.                     return 0;
  228.                 Marshal.Copy(LoadFxFuncStub, 0, _loadFxFuncAddress, LoadFxFuncStub.Length);
  229.                 _loadFxFunc = (LoadFxFuncDelegate)Marshal.GetDelegateForFunctionPointer(_loadFxFuncAddress, typeof(LoadFxFuncDelegate));
  230.             }
  231.  
  232.             // Save and override a byte value to bypass longjmp in-case of failiure.
  233.             byte value = Marshal.ReadByte(ScriptFailuireByteCheckAddress);
  234.             Marshal.WriteByte(ScriptFailuireByteCheckAddress, 1);
  235.            
  236.             // Call the LoadFX stub (which calls G_EffectIndex)
  237.             int result = _loadFxFunc(fxName);
  238.  
  239.             // Restore the byte value.
  240.             Marshal.WriteByte(ScriptFailuireByteCheckAddress, value);
  241.  
  242.             // Return effect ID.
  243.             return result;
  244.         }
  245.  
  246.         public static void PlayFX(int effectId, Vector origin, Vector forward = null, Vector up = null)
  247.         {
  248.             // Allocate the stub/function.
  249.             if(_playFxFuncAddress == IntPtr.Zero)
  250.             {
  251.                 _playFxFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)PlayFxFuncStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  252.                 if(_playFxFuncAddress == IntPtr.Zero)
  253.                     return;
  254.                 Marshal.Copy(PlayFxFuncStub, 0, _playFxFuncAddress, PlayFxFuncStub.Length);
  255.                 _playFxFunc = (PlayFxFuncDelegate)Marshal.GetDelegateForFunctionPointer(_playFxFuncAddress, typeof(PlayFxFuncDelegate));
  256.             }
  257.  
  258.             // Since forward and up are optional, set them to NULL if they are not used.
  259.             IntPtr forwardPtr = IntPtr.Zero, upPtr = IntPtr.Zero;
  260.  
  261.             // Convert the forward/up vector to a pointer.
  262.             if (forward != null) forwardPtr = GetPtrFromObject(forward);
  263.             if (up != null) upPtr = GetPtrFromObject(up);
  264.  
  265.             // Call the function.
  266.             var vec3 = (Vec3) origin;
  267.             _playFxFunc(effectId, ref vec3, forwardPtr, upPtr);
  268.  
  269.             // Free the memory if required.
  270.             if(forwardPtr != IntPtr.Zero) Marshal.FreeHGlobal(forwardPtr);
  271.             if(upPtr != IntPtr.Zero) Marshal.FreeHGlobal(upPtr);
  272.         }
  273.  
  274.         private static IntPtr GetPtrFromObject(object obj)
  275.         {
  276.             int size = Marshal.SizeOf(obj);
  277.             IntPtr ptr = Marshal.AllocHGlobal(size);
  278.             Marshal.StructureToPtr(obj, ptr, true);
  279.             return ptr;
  280.         }
  281.  
  282.         public static int FindAirdropCrateCollisionId()
  283.         {
  284.             try
  285.             {
  286.                 IntPtr mapNameDvarAddress = Marshal.ReadIntPtr(MapNameDvarPointer);
  287.                 if (mapNameDvarAddress == IntPtr.Zero)
  288.                     return -1;
  289.  
  290.                 string currentMap = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(mapNameDvarAddress, 0xC));
  291.                 if (currentMap == _lastMapName)
  292.                     return _lastAirdropCrateCollisionId;
  293.  
  294.                 IntPtr d3dBspEntsAddress = Marshal.ReadIntPtr(D3DBspEntsPointer);
  295.                 if (d3dBspEntsAddress == IntPtr.Zero)
  296.                     return -1;
  297.  
  298.                 IntPtr airdropCrateTargetName = FindStringPattern(d3dBspEntsAddress, Encoding.ASCII.GetBytes("1673 \"care_package\""));
  299.                 IntPtr startEntEntry = airdropCrateTargetName;
  300.  
  301.                 while (Marshal.ReadByte(startEntEntry) != '{')
  302.                     startEntEntry = (IntPtr)(startEntEntry.ToInt32() - 1);
  303.  
  304.                 var targetAddress = (IntPtr)(FindStringPattern(startEntEntry, Encoding.ASCII.GetBytes("1672 \"")).ToInt32() + 7);
  305.                 var endTargetNameAddress = FindStringPattern(targetAddress, Encoding.ASCII.GetBytes("\""));
  306.                 string target = Marshal.PtrToStringAnsi(targetAddress, endTargetNameAddress.ToInt32() - targetAddress.ToInt32() + 1);
  307.  
  308.                 IntPtr airdropCrateCollisionTargetName = FindStringPattern(d3dBspEntsAddress, Encoding.ASCII.GetBytes("1673 \"" + target + "\""));
  309.                 startEntEntry = airdropCrateCollisionTargetName;
  310.  
  311.                 while (Marshal.ReadByte(startEntEntry) != '{')
  312.                     startEntEntry = (IntPtr)(startEntEntry.ToInt32() - 1);
  313.  
  314.                 var airdropCrateCollisionOrigin = (IntPtr)(FindStringPattern(startEntEntry, Encoding.ASCII.GetBytes("1669 \"")).ToInt32() + 7);
  315.                 var endOriginAddress = FindStringPattern(airdropCrateCollisionOrigin, Encoding.ASCII.GetBytes("\""));
  316.  
  317.                 string originValue = Marshal.PtrToStringAnsi(airdropCrateCollisionOrigin, endOriginAddress.ToInt32() - airdropCrateCollisionOrigin.ToInt32() + 1);
  318.                 string[] origin = originValue.Split(' ');
  319.  
  320.                 float x = float.Parse(origin[0]);
  321.                 float y = float.Parse(origin[1]);
  322.                 float z = float.Parse(origin[2]);
  323.  
  324.                 for (int i = 18; i < 2047; i++)
  325.                 {
  326.                     var currentOrigin = (Vec3)Marshal.PtrToStructure((IntPtr)(GetEntityFromNum(i).ToInt32() + 0x18), typeof(Vec3));
  327.                     if (currentOrigin.X != x || currentOrigin.Y != y || currentOrigin.Z != z)
  328.                         continue;
  329.                     _lastAirdropCrateCollisionId = i;
  330.                     _lastMapName = currentMap;
  331.                     return i;
  332.                 }
  333.  
  334.                 return -1;
  335.             }
  336.             catch
  337.             {
  338.                 return -1;
  339.             }
  340.         }
  341.  
  342.         private static IntPtr FindStringPattern(IntPtr startAddress, byte[] value)
  343.         {
  344.             int offset = 0, matchIndex = 0;
  345.             byte read;
  346.             while ((read = Marshal.ReadByte(startAddress, offset)) != 0)
  347.             {
  348.                 if (value[matchIndex++] == read)
  349.                 {
  350.                     if (matchIndex == value.Length)
  351.                         return (IntPtr) (startAddress.ToInt32() + offset - value.Length);
  352.                 }
  353.                 else
  354.                 {
  355.                     matchIndex = 0;
  356.                 }
  357.                 offset++;
  358.             }
  359.             return IntPtr.Zero;
  360.         }
  361.  
  362.         public static void CloneBrushModelToScriptModel(Entity scriptModel, int brushModelEntityId)
  363.         {
  364.             if(_cloneBrushModelToScriptModelFuncAddress == IntPtr.Zero)
  365.             {
  366.                 // Allocate memory for the stubs/functions.
  367.                 _cloneBrushModelToScriptModelFuncAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)CloneBrushModelToScriptModelFuncStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  368.                 _getEspValueAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)GetEspValueStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  369.                
  370.                 if(_cloneBrushModelToScriptModelFuncAddress == IntPtr.Zero || _getEspValueAddress == IntPtr.Zero)
  371.                     return;
  372.  
  373.                 // Allocate memory for a integer holding the jmp destination address.
  374.                 IntPtr jmpDestinationHolder = Marshal.AllocHGlobal(4);
  375.                 Marshal.Copy(BitConverter.GetBytes(JmpDestination.ToInt32()), 0, jmpDestinationHolder, 4);
  376.  
  377.                 // Fix the stub with the address of the GetEspValue stub that we just allocated since it's a relative call.
  378.                 Array.Copy(BitConverter.GetBytes(_getEspValueAddress.ToInt32() - _cloneBrushModelToScriptModelFuncAddress.ToInt32() - 20), 0, CloneBrushModelToScriptModelFuncStub, 16, 4);
  379.                
  380.                 // Do the same for the jmp destination.
  381.                 Array.Copy(BitConverter.GetBytes(jmpDestinationHolder.ToInt32()), 0, CloneBrushModelToScriptModelFuncStub, 30, 4);
  382.                
  383.                 // Write the bytes for stubs/functions to the memory we allocated earlier on.
  384.                 Marshal.Copy(CloneBrushModelToScriptModelFuncStub, 0, _cloneBrushModelToScriptModelFuncAddress, CloneBrushModelToScriptModelFuncStub.Length);
  385.                 Marshal.Copy(GetEspValueStub, 0, _getEspValueAddress, GetEspValueStub.Length);
  386.  
  387.                 // Produce a delegate to invoke/call.
  388.                 _cloneBrushModelToScriptModelFunc = (CloneBrushModelToScriptModelFuncDelegate)Marshal.GetDelegateForFunctionPointer(_cloneBrushModelToScriptModelFuncAddress, typeof(CloneBrushModelToScriptModelFuncDelegate));
  389.             }
  390.  
  391.             _cloneBrushModelToScriptModelFunc(GetEntityFromNum(scriptModel.EntityNum), GetEntityFromNum(brushModelEntityId));
  392.         }
  393.     }
  394. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement