Please note that okapi has a memory leak, somewhere. I noticed it only when hooking virtual functions under linux. Until Arkshine decides to fix the module, you can only hope that you don't do something that will cause the crash.
Also treemap will be removed, I remember Arkshine saying that they are not as reliable as we thought at the beginning.
Now, about your question:
To find the function you need it's symbol for linux and a signature of bytes for windows
for most functions. But, BuyTouch function is exported, this means that in windows it has a name, it's not called sub_*****.
So, for this kind of functions a signature is not needed, you can still use a symbol, as for linux.
1.On linux function is easy to find. Open cs.so with IDA and search for it's name.
The right symbol is:
Code:
_ZN8CBuyZone8BuyTouchEP11CBaseEntity
2.For exported functions, we do the same step as for linux on windows. Load mp.dll in IDA.
You will find this symbol:
Code:
?BuyTouch@CBuyZone@@QAEXPAVCBaseEntity@@@Z
If the function was not exported, you could not use the symbol and the signature of bytes was needed.
Just for the sake of it, I'll show you how to make a signature for this function. I don't know from where you got that signature, but it's wrong.
Load mp.dll in IDA(if you didn't already), go to Option -> general and in the right panel, at "Number of opcode bytes" put 10. Go back to IDA View - A, you should see something like this:
Code:
.text:100C0AC0 56 push esi
.text:100C0AC1 8B 74 24 08 mov esi, [esp+4+arg_0]
.text:100C0AC5 57 push edi
.text:100C0AC6 8B F9 mov edi, ecx
.text:100C0AC8 8B 06 mov eax, [esi]
.text:100C0ACA 8B CE mov ecx, esi
.text:100C0ACC FF 90 A0 00 00 00 call dword ptr [eax+0A0h]
.text:100C0AD2 85 C0 test eax, eax
.text:100C0AD4 74 23 jz short loc_100C0AF9
.text:100C0AD6 8B 4F 04 mov ecx, [edi+4]
.text:100C0AD9 8B 81 AC 01 00 00 mov eax, [ecx+1ACh]
.text:100C0ADF 85 C0 test eax, eax
.text:100C0AE1 74 08 jz short loc_100C0AEB
.text:100C0AE3 3B 86 C8 01 00 00 cmp eax, [esi+1C8h]
.text:100C0AE9 75 0E jnz short loc_100C0AF9
What we need are the numbers after text:something. In order to make a signature as reliable as possible, you need to keep only first byte from each line and replace the others with ?
So, for example: 8B 74 24 08 become 8B ? ? ?
Let's do this:
PHP Code:
56 8B ? ? ? 57 8B ? 8B ? 8B
(the lines that have only one byte remains unchanged - for example the first one). I went for a random number of bytes. Let's check if the signature is unique, i.e it points to only one function.
In IDA go to search -> sequence of bytes, paste and search. You'll get something like:
Code:
Address Function Instruction
------- -------- -----------
.text:10025970 sub_10025970 push esi
.text:10033BF0 sub_10033BF0 push esi
.text:100AAEF2 sub_100AAEF0 push esi
.text:100C0AC0 ?BuyTouch@CBuyZone@@QAEXPAVCBaseEntity@@@Z push esi
.text:100C0C10 ?BombTargetTouch@CBombTarget@@QAEXPAVCBaseEntity@@@Z push esi
.text:100C1670 ?GravityTouch@CTriggerGravity@@QAEXPAVCBaseEntity@@@Z push esi
.text:100CDD10 ?DefaultTouch@CBasePlayerItem@@QAEXPAVCBaseEntity@@@Z push esi
.text:100D0892 push esi
.text:100D0A00 ?ArmouryTouch@CArmoury@@QAEXPAVCBaseEntity@@@Z push esi
This means that the signature is not good enough, it points to more functions. We need to add more bytes.
PHP Code:
56 8B ? ? ? 57 8B ? 8B ? 8B ? FF ? ? ? ? ? 85 ? 74 ? 8B ? ? 8B ? ? ? ? ? 85 ? 74
Basically, start with some bytes, then keep adding until the search returns only your function. Now, we need to convert this signature so we can use it with okapi:
Code:
0x56,0x8B,0xDFF,0xDFF,0xDFF,0x57,0x8B,0xDFF,0x8B,0xDFF,0x8B,,0xDFF,0xFF,0xDFF,0xDFF,0xDFF,0xDFF,0xDFF,0x85,0xDFF,0x74,0xDFF,0x8B,0xDFF,0xDFF,0x8B,0xDFF,0xDFF,0xDFF,0xDFF,0xDFF,0x85,0xDFF,0x74
Add 0x in front of each byte and replace any ? with 0xDFF. Add , before each of them.
Now, we found the function, let's create a plugin for hooking it.
PHP Code:
#include <amxmodx>
#include <okapi>
public plugin_init()
{
new const BuyTouchLinuxSymbol [] = "?BuyTouch@CBuyZone@@QAEXPAVCBaseEntity@@@Z"
new const BuyTouchWindowsSymbol[] = "_ZN8CBuyZone8BuyTouchEP11CBaseEntity"
new HandleFuncBuyTouch
if
(
(HandleFuncBuyTouch = okapi_mod_get_symbol_ptr(BuyTouchLinuxSymbol)) ||
(HandleFuncBuyTouch = okapi_mod_get_symbol_ptr(BuyTouchWindowsSymbol))
)
{
okapi_add_hook(okapi_build_method(HandleFuncBuyTouch, arg_void, arg_cbase, arg_cbase), "OnBuyTouch", .post = 1)
}
}
public OnBuyTouch(const entity, const id)
{
client_print(0, print_chat, "Debug = %i %i", entity, id)
}
I'll explain again why I did it like that.
In linux function have names, so we can identify them by a symbol. In windows, very few functions have names, the others are called sub_****. In this case, the BuyTouch is part of the few function, so a signature is not needed, we can do it easily with a symbol, same as for linux.
Now, next thing that you'll see is that I used
okapi_build_method instead of
okapi_build_function. okapi is a bit harder to use than orpheu due to that. okapi_build_function should be used for function with no class(i.e no CSomething::FunctionName, they are called only FunctionName, for example InstallGameRules).
okapi_build_method is used for functions that are part of a class.
Let's look here:
https://github.com/s1lentq/ReGameDLL...gers.cpp#L1748
Code:
void CBuyZone::BuyTouch(CBaseEntity *pOther)
You see that function is part of
CBuyZone class, so we need to use okapi_build_method for it.
The first argument is the address, which we retrieved from the symbol. The second argument is the return value of the function. Since it's "void", we use arg_void. The third argument is the type of the class, since it's CBuyZone and we know a buyzone is an entity, we can safely say it's the same as CBaseEntity, which in okapi is represented by an arg_cbase.
The next parameters for okapi_build_method are the parameters of the function that you need to hook. Look again at the link, the param is
CBaseEntity *pOther, so again arg_cbase.
I said that okapi is harder to use because orpheu would have added internally for you the class param, based on the file that you provide. So the first arg_cbase is not needed while working with orpheu, it does that automatically.
But, again, for the sake of it, let's assume that this function would not have a name, so we have to hook it from a signature.
PHP Code:
#include <amxmodx>
#include <okapi>
public plugin_init()
{
new const BuyTouchLinuxSymbol [] = "?BuyTouch@CBuyZone@@QAEXPAVCBaseEntity@@@Z"
new const BuyTouchWindowsSignature[] = {0x56, 0x8B, 0xDFF, 0xDFF,0xDFF,0x57,0x8B,0xDFF,0x8B,0xDFF,0x8B,0xDFF,0xFF,0xDFF,0xDFF,0xDFF,0xDFF,0xDFF,0x85,0xDFF,0x74,0xDFF,0x8B,0xDFF,0xDFF,0x8B,0xDFF,0xDFF,0xDFF,0xDFF,0xDFF,0x85,0xDFF,0x74 }
new HandleFuncBuyTouch
if
(
(HandleFuncBuyTouch = okapi_mod_get_symbol_ptr(BuyTouchLinuxSymbol)) ||
(HandleFuncBuyTouch = okapi_mod_find_sig(BuyTouchWindowsSignature, sizeof BuyTouchWindowsSignature))
)
{
okapi_add_hook(okapi_build_method(HandleFuncBuyTouch, arg_void, arg_cbase, arg_cbase), "OnBuyTouch", .post = 1)
}
}
public OnBuyTouch(const entity, const id)
{
client_print(0, print_chat, "Debug = %i %i", entity, id)
}
Output is the same, but why making our life harder by creating the signature?
Ask anything that's not clear.
__________________