Page 1 of 1

Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 6:52 am
by Tetragromaton
Hello guys, im new on sourcepython and I dont want to mess with sourcepawn extensions just to hook one single instruction in the server code, so i need your guys help, how can i hook instruction in server.so file ? I'm already have signature of this code and my objective to do atleast notify for all players that this part of code was executed at the server.
Ok so, this is the signature of the code that i want to hook.

Game:CSGO(server.so file)
Instruction signatue(Signature from Cheat Engine(AOB Pattern) ):39 81 B0 0A 00 00 0F 84 B0
Watch png file so you can understand me better :rolleyes:

Re: Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 11:39 am
by Sam
Do you want to modify instruction `cmp [ecx+0x0AB0], eax`. I'm not a Linux expert but I can say that you can use (for Windows): pywin32 + ctypes (WriteProcessMemory, ReadProcessMemory, and etc)

Re: Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 11:44 am
by Sam
Sam wrote:Do you want to modify instruction `cmp [ecx+0x0AB0], eax`. I'm not a Linux expert but I can say that you can use (for Windows): pywin32 + ctypes (WriteProcessMemory, ReadProcessMemory, and etc)

Code: Select all

import ctypes
import ctypes
.wintypes as wintypes


PROCESS_VM_READ 
= 0x0010
BUF_SIZE 
= 64

kernel32 
= ctypes.windll.kernel32

kernel32
.OpenProcess.restype = wintypes.HANDLE
kernel32
.OpenProcess.argtypes = [
    wintypes.DWORD,
    wintypes.BOOL,
    wintypes.DWORD
]

kernel32.CloseHandle.restype = wintypes.BOOL
kernel32
.CloseHandle.argtypes = [ wintypes.HANDLE ]

kernel32.ReadProcessMemory.restype = wintypes.BOOL
kernel32
.ReadProcessMemory.argtypes = [ 
    wintypes
.HANDLE,
    wintypes.LPCVOID,
    wintypes.LPVOID,
    ctypes.c_size_t,
    ctypes.POINTER(ctypes.c_size_t)
]

pid = int(sys.argv[1])
addr = int(sys.argv[2], 16)

buf = ctypes.create_string_buffer(BUF_SIZE)
read = ctypes.c_size_t()

ph = kernel32.OpenProcess(PROCESS_VM_READ, False, pid)
= kernel32.ReadProcessMemory(ph, addr, ctypes.byref(buf), BUF_SIZE, ctypes.byref(read))
kernel32.CloseHandle(ph)

print(
buf.value

Re: Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 12:28 pm
by Tetragromaton
I need linux...

Re: Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 3:39 pm
by Sam
Tetragromaton wrote:I need linux...

What prevents you from using module `ctypes`?

Re: Hooking instruction by its signature via plugin

Posted: Tue Mar 03, 2020 4:02 pm
by Ayuto
Sam wrote:Do you want to modify instruction `cmp [ecx+0x0AB0], eax`. I'm not a Linux expert but I can say that you can use (for Windows): pywin32 + ctypes (WriteProcessMemory, ReadProcessMemory, and etc)

It's a lot easier to use our memory module. Unfortunately, I'm currently on the phone and in hurry, so i can't provide an example. I will try to do on the weekend.

Re: Hooking instruction by its signature via plugin

Posted: Wed Mar 04, 2020 4:58 pm
by Ayuto
Just noticed in the plugins release forum that you already figured a way to patch bytes. However, here is how I would do it:

Syntax: Select all

def patch_bytes(addr, pbytes):
addr.unprotect(len(pbytes))
for index, byte in enumerate(pbytes):
addr.set_uchar(byte, index)

# Patch the first four bytes of <some_addr> by replacing them with NOP instructions
# <some_addr> is an instance of the memory.Pointer class.
patch_bytes(some_addr, [0x90, 0x90, 0x90, 0x90])

Re: Hooking instruction by its signature via plugin

Posted: Thu Mar 05, 2020 11:08 am
by Tetragromaton
Thanks ! Is there a way to generate signature for instruction for x32 server.so file ? Just pretty annoying to update adress every game update.

Re: Hooking instruction by its signature via plugin

Posted: Thu Mar 05, 2020 5:26 pm
by Ayuto
Sure, you can generate signatures for everything. Good signatures use placeholders for bytes that are likely to change after an update (e. g. references to pointers or offsets). I hope this example might help:

Code: Select all

55                                                              push    ebp
89 E5                                                           mov     ebp, esp
53                                                              push    ebx
83 EC 14                                                        sub     esp, 14h
8B 5D 08                                                        mov     ebx, [ebp+arg_0]

8B 0D 10 85 AC 00                                               mov     ecx, g_pEntityList
; For this line we would write down 8B 0D 2A 2A 2A 2A, because the last four bytes refer
; to g_pEntityList, which is a pointer and easily changes


C7 83 0C 1C 00 00 0B 00 00 00                                   mov     dword ptr [ebx+1C0Ch], 0Bh
; For this we could uses something like this: C7 83 2A 2A 00 00 0B 00 00 00
; The instruction accesses an address by an offset (1C0C), which might also changes after an update.

8B 83 44 1A 00 00                                               mov     eax, [ebx+1A44h]
; Same for this line: 8B 83 2A 2A 00 00

C7 83 10 1C 00 00 FF FF FF FF                                   mov     dword ptr [ebx+1C10h], 0FFFFFFFFh
; Same here: C7 83 2A 2A 00 00 FF FF FF FF

83 F8 FF                                                        cmp     eax, 0FFFFFFFFh
74 15                                                           jz      short loc_54DEF4
89 C2                                                           mov     edx, eax
C1 E8 0C                                                        shr     eax, 0Ch
81 E2 FF 0F 00 00                                               and     edx, 0FFFh
C1 E2 04                                                        shl     edx, 4
01 CA                                                           add     edx, ecx
39 42 08                                                        cmp     [edx+8], eax
74 2C                                                           jz      short loc_54DF20