Il y a quelques jours je me suis amusé avec l'"assembleur" du PAWN (P-CODE) et j'ai codé une fonction qui permet de détourner des fonctions publique seulement si elles sont appelées par le serveur SA-MP (ou un plugin etc ...).
C'est complétement inutile je pense, mais ça peut être marrant.
[spoiler]
#include <a_samp>
new g_AmxDefsize = -1;
new g_AddrPublicTable = -1;
new g_AddrNativeTable = -1;
stock AMX_ReadString(addr, str[], len = sizeof (str))
{
new Value;
new i;
/* Fonction pas du tout optimisée mais elle fonctionne */
for(i = 0; i < len; i++, addr++)
{
#emit LREF.S.PRI addr
#emit STOR.S.PRI Value
str[i] = Value & 0xff;
if(str[i] == 0) return;
}
}
GetPublicCount()
{
return (g_AddrNativeTable - g_AddrPublicTable) / g_AmxDefsize;
}
ReadAmxHeader()
{
new Addr;
new Offset;
new Value;
#emit LCTRL 1
#emit STOR.S.PRI Addr
Addr = -Addr;
/* Offset of flags + defsize*/
Offset = Addr + 8;
#emit LREF.S.PRI Offset
#emit STOR.S.PRI Value
g_AmxDefsize = (Value >> 16);
/* Offset of publics table */
Offset = Addr + 32;
#emit LREF.S.PRI Offset
#emit STOR.PRI g_AddrPublicTable
/* Offset of natives table*/
Offset = Addr + 36;
#emit LREF.S.PRI Offset
#emit STOR.PRI g_AddrNativeTable
}
GetPublicIdx(public_name[])
{
new Addr;
new Offset;
new Public_Name;
new Name[128];
new i;
#emit LCTRL 1
#emit STOR.S.PRI Addr
Addr = -Addr;
for(i = 0; i < GetPublicCount(); i++)
{
Offset = Addr + g_AddrPublicTable + i * g_AmxDefsize + 4;
#emit LREF.S.PRI Offset
#emit STOR.S.PRI Public_Name
AMX_ReadString(Addr+Public_Name, Name);
if(strcmp(public_name, Name) == 0)
{
return i;
}
}
return -1;
}
GetPublicAddr(idx)
{
new Addr;
new Offset;
new Public_Addr;
#emit LCTRL 1
#emit STOR.S.PRI Addr
Addr = -Addr;
Offset = Addr + g_AddrPublicTable + idx * g_AmxDefsize;
#emit LREF.S.PRI Offset
#emit STOR.S.PRI Public_Addr
return Public_Addr;
}
DetourPublic(funcToDetour[], func_dest[])
{
new Addr;
new func_1, func_2;
new Offset;
new Func_Addr;
#emit LCTRL 1
#emit STOR.S.PRI Addr
Addr = -Addr;
func_1 = GetPublicIdx(funcToDetour);
func_2 = GetPublicIdx(func_dest);
if(func_1 != -1 && func_2 != -1)
{
Func_Addr = GetPublicAddr(func_2);
Offset = Addr + g_AddrPublicTable + func_1 * g_AmxDefsize;
#emit LOAD.S.pri Func_Addr
#emit SREF.S.PRI Offset
}
}
public MyOnPlayerConnect(playerid);
public MyOnPlayerConnect(playerid)
{
print("MyOnPlayerConnect()");
OnPlayerConnect(playerid);
}
public OnPlayerConnect(playerid)
{
print("OnPlayerConnect()");
}
public OnGameModeInit()
{
}
main()
{
ReadAmxHeader();
DetourPublic("OnPlayerConnect", "MyOnPlayerConnect");
}
[/spoiler]
Je me suis très fortement inspiré des codes d'Y_Less.
Ce code fait en sorte que quand le serveur appel OnPlayerConnect c'est la fonction MyOnPlayerConnect qui est appelé à la place.