Friday, 26.05.2017, 10:23
Приветствую Вас Гость
Register | Login | RSS
Jedi Academy Server Security
[ New messages · Users · Forum rules · Search · RSS ]
Page 1 of 11
Forum » JASS » English forum » Question - Hooking a function
Question - Hooking a function
WEAPON_XDate: Monday, 21.05.2012, 08:46 | Message # 1
Group: User
Messages: 12
Reputation: 0
Status: Offline
Hello,

Would it be possible to hook a function?

Lets say for example, the use function for target_relay.

I know that if i have the entity, i can reassign a new think function. by ent->use = newRelayUse.

But my question is in general.

If i got the pointer of the original use function, how can I make it hook at lets say GAME_INIT, so that it always calls my function.

I just want to make my own use function for some of the entities.


Message edited by WEAPON_X - Monday, 21.05.2012, 08:50
 
BufferOverflowDate: Thursday, 24.05.2012, 18:09 | Message # 2
Group: Developer
Messages: 47
Reputation: 0
Status: Offline
Yes, you can. But it's not recommended. Use this only if you cannot do the same using only JAZZ. Every JAZZ plugin is loaded inside of JKA memory space, so it's easy to hook functions on both x64 and x86. But it is code modifying, the thing that players don't like because "Modified DLL code will change saber damage". I'm sure that this kind of modification couldn't change saber damage, but anyway I'm never using this method to replace mod functs, JAZZ features is enough to protect servers.

Code
//This structure is needed for replacing
#pragma pack (push,1)
struct jmp_far{
BYTE instr_push;    //assembler push instruction
DWORD arg;  //argument - pointer to your function
BYTE instr_ret;  //assembler ret instruction
};
#pragma pack (pop)

//needed variables
BYTE oldFunc[6]; //here the original function bytes will be stored
DWORD adr_Func;//address of original function to replace
jmp_far jump;


After that, you can hook this function in JASS_Attach. Remember, that you always must restore original function in JASS_Detach.
Code
C_DLLEXPORT int JASS_Attach(eng_syscall_t engfunc, mod_vmMain_t modfunc, pluginres_t* presult, pluginfuncs_t* pluginfuncs, int iscmd) {
JASS_SAVE_VARS();
jump.instr_push = 0x68; //push
jump.arg = (DWORD)&Hook_YourFunction); //a pointer to your funct
jump.instr_ret = 0xC3; //ret
//storing original six bytes
ReadProcessMemory(GetCurrentProcess(),(void*) adr_Func, (void*)&oldFunc, 6, NULL);
//Writing our six bytes
WriteProcessMemory(GetCurrentProcess(), (void*)adr_Func, (void*)&jump, 6, NULL);
...


After that, on every call to original function your jump will redirect it to your function.
Your function must be just like original one. The same header, the same calling conversion, and returning value.
Ex:
Code
bool __cdecl Hook_YourFunction(char *something)
{
//If you need to call original function inside hook, you must restore original six bytes
WriteProcessMemory(GetCurrentProcess(), (void*) adr_Func, (void*)&oldFunc, 6, NULL);

//Do whatever you want. Better to create separate function for this, that will help you to avoid some troubles

//Call original funct
bool x = ((bool (__cdecl*)(char*))adr_Func)(something);

//Hook again
WriteProcessMemory(GetCurrentProcess(), (void*)adr_Func, (void*)&jump, 6, NULL);
return x;
}


Also, as I said, you must to restore original function before your plugin will be unloaded:
Code
C_DLLEXPORT void JASS_Detach(int iscmd) {
WriteProcessMemory(GetCurrentProcess(), (void*) adr_Func, (void*)&oldFunc, 6, NULL);
...


Remember, that not all the functions can be replaced that way. Ever if you will copy original function header, there is no guaranties that it will be the same as REAL function header. Compiler like to optimize non-exported functions, especially if it is declared as static. If your actions causing the JKA to crash, it's mean, that function differs from it's source.
 
WEAPON_XDate: Saturday, 09.06.2012, 04:36 | Message # 3
Group: User
Messages: 12
Reputation: 0
Status: Offline
hi!

It worked very nicely. Thank you so much.

for anyone who needs, for the USE function call like this
void __cdecl Hook_YourFunction(gentity_t *self, gentity_t *other, gentity_t *activator)

Thank you again :D.

Добавлено (09.06.2012, 04:36)
---------------------------------------------
Hello,

I run into a little issue. I am trying to hook target_level_change_use.

I followed your method, except i don't call original. It appears to work, but there are some weird side-effects.

For example, i dont' see explosion fx when i trigger a detpack or tripmine.

When i comment out all hooking related code, the explosion fx are back.

Also, this issue doesn't occur when i try to hook other _use functions.

 
BufferOverflowDate: Saturday, 09.06.2012, 13:02 | Message # 4
Group: Developer
Messages: 47
Reputation: 0
Status: Offline
Rly strange. Maybe, it's data corruption in any kind... Can you post a code?
 
WEAPON_XDate: Sunday, 10.06.2012, 04:00 | Message # 5
Group: User
Messages: 12
Reputation: 0
Status: Offline
yeah, and i use lugormod mod

I don't know if this is an issue but i also modified the sdk structure for entity and client to match lugormod. the reason i want to do this is to patch a bug in target_level_change that allows injecting console commands. Meanwhile i am using a different way to patch this bug by disabling any client command that contains "mapname".

do you still play JKA?

Code
#pragma pack (push,1)
struct jmp_far{
    BYTE instr_push;    //assembler push instruction
    DWORD arg;  //argument - pointer to your function
    BYTE instr_ret;  //assembler ret instruction
};
#pragma pack (pop)
jmp_far jump;

BYTE oldTargetLevelChangeUse[6];

qboolean G_MapExists( char *name )
{
    fileHandle_t fh;

    g_syscall(G_FS_FOPEN_FILE, JASS_VARARGS("maps/%s.bsp", name ), &fh, FS_READ);
    if (!fh)
     return qfalse;

    g_syscall(G_FS_FCLOSE_FILE, fh);
    return qtrue;
}

void __cdecl target_level_change_use(gentity_t *self, gentity_t *other, gentity_t *activator)
{
    /*WriteProcessMemory(GetCurrentProcess(), (void*)0x20140cc8, (void*)&oldTargetLevelChangeUse, 6, NULL);
    ((void (__cdecl*)(gentity_t*, gentity_t*, gentity_t*))0x20140cc8)(self, other, activator);
    */
    if (G_MapExists(self->message))
     g_syscall(G_SEND_CONSOLE_COMMAND, EXEC_APPEND, JASS_VARARGS("map %s\n", self->message));

    // hook again
    //jump.arg = (DWORD)(&target_level_change_use);
    WriteProcessMemory(GetCurrentProcess(), (void*)0x20140cc8, (void*)&jump, sizeof(jmp_far), NULL);
}

C_DLLEXPORT int JASS_Attach(eng_syscall_t engfunc, mod_vmMain_t modfunc, pluginres_t* presult, pluginfuncs_t* pluginfuncs, int vmbase, int iscmd) {
    JASS_SAVE_VARS();
    jump.instr_push = 0x68;
    jump.instr_ret = 0xC3;

    jump.arg = (DWORD)(&target_level_change_use);
    ReadProcessMemory( GetCurrentProcess(),(void*)0x20140cc8, (void*)&oldTargetLevelChangeUse, 6, NULL);
    WriteProcessMemory(GetCurrentProcess(), (void*)0x20140cc8, (void*)&jump, 6, NULL);

    iscmd = 0;
    return 1;
}

C_DLLEXPORT void JASS_Detach(int iscmd) {
    WriteProcessMemory(GetCurrentProcess(), (void*)0x20140cc8, (void*)&oldTargetLevelChangeUse, 6, NULL);
    iscmd = 0;
}


Message edited by WEAPON_X - Sunday, 10.06.2012, 04:04
 
BufferOverflowDate: Sunday, 10.06.2012, 11:54 | Message # 6
Group: Developer
Messages: 47
Reputation: 0
Status: Offline
WEAPON_X, it isn't such strange as I was thinking. Lugormod is obfuscated, so this problem could be caused by everything...
But, for a start, hadn't you tried not to add your plugin into jass.ini, but to load it via "jass load plugins/<name>.dll"?
 
WEAPON_XDate: Monday, 11.06.2012, 12:28 | Message # 7
Group: User
Messages: 12
Reputation: 0
Status: Offline
I will try eventually, i didn't know i could load plugin from console.

I found a nice way to fix target_level_change, which i posted in another thread.

Meanwhile, I am using hooking method to enhance lugormod's target_powerup_use, so far works great


Message edited by WEAPON_X - Monday, 11.06.2012, 12:32
 
Forum » JASS » English forum » Question - Hooking a function
Page 1 of 11
Search: