Advertisement
Guest User

Untitled

a guest
Jan 3rd, 2014
772
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.37 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using Addon;
  5.  
  6. namespace Addon
  7. {
  8.     static class TestClients
  9.     {
  10.         #region Hooking Functions
  11.         [DllImport("kernel32.dll", SetLastError = true)]
  12.         static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
  13.  
  14.         [DllImport("kernel32.dll", SetLastError = true)]
  15.         static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);
  16.  
  17.         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  18.         static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
  19.  
  20.         private const uint MEM_COMMIT = 0x1000;
  21.         private const uint MEM_RESERVE = 0x2000;
  22.         private const uint PAGE_EXECUTE_READWRITE = 0x40;
  23.  
  24.         private static readonly List<GCHandle> GCHandles = new List<GCHandle>();
  25.  
  26.         private static void PerformJmpHook(IntPtr original, byte[] destinationStub)
  27.         {
  28.             var stubAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) destinationStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  29.             Marshal.Copy(destinationStub, 0, stubAddress, destinationStub.Length);
  30.             PerformJmpHook(original, stubAddress);
  31.         }
  32.  
  33.         private static void PerformJmpHook(IntPtr original, IntPtr destination)
  34.         {
  35.             uint oldProtect;
  36.             VirtualProtect(original, (UIntPtr)5, PAGE_EXECUTE_READWRITE, out oldProtect);
  37.             var hook = new byte[5];
  38.             hook[0] = 0xE9;
  39.             BitConverter.GetBytes((destination.ToInt32() - original.ToInt32()) - 5).CopyTo(hook, 1);
  40.             Marshal.Copy(hook, 0, original, hook.Length);
  41.             VirtualProtect(original, (UIntPtr)5, oldProtect, out oldProtect);
  42.         }
  43.  
  44.         private static IntPtr GetUnmanagedFunctionPointerFromDelegate(Delegate d)
  45.         {
  46.             GCHandles.Add(GCHandle.Alloc(d));
  47.             return Marshal.GetFunctionPointerForDelegate(d);
  48.         }
  49.         #endregion
  50.  
  51.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  52.         private delegate bool SvCheckClientDelegate(IntPtr clientPart);
  53.  
  54.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  55.         private delegate int FuncIntDelegate();
  56.  
  57.         [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
  58.         private delegate void SvCmdTokenizeStringDelegate(string str);
  59.  
  60.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  61.         private delegate void SvDirectConnectDelegate(netaddr_t adr);
  62.  
  63.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  64.         private delegate void SvSendClientGameStateDelegate(IntPtr client);
  65.  
  66.         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  67.         private delegate void SvClientEnterWorldDelegate(IntPtr client, byte[] userCmd);
  68.  
  69.         private static readonly IntPtr SvCheckTimeoutAddress = (IntPtr) 0x4FE8A0;
  70.         private static readonly IntPtr SteamCheckSvAuthAddress = (IntPtr) 0x599D20;
  71.         private static readonly IntPtr ResetReliableCmdAddress = (IntPtr) 0x5029DB;
  72.         private static readonly IntPtr SvMaxClientsDvarPtr = (IntPtr) 0x5787780;
  73.         private static readonly IntPtr ClientAddress = (IntPtr) 0x4A0FE90;
  74.         private static readonly IntPtr GetStatMajorAddress = (IntPtr) 0x4D0560;
  75.         private static readonly IntPtr GetStatMinorAddress = (IntPtr) 0x4D05A0;
  76.         private static readonly IntPtr GetChecksumAddress = (IntPtr) 0x40C8C0;
  77.         private static readonly IntPtr SvDirectConnectAddress = (IntPtr) 0x4F7670;
  78.         private static readonly IntPtr SvCmdArgsAddress = (IntPtr) 0x1B5B7D8;
  79.  
  80.         private static readonly FuncIntDelegate GetStatMajor;
  81.         private static readonly FuncIntDelegate GetStatMinor;
  82.         private static readonly FuncIntDelegate GetChecksum;
  83.         private static readonly SvCmdTokenizeStringDelegate SvCmdTokenizeString;
  84.         private static readonly SvDirectConnectDelegate SvDirectConnect;
  85.         private static readonly SvSendClientGameStateDelegate SvSendClientGameState;
  86.         private static readonly SvClientEnterWorldDelegate SvClientEnterWorld;
  87.  
  88.         private static ushort BotPort;
  89.  
  90.         private static byte[] SvCheckTimeoutHookStub = new byte[]
  91.         {
  92.             0x56, // push esi
  93.             0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <handler>
  94.             0xFF, 0xD0, // call eax
  95.             0x83, 0xC4, 0x04, // add esp, 4
  96.             0x84, 0xC0, // test al, al
  97.             0x68, 0xA7, 0xE8, 0x4F, 0x00, // push 4FE8A7h
  98.             0xC3, // retn
  99.         };
  100.  
  101.         private static byte[] SteamCheckSvAuthHookStub = new byte[]
  102.         {
  103.             0x56, // push esi
  104.             0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <handler>
  105.             0xFF, 0xD0, // call eax
  106.             0x83, 0xC4, 0x04, // add esp, 4
  107.             0x84, 0xC0, // test al, al
  108.             0x75, 0x06, // jnz short continueSteamCheck
  109.             0x68, 0xBC, 0x9D, 0x59, 0x00, // push 599DBCh
  110.             0xC3, // retn
  111.  
  112.             // continueSteamCheck:
  113.             0x68, 0x2D, 0x9D, 0x59, 0x00, // push 599D2Dh
  114.             0xC3, // retn
  115.         };
  116.  
  117.         private static byte[] ResetReliableCmdHookStub = new byte[]
  118.         {
  119.             0x80, 0xBE, 0xC0, 0x52, 0x04, 0x00, 0xFF, // cmp byte ptr [esi+452C0h], 0FFh
  120.             0x75, 0x0C, // jnz short doReturn
  121.             0x8B, 0x86, 0x70, 0x0E, 0x02, 0x00, // mov eax, [esi+20E70h]
  122.             0x89, 0x86, 0x74, 0x0E, 0x02, 0x00, // mov [esi+20E74h], eax
  123.  
  124.             // doReturn:
  125.             0x83, 0x3D, 0x9C, 0x1F, 0x2F, 0x06, 0x00, // cmp dword ptr [62F1F9C], 0
  126.             0x68, 0xE2, 0x29, 0x50, 0x00, // push 5029E2h
  127.             0xC3 // retn
  128.         };
  129.  
  130.         private static byte[] SvCmdTokenizeStringStub = new byte[]
  131.         {
  132.             0x55, // push ebp
  133.             0x8B, 0xEC, // mov ebp, esp
  134.             0x56, // push esi
  135.             0x51, // push ecx
  136.             0xB8, 0x00, 0x02, 0x00, 0x00, // mov eax, 200
  137.             0x2B, 0x05, 0xD0, 0xAF, 0xB4, 0x01, // sub eax, dword ptr [1B4AFD0]
  138.             0x50, // push eax
  139.             0xFF, 0x75, 0x08, // push [ebp+8]
  140.             0xB9, 0xB0, 0x87, 0xB4, 0x01, // mov ecx, 1B487B0
  141.             0xBE, 0xD8, 0xB7, 0xB5, 0x01, // mov esi, 1B5B7D8
  142.             0xB8, 0x00, 0xC1, 0x4C, 0x00, // mov eax, 4CC100
  143.             0xFF, 0xD0, // call eax
  144.             0x83, 0xC4, 0x08, // add esp, 8
  145.             0x59, // pop ecx
  146.             0x5E, // pop esi
  147.             0x5D, // pop ebp
  148.             0xC3 // retn
  149.         };
  150.  
  151.         private static readonly byte[] SvSendClientGameStateStub = new byte[]
  152.         {
  153.             0x55, // push ebp
  154.             0x8B, 0xEC, // mov ebp, esp
  155.             0x51, // push ecx
  156.             0xB9, 0x40, 0x8D, 0x4F, 0x00, // mov ecx, 4F8D40
  157.             0x8B, 0x45, 0x08, // mov eax, [ebp+8]
  158.             0xFF, 0xD1, // call ecx
  159.             0x59, // pop ecx
  160.             0x5D, // pop ebp
  161.             0xC3 // retn
  162.         };
  163.  
  164.         private static readonly byte[] SvClientEnterWorldStub = new byte[]
  165.         {
  166.             0x55, // push ebp
  167.             0x8B, 0xEC, // mov ebp, esp
  168.             0x52, // push edx
  169.             0xB8, 0xC0, 0x8F, 0x4F, 0x00, // mov eax, 4F8FC0
  170.             0xFF, 0x75, 0x08, // push [ebp+8]
  171.             0x8B, 0x55, 0x0C, // mov edx, [ebp+C]
  172.             0xFF, 0xD0, // call eax
  173.             0x83, 0xC4, 0x04, // add esp, 4
  174.             0x5A, // pop edx
  175.             0x5D, // pop ebp
  176.             0xC3 // retn
  177.         };
  178.  
  179.         [StructLayout(LayoutKind.Sequential)]
  180.         struct netaddr_t
  181.         {
  182.             public int type;
  183.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
  184.             public byte[] ip;
  185.             public ushort port;
  186.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
  187.             public byte[] ipx;
  188.         }
  189.  
  190.         static TestClients()
  191.         {
  192.             // Hook required methods.
  193.             var svCheckTimeoutFuncAddress = GetUnmanagedFunctionPointerFromDelegate(
  194.                 new SvCheckClientDelegate(SvCheckTimeoutFunc));
  195.             BitConverter.GetBytes(svCheckTimeoutFuncAddress.ToInt32()).CopyTo(SvCheckTimeoutHookStub, 2);
  196.             PerformJmpHook(SvCheckTimeoutAddress, SvCheckTimeoutHookStub);
  197.  
  198.             var steamCheckSvAuthFuncAddress = GetUnmanagedFunctionPointerFromDelegate(
  199.                 new SvCheckClientDelegate(SteamCheckSvAuthFunc));
  200.             BitConverter.GetBytes(steamCheckSvAuthFuncAddress.ToInt32()).CopyTo(SteamCheckSvAuthHookStub, 2);
  201.             PerformJmpHook(SteamCheckSvAuthAddress, SteamCheckSvAuthHookStub);
  202.  
  203.             PerformJmpHook(ResetReliableCmdAddress, ResetReliableCmdHookStub);
  204.  
  205.             // Prepare function delegates.
  206.             GetStatMajor = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetStatMajorAddress, typeof (FuncIntDelegate));
  207.             GetStatMinor = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetStatMinorAddress, typeof (FuncIntDelegate));
  208.             GetChecksum = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetChecksumAddress, typeof (FuncIntDelegate));
  209.             SvDirectConnect = (SvDirectConnectDelegate) Marshal.GetDelegateForFunctionPointer(SvDirectConnectAddress, typeof (SvDirectConnectDelegate));
  210.  
  211.             var svCmdTokenizeStringAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) SvCmdTokenizeStringStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  212.             Marshal.Copy(SvCmdTokenizeStringStub, 0, svCmdTokenizeStringAddress, SvCmdTokenizeStringStub.Length);
  213.             SvCmdTokenizeString = (SvCmdTokenizeStringDelegate) Marshal.GetDelegateForFunctionPointer(svCmdTokenizeStringAddress, typeof (SvCmdTokenizeStringDelegate));
  214.  
  215.             var svSendClientGameStateAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) SvSendClientGameStateStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  216.             Marshal.Copy(SvSendClientGameStateStub, 0, svSendClientGameStateAddress, SvSendClientGameStateStub.Length);
  217.             SvSendClientGameState = (SvSendClientGameStateDelegate) Marshal.GetDelegateForFunctionPointer(svSendClientGameStateAddress, typeof (SvSendClientGameStateDelegate));
  218.  
  219.             var svClientEnterWorldAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)SvClientEnterWorldStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  220.             Marshal.Copy(SvClientEnterWorldStub, 0, svClientEnterWorldAddress, SvClientEnterWorldStub.Length);
  221.             SvClientEnterWorld = (SvClientEnterWorldDelegate)Marshal.GetDelegateForFunctionPointer(svClientEnterWorldAddress, typeof(SvClientEnterWorldDelegate));
  222.         }
  223.  
  224.         private static bool SvCheckTimeoutFunc(IntPtr clientPart)
  225.         {
  226.             var client = (IntPtr) (clientPart.ToInt32() - 136300);
  227.             return Marshal.ReadInt32(client, -136260) != 2 &&
  228.                    (Marshal.ReadInt32(client) == 1 || Marshal.ReadInt32(client, 283328) != -1);
  229.         }
  230.  
  231.         private static bool SteamCheckSvAuthFunc(IntPtr clientPart)
  232.         {
  233.             var client = (IntPtr) (clientPart.ToInt32() - 283325);
  234.             return Marshal.ReadInt32(client) >= 5 && Marshal.ReadInt32(client, 283328) != -1;
  235.         }
  236.  
  237.         private static IntPtr GetClientFromNum(int clientNum)
  238.         {
  239.             return (IntPtr)(ClientAddress.ToInt32() + clientNum * 0x78690);
  240.         }
  241.  
  242.         private static void SvCmdEndTokenizedString()
  243.         {
  244.             var argsIndex = Marshal.ReadInt32(SvCmdArgsAddress);
  245.  
  246.             var addr = (IntPtr) 0x1B4AFD0;
  247.             var value = Marshal.ReadInt32(addr);
  248.             var arrValue = Marshal.ReadInt32((IntPtr)0x1B5B81C, argsIndex * 4);
  249.             Marshal.WriteInt32(addr, value - arrValue);
  250.  
  251.             addr = (IntPtr) 0x1B4AFD4;
  252.             value = Marshal.ReadInt32(addr);
  253.             arrValue = Marshal.ReadInt32((IntPtr)0x1B4AFB0, argsIndex * 4);
  254.  
  255.             argsIndex--;
  256.             Marshal.WriteInt32(SvCmdArgsAddress, argsIndex);
  257.         }
  258.  
  259.         private static void Memset(IntPtr ptr, int value, int length)
  260.         {
  261.             var b = (byte) value;
  262.             for (int i = 0; i < length; i++)
  263.                 Marshal.WriteByte(ptr, i, b);
  264.         }
  265.  
  266.         public static void ConnectBot(ServerClient client)
  267.         {
  268.             if (!IsBot(client))
  269.                 return;
  270.  
  271.             ConnectBot(GetClientFromNum(client.ClientNum));
  272.         }
  273.  
  274.         private static void ConnectBot(IntPtr clientAddress)
  275.         {
  276.             // Call SV_SendClientGameState
  277.             SvSendClientGameState(clientAddress);
  278.  
  279.             // SV_ClientEnterWorld
  280.             SvClientEnterWorld(clientAddress, new byte[44]);
  281.         }
  282.  
  283.         public static bool IsBot(ServerClient client)
  284.         {
  285.             var clientAddress = GetClientFromNum(client.ClientNum);
  286.             return Marshal.ReadInt32(clientAddress, 283328) == -1;
  287.         }
  288.  
  289.         public static int AddTestClient()
  290.         {
  291.             // Read the sv_maxclients dvar value.
  292.             var maxClients = Marshal.ReadInt32(Marshal.ReadIntPtr(SvMaxClientsDvarPtr), 0xC);
  293.            
  294.             // Look for a free slot.
  295.             int index = 0;
  296.             for (index = 0; index < maxClients; index++)
  297.             {
  298.                 if (Marshal.ReadInt32(GetClientFromNum(index)) == 0)
  299.                     break;
  300.             }
  301.  
  302.             // No slots available.
  303.             if (index == maxClients)
  304.                 return -1;
  305.  
  306.             // Prepare connection string.
  307.             const int protocol = 20601; // as of 1.9.461
  308.             var connectString = string.Format(
  309.                 "connect bot{0} \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\bot{0}\\protocol\\{1}\\checksum\\{2}\\statver\\{3} {4}\\qport\\{5}\"",
  310.                 BotPort, protocol, GetChecksum(),
  311.                 GetStatMajor(), (uint) GetStatMinor(),
  312.                 BotPort + 1);
  313.  
  314.             // Handle client connection.
  315.             var botAdr = new netaddr_t { port = BotPort };
  316.  
  317.             SvCmdTokenizeString(connectString.PadRight(1023, '\0'));
  318.             SvDirectConnect(botAdr);
  319.             SvCmdEndTokenizedString();
  320.  
  321.             BotPort++;
  322.  
  323.             // Get the bot's client number and client address.
  324.             index = 0;
  325.  
  326.             IntPtr botClient = IntPtr.Zero;
  327.             for (index = 0; index < maxClients; index++)
  328.             {
  329.                 if (Marshal.ReadInt32(botClient = GetClientFromNum(index)) == 0)
  330.                     continue;
  331.                 var clientAdr = (netaddr_t) Marshal.PtrToStructure((IntPtr) (botClient.ToInt32() + 40), typeof (netaddr_t));
  332.                 if (clientAdr.type == botAdr.type && clientAdr.port == botAdr.port)
  333.                     break;
  334.             }
  335.  
  336.             // Failed for some reason.
  337.             if (index == maxClients)
  338.                 return -1;
  339.  
  340.             // Set the "bot" flag (actually the lower dword of the steam id)
  341.             Marshal.WriteInt32(botClient, 283328, -1);
  342.  
  343.             // Set stat flags to "already set"
  344.             Marshal.WriteInt16(botClient, 283322, 0x3FF);
  345.             Memset((IntPtr)(botClient.ToInt32() + 269497), 0, 0x2FFC);
  346.             Memset((IntPtr)(botClient.ToInt32() + 281785), 0, 0x600);
  347.  
  348.             // Connect the bots as spectators.
  349.             ConnectBot(botClient);
  350.  
  351.             // Return client num.
  352.             return index;
  353.         }
  354.     }
  355. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement