Guest User

Untitled

a guest
Sep 14th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 3.75 KB | None | 0 0
  1. module hooking.jmphook;
  2.  
  3. import std.c.windows.windows;
  4. import hooking.processmemory;
  5. public import hooking.define;
  6.  
  7. class JmpHook(TResult, TArguments...)
  8. {
  9.    
  10.     alias extern(Windows) TResult function(TArguments) StdCallFunc;
  11.     alias extern(C) TResult function(TArguments) CdeclFunc;
  12.    
  13.     // Fields
  14.     private static __gshared JmpHook[void*] _hooks;
  15.    
  16.     private void* _address;
  17.     private void* _callback;
  18.     private CallingConvention _callingConvention;
  19.     private byte _length;
  20.     private byte[] _newBytes;
  21.     private byte[] _originalBytes;
  22.    
  23.     // Constructors
  24.     public this(void* address, void* callback, CallingConvention callingConvention, byte length = 5)
  25.     {
  26.        
  27.         if (address == null)
  28.             throw new Exception("Address cannot be null");
  29.        
  30.         if (length < 5)
  31.             throw new Exception("Length cannot be less than 5");
  32.        
  33.         _address = address;
  34.         _callback = callback;
  35.         _callingConvention = callingConvention;
  36.         _length = length;
  37.         _newBytes = new byte[_length + 5];
  38.        
  39.         _originalBytes = ProcessMemory.readBytes(address, length);
  40.        
  41.     }
  42.        
  43.     public this(string moduleName, string procedureName, void* callback, CallingConvention callingConvention, byte length = 5)
  44.     {
  45.         this(getModuleProcedureAddress(moduleName, procedureName), callback, callingConvention, length);       
  46.     }
  47.  
  48.     // Public
  49.     @property
  50.     public bool isInstalled()
  51.     {
  52.         JmpHook hook = _hooks.get(_address, null);
  53.         return hook !is null;
  54.     }
  55.    
  56.     @property
  57.     public void* newFunctionAddress()
  58.     {
  59.         return &_newBytes[0];
  60.     }
  61.    
  62.     public TResult invokeOriginal(void* thisPtr, TArguments arguments)
  63.     {
  64.        
  65.         switch (_callingConvention)
  66.         {
  67.            
  68.             case CallingConvention.StdCall:
  69.                 asm { mov ECX, thisPtr; }
  70.                 return (cast(StdCallFunc)&_newBytes[0])(arguments);
  71.  
  72.             case CallingConvention.Cdecl:
  73.                 asm { mov ECX, thisPtr; }
  74.                 return (cast(CdeclFunc)&_newBytes[0])(arguments);
  75.                
  76.             default:
  77.                 throw new Exception("Calling convention not supported");
  78.                    
  79.         }
  80.        
  81.     }
  82.    
  83.     public void install()
  84.     {
  85.        
  86.         if (!isInstalled)
  87.         {
  88.  
  89.             byte* newBytesPtr = &_newBytes[0];
  90.            
  91.             if (_originalBytes[0] == cast(byte)0xE9) // Check if far jump instruction
  92.             {
  93.                
  94.                 uint jumpOffset = *cast(uint*)(_address + 1);
  95.                 void* jumpDestination = cast(void*)(_address + 5) + (jumpOffset);
  96.                
  97.                 ProcessMemory.writeBytes(newBytesPtr, _originalBytes);
  98.                
  99.                 JmpPatch jmpOldHookPatch = JmpPatch(newBytesPtr, jumpDestination);
  100.                 ProcessMemory.write!(JmpPatch)(newBytesPtr, jmpOldHookPatch);
  101.                    
  102.             }
  103.             else if (_originalBytes[0] == cast(byte)0xEB) // Check if short jump instruction
  104.             {
  105.                
  106.                 byte jumpOffset = *cast(byte*)(_address + 1);
  107.                 void* jumpDestination = cast(void*)(_address + 2) + (jumpOffset);
  108.                
  109.                 ProcessMemory.writeBytes(newBytesPtr, _originalBytes);
  110.                
  111.                 JmpPatch jmpOldHookPatch = JmpPatch(newBytesPtr, jumpDestination);
  112.                 ProcessMemory.write!(JmpPatch)(newBytesPtr, jmpOldHookPatch);
  113.                
  114.             }
  115.             else
  116.                 ProcessMemory.writeBytes(newBytesPtr, _originalBytes);
  117.                
  118.             // Write the (jmp hookaddress + hooklength) to the new bytes
  119.             JmpPatch jmpBackPatch = JmpPatch(&_newBytes[_length], _address + _length);
  120.             ProcessMemory.write!(JmpPatch)(&_newBytes[_length], jmpBackPatch);
  121.                
  122.             // Write the jmp patch
  123.             JmpPatch jmpPatch = JmpPatch(_address, _callback);
  124.             ProcessMemory.write!(JmpPatch)(_address, jmpPatch);
  125.            
  126.             if (_length > 5)
  127.             {
  128.                
  129.                 byte[] nops = new byte[_length - 5];
  130.                
  131.                 for (int i = 0; i < _length - 5; i++)
  132.                     nops[i] = cast(byte)0x90;
  133.                
  134.                 ProcessMemory.writeBytes(_address + 5, nops);
  135.                
  136.             }
  137.            
  138.             _hooks[_address] = this;
  139.            
  140.         }
  141.                
  142.     }
  143.    
  144.     public void uninstall()
  145.     {
  146.         if (isInstalled)
  147.         {
  148.             ProcessMemory.writeBytes(_address, _originalBytes);
  149.             _hooks[_address] = null;
  150.         }
  151.     }
  152.    
  153. }
Add Comment
Please, Sign In to add comment