Advertisement
Guest User

Untitled

a guest
Oct 27th, 2013
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 8.84 KB | None | 0 0
  1. module ScriptHooks;
  2.  
  3. private import ScriptClasses;
  4. private import IndentedStreamWriter;
  5. private import std.c.stdlib;
  6.  
  7. alias HookType function(void* obj, void* result, ubyte* args) HookFunction;
  8. alias extern(Windows) void function(ScriptStackFrame* stack, void* result, ScriptFunction func) CleanupStack;
  9. // These are __thiscall, but, as D doesn't support __thiscall, they are declared
  10. // as __cdecl, and an assembly stub is used to pass the this argument in ECX,
  11. // and push the arguments in right to left order.
  12. alias extern(C++) void function(ScriptStackFrame* stack, void* result) NativeFunction;
  13. alias extern(C++) void function(ScriptStackFrame* stack, void* result, ScriptFunction func) CallFunction;
  14.  
  15. public struct ScriptStackFrame
  16. {
  17. private:
  18.     byte __padding__[0x10];
  19.  
  20.     ScriptStruct* mNode;
  21.     ScriptObject* mObject;
  22.     ubyte* mCode;
  23.     ubyte* mLocals;
  24.  
  25.     ScriptStackFrame* mPreviousFrame;
  26.  
  27. public:
  28.     @property
  29.     {
  30.         auto ref ScriptStruct* Node() { return mNode; }
  31.         auto ref ScriptObject* ParentObject() { return mObject; }
  32.         auto ref ubyte* Code() { return mCode; }
  33.         auto ref ubyte* Locals() { return mLocals; }
  34.         auto ref ScriptStackFrame* PreviousFrame() { return mPreviousFrame; }
  35.     }
  36. }
  37.  
  38. public enum HookType
  39. {
  40.     Continue,
  41.     Block,
  42. }
  43.  
  44. public struct HookInfo
  45. {
  46. private:
  47.     HookFunction mFunctionHook;
  48.     ScriptFunction mHookTarget;
  49.     NativeFunction mOriginalFunction;
  50.     int[] mArgumentSizes;
  51.     int mStackSize;
  52.  
  53. public:
  54.     @property
  55.     {
  56.         auto ref HookFunction FunctionHook() { return mFunctionHook; }
  57.         auto ref ScriptFunction HookTarget() { return mHookTarget; }
  58.         auto ref NativeFunction OriginalFunction() { return mOriginalFunction; }
  59.         auto ref int[] ArgumentSizes() { return mArgumentSizes; }
  60.         auto ref int StackSize() { return mStackSize; }
  61.     }
  62. }
  63. version(D_InlineAsm_X86)
  64. {
  65. private:
  66.     static __gshared HookInfo[] mHookArray;
  67.  
  68.     static __gshared NativeFunction* mNativeArray;
  69.     static __gshared NativeFunction mOriginalVirtualFunction;
  70.     static __gshared CleanupStack mCleanupStack;
  71.     static __gshared CallFunction mCallFunction;
  72.  
  73. public:
  74.     @property
  75.     {
  76.         final static auto ref NativeFunction* NativeArray() { return mNativeArray; }
  77.         final static auto ref CleanupStack CleanupStackPtr() { return mCleanupStack; }
  78.         final static auto ref CallFunction CallFunctionPtr() { return mCallFunction; }
  79.     }
  80.  
  81.     static HookType CallHook(HookFunction func, ScriptObject* obj, int paramSize, void* result, ubyte* funcArgs)
  82.     {
  83.         asm
  84.         {
  85.             naked;
  86.  
  87.             push EBP;
  88.             mov EBP, ESP;
  89.             push EDX;
  90.             push ECX;
  91.  
  92.             mov ECX, funcArgs;
  93.             add ECX, paramSize;
  94.  
  95.             mov EDX, funcArgs;
  96.  
  97.             cmp EDX, ECX;
  98.             je endLoop;
  99.  
  100.     pushLoop:
  101.             push [EDX];
  102.             add EDX, 4;
  103.  
  104.             cmp EDX, ECX;
  105.             jl pushLoop;
  106.  
  107.     endLoop:
  108.             push result;
  109.             push obj;
  110.  
  111.             call func;
  112.             add ESP, 8;
  113.             add ESP, paramSize;
  114.  
  115.             pop ECX;
  116.             pop EDX;
  117.             pop EBP;
  118.  
  119.             ret;
  120.         }
  121.     }
  122.  
  123.     static size_t** GetEBP()
  124.     {
  125.         asm
  126.         {
  127.             naked;
  128.             mov EAX, EBP;
  129.             ret;
  130.         }
  131.     }
  132.  
  133.     static void HookThunk()
  134.     {
  135.         asm
  136.         {
  137.             naked;
  138.  
  139.             push EBP;
  140.             mov EBP, ESP;
  141.  
  142.             push dword ptr [EBP+0xC];
  143.             push dword ptr [EBP+0x8];
  144.             push dword ptr [EBP+0x4];
  145.             push ECX;
  146.             call HookHandler;
  147.             add ESP, 0x10;
  148.  
  149.             pop EBP;
  150.            
  151.             ret 0x8;
  152.         }
  153.     }
  154.  
  155.     export extern(C) static void HookHandler(ScriptObject thisPtr, size_t retAddr, ScriptStackFrame* stack, void* result)
  156.     {
  157.         IndentedStreamWriter wtr = new IndentedStreamWriter("TribesAscendSDK-Debug.txt");
  158.  
  159.         size_t func;
  160.         //size_t funcPtr = cast(size_t)mCallFunction.funcptr;
  161.         //size_t mPtr = cast(size_t)mCallFunction.ptr;
  162.         size_t mmcallfunc = cast(size_t)mCallFunction;
  163.         if (retAddr >= cast(size_t)mCallFunction && retAddr <= cast(size_t)mCallFunction + 0x100)
  164.         {
  165.             //lea ebp, [esp-404] in CallFunction
  166.             func = *cast(size_t*)(**GetEBP() + 0x404 + 0x10); //3rd arg of CallFunction
  167.         }
  168.         else //ProcessEvent
  169.         {
  170.             //OutputLog( "ProcessEvent: 0x%X\n", ret_addr );
  171.             func = *cast(size_t*)(**GetEBP() + 0x8); //1st arg of ProcessEvent
  172.         }
  173.  
  174.         ubyte* origCode = stack.Code;
  175.         for (uint i = 0; i < mHookArray.length; i++)
  176.         {
  177.             if (func == cast(size_t)cast(void*)mHookArray[i].HookTarget)
  178.             {
  179.                 int argOffset = mHookArray[i].StackSize;
  180.                 ubyte* funcArgs = cast(ubyte*)malloc(argOffset);
  181.  
  182.                 for (uint paramNum = 0; *stack.Code != 0x16 && paramNum < mHookArray[i].ArgumentSizes.length; paramNum++) //copy args to buffer, respecting LIFO
  183.                 {
  184.                     argOffset -= mHookArray[i].ArgumentSizes[paramNum];
  185.                    
  186.                     ScriptObject *po = stack.ParentObject;
  187.                     NativeFunction nFunc = mNativeArray[*stack.Code++];
  188.                     ubyte* retLocation = funcArgs + argOffset;
  189.                     asm
  190.                     {
  191.                         mov ECX, po;
  192.                         push retLocation;
  193.                         push stack;
  194.                         call nFunc;
  195.                     }
  196.                     //mNativeArray[*stack.Code++](stack.ParentObject, stack, funcArgs + argOffset);
  197.                 }
  198.  
  199.                 wtr.WriteLine("Got args");
  200.  
  201.                 if (retAddr >= cast(size_t)mCallFunction && retAddr <= cast(size_t)mCallFunction + 0x100)
  202.                 {
  203.                     //OutputLog( "Function: %s\n", hook_array[ i ].hook_target->GetName() );
  204.                     if(CallHook(mHookArray[i].FunctionHook, stack.ParentObject, mHookArray[i].StackSize, result, funcArgs) == HookType.Block)
  205.                     {
  206.                         wtr.WriteLine("Function blocked");
  207.                         mCleanupStack(stack, result, mHookArray[i].HookTarget);
  208.                         wtr.WriteLine("Stack cleaned");
  209.                         free(funcArgs);
  210.                         return;
  211.                     }
  212.                    
  213.                     free(funcArgs);
  214.                     stack.Code = origCode;
  215.                     wtr.WriteLine("Function continued");
  216.                    
  217.                     if(mHookArray[i].OriginalFunction)
  218.                     {
  219.                         mHookArray[i].HookTarget.Function = mHookArray[i].OriginalFunction;
  220.  
  221.                         ScriptFunction ht = mHookArray[i].HookTarget;
  222.                         asm
  223.                         {
  224.                             mov ECX, thisPtr;
  225.                             push ht;
  226.                             push result;
  227.                             push stack;
  228.                             call mCallFunction;
  229.                         }
  230.                         //mCallFunction(thisPtr, stack, result, mHookArray[i].HookTarget);
  231.                         mHookArray[i].HookTarget.Function = &HookThunk;
  232.                     }
  233.                     else
  234.                     {
  235.                         mHookArray[i].HookTarget.FunctionFlags.UnsetFlag(ScriptFunctionFlags.Native);
  236.                        
  237.                         ScriptFunction ht = mHookArray[i].HookTarget;
  238.                         asm
  239.                         {
  240.                             mov ECX, thisPtr;
  241.                             push ht;
  242.                             push result;
  243.                             push stack;
  244.                             call mCallFunction;
  245.                         }
  246.                         //mCallFunction(thisPtr, stack, result, mHookArray[i].HookTarget);
  247.                         mHookArray[i].HookTarget.FunctionFlags.SetFlag(ScriptFunctionFlags.Native);
  248.                     }
  249.                 }
  250.                 else
  251.                 {
  252.                     if(CallHook(mHookArray[i].FunctionHook, stack.ParentObject, mHookArray[i].StackSize, result, funcArgs) == HookType.Block)
  253.                     {
  254.                         free(funcArgs);
  255.                         return;
  256.                     }
  257.                    
  258.                     free(funcArgs);
  259.  
  260.                     void* params = *cast(void**)(*GetEBP() + 0xC);
  261.                    
  262.                     if(mHookArray[i].OriginalFunction)
  263.                     {
  264.                         mHookArray[i].HookTarget.Function = mHookArray[i].OriginalFunction;
  265.                         thisPtr.ProcessEvent(mHookArray[i].HookTarget, params, result);
  266.                         mHookArray[i].HookTarget.Function = &HookThunk;
  267.                     }
  268.                     else
  269.                     {
  270.                         mHookArray[i].HookTarget.FunctionFlags.UnsetFlag(ScriptFunctionFlags.Native);
  271.                         thisPtr.ProcessEvent(mHookArray[i].HookTarget, params, result);
  272.                         mHookArray[i].HookTarget.FunctionFlags.SetFlag(ScriptFunctionFlags.Native);
  273.                     }
  274.                 }
  275.                
  276.                 return;
  277.             }
  278.  
  279.         }
  280.  
  281.         wtr.Close();
  282.     }
  283.  
  284.     static void AddHook(immutable string functionName, void* hook)
  285.     {
  286.         ScriptFunction scriptFunction = ScriptObject.Find!(ScriptFunction)(functionName);
  287.         IndentedStreamWriter wtr = new IndentedStreamWriter("TribesAscendSDK-Error.txt");
  288.  
  289.         if(scriptFunction)
  290.             AddHook(scriptFunction, hook);
  291.         else
  292.             wtr.WriteLine( "Failed to find function %s.", functionName );
  293.     }
  294.  
  295.     static void AddHook(ScriptFunction scriptFunction, void* hook)
  296.     {
  297.         HookInfo newHook;
  298.        
  299.         newHook.FunctionHook = cast(HookFunction)hook;
  300.         newHook.HookTarget = scriptFunction;
  301.        
  302.         newHook.StackSize = 0;
  303.        
  304.         if(scriptFunction.FunctionFlags.HasFlag(ScriptFunctionFlags.Native))
  305.         {
  306.             newHook.OriginalFunction = cast(NativeFunction)scriptFunction.Function;
  307.         }
  308.         else
  309.         {
  310.             newHook.OriginalFunction = null;
  311.         }
  312.  
  313.        
  314.         for(ScriptProperty scriptProperty = cast(ScriptProperty)scriptFunction.Children; scriptProperty; scriptProperty = cast(ScriptProperty)scriptProperty.Next)
  315.         {
  316.             if(scriptProperty.PropertyFlags.HasFlag(ScriptPropertyFlags.Param))
  317.             {
  318.                 //OutputLog( "Arg %s size %i\n", script_property->GetName(), script_property->element_size );
  319.                 newHook.ArgumentSizes ~= scriptProperty.ElementSize;
  320.                 newHook.StackSize += scriptProperty.ElementSize;
  321.             }
  322.         }
  323.        
  324.         newHook.StackSize = ((newHook.StackSize >> 2) + ((newHook.StackSize & 0x03) != 0)) << 2;
  325.        
  326.         mHookArray ~= newHook;
  327.        
  328.         scriptFunction.Function = &HookThunk;
  329.         scriptFunction.FunctionFlags.SetFlag(ScriptFunctionFlags.Native);
  330.  
  331.         //OutputLog( "Hooked function %s (0x%X) (args %i)\n\n", function_name, script_function, new_hook.stack_size );
  332.     }
  333. }
  334. else
  335. {
  336.     static assert(0, "Only x86 is supported!");
  337. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement