mirror of
https://github.com/gmh5225/awesome-game-security
synced 2026-06-21 13:56:22 +00:00
archive: add 5 repo prompt(s) [skip ci]
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,711 @@
|
||||
Project Path: arc_Salvatore-Als_cs2-signature-list_tdx9hqn1
|
||||
|
||||
Source Tree:
|
||||
|
||||
```txt
|
||||
arc_Salvatore-Als_cs2-signature-list_tdx9hqn1
|
||||
├── CBaseModelEntity_SetModel.md
|
||||
├── CBasePlayerController-ChangeTeam.md
|
||||
├── CBasePlayerController-HandleCommand_JoinTeam.md
|
||||
├── CBasePlayerController_SetPlayerName.md
|
||||
├── CCSPlayerController-SwitchTeam.md
|
||||
├── CGameRules-ClientSettingsChanged.md
|
||||
├── CTakeDamageInfo_GetWeaponName.md
|
||||
├── Clantag.md
|
||||
├── ClientPrint.md
|
||||
├── GetCSGlobalTeam__AND__UTIL_ConsolePrint.md
|
||||
├── GiveNamedItem.md
|
||||
├── Host_Say.md
|
||||
├── NetworkStateChanged.md
|
||||
├── README.md
|
||||
├── TakeDamage.md
|
||||
├── UTIL_ClientPrintAll.md
|
||||
├── UTIL_GetListenServerHost__AND__UTIL_PlayerSlotToPlayerController.md
|
||||
├── UTIL_Remove.md
|
||||
├── UTIL_SayTextFilter.md
|
||||
├── UTIL_SayTextFilter2.md
|
||||
├── WeaponBuy.md
|
||||
└── makesig.idc
|
||||
|
||||
```
|
||||
|
||||
`CBaseModelEntity_SetModel.md`:
|
||||
|
||||
```md
|
||||
search string: `weapons/models/defuser/defuser.vmdl`, and xref
|
||||
|
||||
```cpp
|
||||
v2 = a2;
|
||||
v3 = (__int64)a1;
|
||||
CBaseModelEntity_SetModel(a1, (__int64)"weapons/models/defuser/defuser.vmdl");
|
||||
sub_18084ABF0(v3, v2);
|
||||
v4 = (_DWORD *)sub_180CED000(&unk_1813D3728, 0xFFFFFFFFi64);
|
||||
if ( !v4 )
|
||||
v4 = *(_DWORD **)(qword_1813D3730 + 8);
|
||||
if ( *v4 == 1 )
|
||||
{
|
||||
v5 = (__int64 *)(*(__int64 (__fastcall **)(__int64, const char *, _QWORD, _QWORD))(*(_QWORD *)qword_18140DB60 + 48i64))(
|
||||
qword_18140DB60,
|
||||
"defuser_dropped",
|
||||
0i64,
|
||||
0i64);
|
||||
```
|
||||
|
||||
prototype: `void CBaseModelEntity::SetModel(CBaseModelEntity* pthis, const char *pszModel)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`CBasePlayerController-ChangeTeam.md`:
|
||||
|
||||
```md
|
||||
search string `"\"%s<%i><%s><%s>\" ChangeTeam() CTMDBG`
|
||||
|
||||
args: `CBasePlayerController *pController, int teamIndex`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
```
|
||||
|
||||
`CBasePlayerController-HandleCommand_JoinTeam.md`:
|
||||
|
||||
```md
|
||||
search string `HandleCommand_JoinTeam( %d ) - invalid`
|
||||
|
||||
prototype: `bool CBasePlayerController::HandleCommand_JoinTeam(CBasePlayerController *pPlayerController, int teamIndex, bool bQueue)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`CBasePlayerController_SetPlayerName.md`:
|
||||
|
||||
```md
|
||||
search string: `name \"%s\"` or `newname`, and xref
|
||||
|
||||
```cpp
|
||||
CBasePlayerController::SetPlayerName(v7, &v52);
|
||||
v37 = *(void (__fastcall **)(__int64, _QWORD, const char *, __int64))(*(_QWORD *)qword_18142C700 + 352i64);
|
||||
v38 = (*(__int64 (__fastcall **)(_DWORD *))(*(_QWORD *)v2 + 1032i64))(v2);
|
||||
sub_180B570E0(v7, &v53);
|
||||
if ( (_DWORD)v53 != -1 )
|
||||
v3 = v53 - 1;
|
||||
v37(qword_18142C700, v3, "name \"%s\"", v38);
|
||||
```
|
||||
|
||||
prototype: `void CBasePlayerController::SetPlayerName(CBasePlayerController* pthis, const char *name)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`CCSPlayerController-SwitchTeam.md`:
|
||||
|
||||
```md
|
||||
search string `CCSPlayerPawnBase::SwitchTeam( %d ) - invalid team index.\n`
|
||||
|
||||
or search string `\"%s<%i><%s><%s>\" SwitchTeam => ChangeBasePlayerTeamAndPendingTeam =%d , req team %d %.2f \n`
|
||||
|
||||
prototype: `bool CCSPlayerController::SwitchTeam(CBasePlayerController *pPlayerController, int teamIndex)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`CGameRules-ClientSettingsChanged.md`:
|
||||
|
||||
```md
|
||||
search string `fov_desired`, xref
|
||||
|
||||
look for the following snippet:
|
||||
```cpp
|
||||
if ( (_DWORD)PlayerInfo != -1 )
|
||||
v4 = (_DWORD)PlayerInfo - 1;
|
||||
v31 = (_BYTE *)v30(g_Source2EngineToServer, v4, "fov_desired");
|
||||
```
|
||||
You should have the oldname, newname and player_changename on the function.
|
||||
|
||||
the current function is `CGameRules::ClientSettingsChanged`
|
||||
|
||||
prototype: `bool CGameRules::ClientSettingsChanged(CGameRules *pGameRules, CBasePlayerController *pPlayerController)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`CTakeDamageInfo_GetWeaponName.md`:
|
||||
|
||||
```md
|
||||
search string: `%.*s`, and xref
|
||||
|
||||
Looks for following code snippet:
|
||||
|
||||
```cpp
|
||||
else
|
||||
{
|
||||
v6 = (char *)&unk_180D9CE78;
|
||||
}
|
||||
if ( (unsigned __int8)sub_18053C0F0(v6) )
|
||||
return v6 + 7;
|
||||
v15 = sub_180D24DE0(v6, 95i64);
|
||||
v16 = v15;
|
||||
if ( !v15 || (unsigned int)V_stricmp_fast(v15, "_projectile") )
|
||||
return v6;
|
||||
sub_180636EE0(&unk_1814F3E00, "%.*s", (unsigned int)(v16 - (_DWORD)v6), v6);
|
||||
return (char *)&unk_1814F3E00;
|
||||
}
|
||||
```
|
||||
|
||||
prototype: `const char *CTakeDamageInfo::GetWeaponName(CTakeDamageInfo *pthis)`
|
||||
|
||||
dll: `server`
|
||||
```
|
||||
|
||||
`Clantag.md`:
|
||||
|
||||
```md
|
||||
search string `clantag`
|
||||
|
||||
Search this snippet
|
||||
|
||||
```
|
||||
if ( !strcmp(Name, "ClanTagChanged") && (*(unsigned __int8 (__fastcall **)(_BYTE *))(*(_QWORD *)a1 + 912i64))(a1) )
|
||||
{
|
||||
String = KeyValues::GetString(a3, "tag", byte_180D76F38, 0i64, 0i64);
|
||||
sub_180638D90(a2, String);
|
||||
v8 = KeyValues::GetString(a3, "name", byte_180D76F38, 0i64, 0i64);
|
||||
sub_180638D70(a2, v8);
|
||||
sub_180566710(a1, 2i64);
|
||||
sub_180566710(a1, 3i64);
|
||||
}
|
||||
```
|
||||
|
||||
On my snippet, the function is the one after `String = KeyValues::GetString(a3, "tag", byte_180D76F38, 0i64, 0i64);` so XREF `sub_180638D90`.
|
||||
|
||||
args: `CBasePlayerController *pController, char clantag`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
|
||||
```
|
||||
|
||||
`ClientPrint.md`:
|
||||
|
||||
```md
|
||||
search string: `Console command too long`
|
||||
|
||||
look for the following snippet:
|
||||
```cpp
|
||||
else
|
||||
{
|
||||
sub_18075B2C0(v5, 2i64, "Console command too long.\n", 0i64, 0i64, 0i64, 0i64);
|
||||
}
|
||||
```
|
||||
|
||||
You should XREF the function that used the string.
|
||||
|
||||
prototype: `void ClientPrint(CBasePlayerController *player, int destination, const char *msg, ...);`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
|
||||
```
|
||||
|
||||
`GetCSGlobalTeam__AND__UTIL_ConsolePrint.md`:
|
||||
|
||||
```md
|
||||
earch string `%sTeam playing \"CT\": %s\n`
|
||||
|
||||
look for the following snippet:
|
||||
```cpp
|
||||
if ( a1 )
|
||||
v2 = a1;
|
||||
v4 = GetCSGlobalTeam(3);
|
||||
if ( v4 )
|
||||
{
|
||||
v5 = (_BYTE *)sub_18014F360(v4);
|
||||
if ( v5 && *v5 )
|
||||
{
|
||||
UTIL_ConsolePrint("%sTeam playing \"CT\": %s\n", v2, v5);
|
||||
}
|
||||
else if ( v3 )
|
||||
{
|
||||
UTIL_ConsolePrint("%sTeam \"CT\" is unset.\n", v2);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
prototype: `CCSTeam *GetCSGlobalTeam(int teamIndex)`
|
||||
|
||||
prototype: `void UTIL_ConsolePrint(const char *fmt, ...)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`GiveNamedItem.md`:
|
||||
|
||||
```md
|
||||
search string: `aNullptrEntInGi ; "nullptr Ent in GiveNamedItem: %s!`
|
||||
|
||||
args: `TODO`
|
||||
|
||||
dll: `server`
|
||||
|
||||
You have to look for the one that contains kevlar and other indication in the function
|
||||
|
||||

|
||||
|
||||
```
|
||||
|
||||
`Host_Say.md`:
|
||||
|
||||
```md
|
||||
search string: `All Chat` or `Allies Chat`, and xref
|
||||
|
||||
prototype: `void Host_Say(CBasePlayerController *pController, CCommand &args, bool teamonly, int unk1, const char *unk2)`
|
||||
|
||||
dll: `server`
|
||||
```
|
||||
|
||||
`NetworkStateChanged.md`:
|
||||
|
||||
```md
|
||||
search string: `light_capsule`, and xref
|
||||
|
||||
```cpp
|
||||
if ( *(_QWORD *)(v10 + 32) )
|
||||
v3 = *(void **)(v10 + 32);
|
||||
v11 = V_stricmp_fast(v3, "light_capsule");
|
||||
v12 = *(_DWORD *)(v5 + 128) == 2;
|
||||
*(_BYTE *)(v5 + 132) = v11 == 0;
|
||||
if ( v12
|
||||
&& *(_BYTE *)(v5 + 324)
|
||||
&& *(_DWORD *)(v5 + 300) == 1
|
||||
&& *(_DWORD *)(v5 + 196) == 1
|
||||
&& *(_DWORD *)(v5 + 292) != -1
|
||||
&& *(_BYTE *)(v5 + 417) != 1 )
|
||||
{
|
||||
NetworkStateChanged((_QWORD **)(v5 + 72), 417i64, 0xFFFFFFFFi64);
|
||||
*(_BYTE *)(v5 + 417) = 1;
|
||||
v13 = *(_QWORD *)(v5 + 64);
|
||||
if ( *(_BYTE *)(v5 + 448) )
|
||||
sub_18077A350(v13);
|
||||
else
|
||||
sub_18079A9E0(v13);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
```
|
||||
|
||||
prototype: `void NetworkStateChanged(void *chainEntity, int offset, int a3)`
|
||||
|
||||
dll: `server`
|
||||
```
|
||||
|
||||
`README.md`:
|
||||
|
||||
```md
|
||||
This repository gives you indications on the strings to search in order to find the signatures of the functions on CS2.
|
||||
|
||||
Keep in mind that you will need to refine your search, it is not an exact science.
|
||||
|
||||
---
|
||||
|
||||
### Clantag
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/Clantag.md
|
||||
|
||||
### WeaponBuy
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/WeaponBuy.md
|
||||
|
||||
### GiveNamedItem
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/GiveNamedItem.md
|
||||
|
||||
### UTIL_SayTextFilter2
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_SayTextFilter2.md
|
||||
|
||||
### UTIL_SayTextFilter
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_SayTextFilter.md
|
||||
|
||||
### CBasePlayerController::ChangeTeam
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CBasePlayerController-ChangeTeam.md
|
||||
|
||||
### CBasePlayerController::HandleCommand_JoinTeam
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CBasePlayerController-HandleCommand_JoinTeam.md
|
||||
|
||||
### CCSPlayerController::SwitchTeam
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CCSPlayerController-SwitchTeam.md
|
||||
|
||||
### CGameRules::ClientSettingsChanged
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CGameRules-ClientSettingsChanged.md
|
||||
|
||||
### GetCSGlobalTeam & UTIL_ConsolePrint
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/GetCSGlobalTeam__AND__UTIL_ConsolePrint.md
|
||||
|
||||
### UTIL_GetListenServerHost & UTIL_PlayerSlotToPlayerController
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_GetListenServerHost__AND__UTIL_PlayerSlotToPlayerController.md
|
||||
|
||||
### TakeDamage
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/TakeDamage.md
|
||||
|
||||
### ClientPrint
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/ClientPrint.md
|
||||
|
||||
### UTIL_ClientPrint
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_ClientPrintAll.md
|
||||
|
||||
### UTIL_ClientPrint
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_ClientPrintAll.md
|
||||
|
||||
### CBaseModelEntity::SetModel
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CBaseModelEntity_SetModel.md
|
||||
|
||||
### Host_Say
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/Host_Say.md
|
||||
|
||||
### NetworkStateChanged
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/NetworkStateChanged.md
|
||||
|
||||
### UTIL_Remove
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/UTIL_Remove.md
|
||||
|
||||
### CTakeDamageInfo::GetWeaponName
|
||||
https://github.com/Salvatore-Als/cs2-signature-list/blob/main/CTakeDamageInfo_GetWeaponName.md
|
||||
```
|
||||
|
||||
`TakeDamage.md`:
|
||||
|
||||
```md
|
||||
search string `CBaseEntity::TakeDamageOld:`
|
||||
|
||||
prototype: `void TakeDamage(CBaseEntity *pVictim, CTakeDamageInfo *damageInfo)`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
```
|
||||
|
||||
`UTIL_ClientPrintAll.md`:
|
||||
|
||||
```md
|
||||
search string: `UTIL_ClientPrint`
|
||||
|
||||
look for the following snippet:
|
||||
```cpp
|
||||
if ( (*(_DWORD *)(a1 + 864) & 0x100) == 0 )
|
||||
{
|
||||
v2 = (*(__int64 (__fastcall **)(__int64))(*(_QWORD *)a1 + 1032i64))(a1);
|
||||
V_strncpy(v31, v2, 128i64);
|
||||
v3 = v31;
|
||||
do
|
||||
{
|
||||
if ( !*v3 )
|
||||
break;
|
||||
if ( *v3 == 37 )
|
||||
*v3 = 32;
|
||||
++v3;
|
||||
}
|
||||
while ( v3 );
|
||||
v4 = v31;
|
||||
if ( !v31[0] )
|
||||
v4 = "<unconnected>";
|
||||
sub_180948060(1, (unsigned int)"#Cstrike_TitlesTXT_Game_connected", (_DWORD)v4, 0, 0i64, 0i64);
|
||||
}
|
||||
```
|
||||
|
||||
You should XREF the function that used the string "Cstrike_TitlesTXT_Game_connected"
|
||||
|
||||
prototype: `void UTIL_ClientPrintAll(int destination, const char *message, const char *param1, const char *param2, const char *param3, const char *param4)`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
```cpp
|
||||
#define HUD_PRINTNOTIFY 1
|
||||
#define HUD_PRINTCONSOLE 2
|
||||
#define HUD_PRINTTALK 3
|
||||
#define HUD_PRINTCENTER 4
|
||||
```
|
||||
```
|
||||
|
||||
`UTIL_GetListenServerHost__AND__UTIL_PlayerSlotToPlayerController.md`:
|
||||
|
||||
```md
|
||||
search string `UTIL_GetListenServerHost() called from a dedicated server or single-player game.\n`
|
||||
|
||||
look for the following snippet:
|
||||
```cpp
|
||||
__int64 UTIL_GetListenServerHost()
|
||||
{
|
||||
__int64 v0; // rdx
|
||||
__int64 v1; // r8
|
||||
|
||||
if ( !(unsigned __int8)sub_180CFAA80() )
|
||||
return UTIL_PlayerSlotToPlayerController(0);
|
||||
Warning("UTIL_GetListenServerHost() called from a dedicated server or single-player game.\n", v0, v1);
|
||||
return 0i64;
|
||||
}
|
||||
```
|
||||
|
||||
prototype: `CBasePlayerController *UTIL_GetListenServerHost()`
|
||||
|
||||
prototype: `CBasePlayerController *UTIL_PlayerSlotToPlayerController(CPlayerSlot slot)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`UTIL_Remove.md`:
|
||||
|
||||
```md
|
||||
search string: `defuser_pickup`, and xref
|
||||
|
||||
```cpp
|
||||
if ( *v6 == 1 )
|
||||
{
|
||||
pEvent = (*(__int64 (__fastcall **)(__int64, const char *, _QWORD, _QWORD))(*(_QWORD *)g_pgameevents
|
||||
+ 48i64))(
|
||||
g_pgameevents,
|
||||
"defuser_pickup",
|
||||
0i64,
|
||||
0i64);
|
||||
if ( pEvent )
|
||||
{
|
||||
sub_180B598D0(pEntity, (__int64)&v8);
|
||||
sub_180101C10(pEvent, "entityid", v8);
|
||||
sub_180108F60(pEvent, "userid", v3);
|
||||
sub_180108F00(pEvent, "priority", 0i64);
|
||||
(*(void (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)g_pgameevents + 56i64))(
|
||||
g_pgameevents,
|
||||
pEvent,
|
||||
0i64);
|
||||
}
|
||||
}
|
||||
result = UTIL_Remove(pEntity);
|
||||
```
|
||||
|
||||
prototype: `void UTIL_Remove(CEntityInstance* pEntity)`
|
||||
|
||||
dll: `server`
|
||||
```
|
||||
|
||||
`UTIL_SayTextFilter.md`:
|
||||
|
||||
```md
|
||||
xref `UTIL_SayTextFilter2`, look for the following snippet:
|
||||
|
||||
```cpp
|
||||
if ( v59 )
|
||||
{
|
||||
UTIL_SayTextFilter2((__int64)&v61, (__int64)v8, 1, v59, v19, v12, v60, 0i64);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOBYTE(v42) = 1;
|
||||
UTIL_SayTextFilter(&v61, v73, v8, v42);
|
||||
}
|
||||
```
|
||||
|
||||
prototype: `void UTIL_SayTextFilter2(IRecipientFilter* filter, const char* pText, CBasePlayerController* pPlayer, bool chat)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`UTIL_SayTextFilter2.md`:
|
||||
|
||||
```md
|
||||
search string: `#Cstrike_Name_Change`, and xref
|
||||
|
||||
```cpp
|
||||
UTIL_SayTextFilter2((__int64)&v45, v14, 1, (__int64)"#Cstrike_Name_Change", v10, &v51, 0i64, 0i64);
|
||||
v15 = (__int64 *)(*(__int64 (__fastcall **)(__int64, const char *, _QWORD, _QWORD))(*(_QWORD *)g_pGameEventManager + 48i64))(
|
||||
g_pGameEventManager,
|
||||
"player_changename",
|
||||
0i64,
|
||||
0i64);
|
||||
```
|
||||
|
||||
prototype: `void UTIL_SayTextFilter2(IRecipientFilter* filter, CBaseEntity* pEntity, bool chat, const char* msg_name, const char* param1, const char* param2, const char* param3, const char* param4)`
|
||||
|
||||
dll: `server`
|
||||
|
||||
```
|
||||
|
||||
`WeaponBuy.md`:
|
||||
|
||||
```md
|
||||
search string: `aItemPurchase ; "item_purchase"`
|
||||
|
||||
args: `TODO`
|
||||
|
||||
dll: `server`
|
||||
|
||||

|
||||
|
||||
```
|
||||
|
||||
`makesig.idc`:
|
||||
|
||||
```idc
|
||||
#include <idc.idc>
|
||||
|
||||
/*
|
||||
* https://gist.github.com/nosoop/7ddfad3f49f40ccd5a310608c091b134
|
||||
*/
|
||||
|
||||
/* makesig.idc: IDA script to automatically create and wildcard a function signature.
|
||||
* Copyright 2014, Asher Baker
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
static main()
|
||||
{
|
||||
Wait(); // We won't work until autoanalysis is complete
|
||||
|
||||
SetStatus(IDA_STATUS_WORK);
|
||||
|
||||
auto pAddress = ScreenEA();
|
||||
pAddress = GetFunctionAttr(pAddress, FUNCATTR_START);
|
||||
if (pAddress == BADADDR) {
|
||||
Warning("Make sure you are in a function!");
|
||||
SetStatus(IDA_STATUS_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
auto name = Name(pAddress);
|
||||
auto sig = "", found = 0;
|
||||
auto pFunctionEnd = GetFunctionAttr(pAddress, FUNCATTR_END);
|
||||
|
||||
while (pAddress != BADADDR) {
|
||||
auto pInfo = DecodeInstruction(pAddress);
|
||||
if (!pInfo) {
|
||||
Warning("Something went terribly wrong D:");
|
||||
SetStatus(IDA_STATUS_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
// isCode(GetFlags(pAddress)) == Opcode
|
||||
// isTail(GetFlags(pAddress)) == Operand
|
||||
// ((GetFlags(pAddress) & MS_CODE) == FF_IMMD) == :iiam:
|
||||
|
||||
auto bDone = 0;
|
||||
|
||||
if (pInfo.n == 1) {
|
||||
if (pInfo.Op0.type == o_near || pInfo.Op0.type == o_far) {
|
||||
if (Byte(pAddress) == 0x0F) { // Two-byte instruction
|
||||
sig = sig + sprintf("0F %02X ", Byte(pAddress + 1)) + PrintWildcards(GetDTSize(pInfo.Op0.dtype));
|
||||
} else {
|
||||
sig = sig + sprintf("%02X ", Byte(pAddress)) + PrintWildcards(GetDTSize(pInfo.Op0.dtype));
|
||||
}
|
||||
bDone = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bDone) { // unknown, just wildcard addresses
|
||||
auto i = 0, itemSize = ItemSize(pAddress);
|
||||
for (i = 0; i < itemSize; i++) {
|
||||
auto pLoc = pAddress + i;
|
||||
if ((GetFixupTgtType(pLoc) & FIXUP_MASK) == FIXUP_OFF32) {
|
||||
sig = sig + PrintWildcards(4);
|
||||
i = i + 3;
|
||||
} else {
|
||||
sig = sig + sprintf("%02X ", Byte(pLoc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsGoodSig(sig)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
pAddress = NextHead(pAddress, pFunctionEnd);
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
Warning("Ran out of bytes to create unique signature.");
|
||||
SetStatus(IDA_STATUS_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
auto len = strlen(sig) - 1, smsig = "\\x";
|
||||
for (i = 0; i < len; i++) {
|
||||
auto c = substr(sig, i, i + 1);
|
||||
if (c == " ") {
|
||||
smsig = smsig + "\\x";
|
||||
} else if (c == "?") {
|
||||
smsig = smsig + "2A";
|
||||
} else {
|
||||
smsig = smsig + c;
|
||||
}
|
||||
}
|
||||
|
||||
Message("Signature for %s:\n%s\n%s\n", name, sig, smsig);
|
||||
|
||||
SetStatus(IDA_STATUS_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
static GetDTSize(dtyp)
|
||||
{
|
||||
if (dtyp == dt_byte) {
|
||||
return 1;
|
||||
} else if (dtyp == dt_word) {
|
||||
return 2;
|
||||
} else if (dtyp == dt_dword) {
|
||||
return 4;
|
||||
} else if (dtyp == dt_float) {
|
||||
return 4;
|
||||
} else if (dtyp == dt_double) {
|
||||
return 8;
|
||||
} else {
|
||||
Warning("Unknown type size (%d)", dtyp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PrintWildcards(count)
|
||||
{
|
||||
auto i = 0, string = "";
|
||||
for (i = 0; i < count; i++) {
|
||||
string = string + "? ";
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
static IsGoodSig(sig)
|
||||
{
|
||||
|
||||
auto count = 0, addr;
|
||||
addr = FindBinary(addr, SEARCH_DOWN|SEARCH_NEXT, sig);
|
||||
while (count <= 2 && addr != BADADDR) {
|
||||
count = count + 1;
|
||||
addr = FindBinary(addr, SEARCH_DOWN|SEARCH_NEXT, sig);
|
||||
}
|
||||
|
||||
//Message("%s(%d)\n", sig, count);
|
||||
|
||||
return (count == 1);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,827 @@
|
||||
Project Path: arc_VitorMob_GHInterfacesCSGO_uydy4x_5
|
||||
|
||||
Source Tree:
|
||||
|
||||
```txt
|
||||
arc_VitorMob_GHInterfacesCSGO_uydy4x_5
|
||||
├── CMakeLists.txt
|
||||
├── LICENSE
|
||||
├── README.md
|
||||
├── include
|
||||
│ ├── ghooks
|
||||
│ │ └── GHooks.hpp
|
||||
│ ├── interface
|
||||
│ │ └── GHInterfaces.hpp
|
||||
│ ├── internals
|
||||
│ │ ├── icliententitylist.hpp
|
||||
│ │ └── usercmd.hpp
|
||||
│ └── vmt
|
||||
│ └── VMThook.hpp
|
||||
├── packages
|
||||
│ ├── client_client.so
|
||||
│ ├── csgo_linux64
|
||||
│ └── launcher_client.so
|
||||
├── sources
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── LauncherClient.cpp
|
||||
│ ├── ghooks
|
||||
│ │ └── GHooks.cpp
|
||||
│ ├── interface
|
||||
│ │ └── GHInterfaces.cpp
|
||||
│ └── vmt
|
||||
│ └── VMThook.cpp
|
||||
├── submodules
|
||||
│ └── googletest
|
||||
└── tests
|
||||
├── CMakeLists.txt
|
||||
└── Simple.cpp
|
||||
|
||||
```
|
||||
|
||||
`CMakeLists.txt`:
|
||||
|
||||
```txt
|
||||
# Information cmake
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
# Information projec
|
||||
project(model_cpp VERSION 0.1 LANGUAGES CXX)
|
||||
set(LIB_MAJOR_VERSION "0")
|
||||
set(LIB_MINOR_VERSION "1")
|
||||
set(LIB_PATCH_VERSION "0")
|
||||
|
||||
|
||||
# Information for builds
|
||||
set(FLAGS_DEBUG OFF )
|
||||
set(BUILD_TESTS OFF )
|
||||
set(BUILD_BENCHMARK OFF )
|
||||
set(FLAGS_OPTIMIZATIONS ON)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
|
||||
set(CMAKE_HAVE_THREADS_LIBRARY 1)
|
||||
set(CMAKE_USE_WIN32_THREADS_INIT 0)
|
||||
set(CMAKE_USE_PTHREADS_INIT 1)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
|
||||
# add subdirectory
|
||||
add_subdirectory( sources/ )
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory( tests/ )
|
||||
endif()
|
||||
if(BUILD_BENCHMARK)
|
||||
add_subdirectory( benchmark/ )
|
||||
endif()
|
||||
|
||||
# set flags
|
||||
set(CMAKE_CXX_FLAGS "-O2 -Os") # default flags
|
||||
|
||||
if(FLAGS_OPTIMIZATIONS)
|
||||
set(CMAKE_CXX_FLAGS "-ftree-vectorize -mavx -fno-stack-protector -march=native -O2 -Os -fdelete-null-pointer-checks -fdelete-dead-exceptions")
|
||||
elseif(FLAGS_DEBUG)
|
||||
set(CMAKE_CXX_FLAGS "-fsanitize=address -fms-extensions --all-warnings -DDEBUG -g -O2 -Os -Wvolatile -Warray-bounds --extra-warnings")
|
||||
endif()
|
||||
|
||||
```
|
||||
|
||||
`LICENSE`:
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Mob
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
```
|
||||
|
||||
`README.md`:
|
||||
|
||||
```md
|
||||
# GHInterfacesCSGO
|
||||
|
||||
Simple base hook for CS:GO on linux
|
||||
|
||||
|
||||
# Running
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
# Compile
|
||||
|
||||
Adjust the settings [config.hpp](config/config.hpp) !! to point to the correct path relative to the folder.
|
||||
|
||||
```
|
||||
cd build
|
||||
cmake ..
|
||||
make
|
||||
```
|
||||
|
||||
# Installation
|
||||
|
||||
> `mv launcher_client.so bin/linux64/launcher_client.so`
|
||||
|
||||
# Help ?
|
||||
|
||||
How does the code work? take a look at the article I made to explain how it develops
|
||||
|
||||
> [Reconstructing the CS:GO VTable on Linux](https://remoob.com/post/2023-06-29-reconstruct-csgo-vtable)
|
||||
|
||||
```
|
||||
|
||||
`include/ghooks/GHooks.hpp`:
|
||||
|
||||
```hpp
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <csignal>
|
||||
#include "vmt/VMThook.hpp"
|
||||
#include "internals/icliententitylist.hpp"
|
||||
|
||||
#define CLIENT_DLL_INTERFACE_VERSION "VClient018" // EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CHLClient, IBaseClientDLL, "VClient018", gHLClient );
|
||||
#define VCLIENTENTITYLIST_INTERFACE_VERSION "VClientEntityList003"
|
||||
#define ALIGN_ADDR(addr) ((void *)((size_t)(addr) & ~(sysconf(_SC_PAGE_SIZE) - 1)))
|
||||
|
||||
class GHooks
|
||||
{
|
||||
private:
|
||||
static size_t m_page_size;
|
||||
|
||||
public:
|
||||
static void GetClientModeSharedVTABLE(int sig, siginfo_t *info, void *ucontext);
|
||||
|
||||
// class
|
||||
struct ClientModeShared
|
||||
{
|
||||
uint64_t *vTable;
|
||||
uint64_t *g_pClientMode;
|
||||
size_t vTableSize;
|
||||
};
|
||||
|
||||
struct CHLClient
|
||||
{
|
||||
uint64_t *vTable;
|
||||
size_t vTableSize;
|
||||
};
|
||||
|
||||
CSGO::IClientEntityList *ClientEntityList;
|
||||
|
||||
GHooks();
|
||||
~GHooks();
|
||||
|
||||
void Start();
|
||||
void ReadjustPagesVTABLE();
|
||||
|
||||
ClientModeShared getClassClientModeShared();
|
||||
CHLClient getClassCHLClient();
|
||||
CSGO::IClientEntityList* getClassClientEntityList();
|
||||
};
|
||||
```
|
||||
|
||||
`include/interface/GHInterfaces.hpp`:
|
||||
|
||||
```hpp
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
typedef void* (*InstantiateInterfaceFn)();
|
||||
|
||||
class InterfaceReg
|
||||
{
|
||||
public:
|
||||
InstantiateInterfaceFn m_CreateFn;
|
||||
const char *m_pName;
|
||||
InterfaceReg *m_pNext; // For the global list.
|
||||
static InterfaceReg *s_pInterfaceRegs;
|
||||
};
|
||||
|
||||
// interface return status
|
||||
enum
|
||||
{
|
||||
IFACE_OK = 0,
|
||||
IFACE_FAILED
|
||||
};
|
||||
|
||||
class GHInterfaces
|
||||
{
|
||||
private:
|
||||
const std::string m_file;
|
||||
void *m_dl;
|
||||
Dl_info m_info;
|
||||
|
||||
bool Memcmp(const uint8_t *data, const std::vector<uint8_t>& pattern, const std::vector<uint8_t>& mask);
|
||||
|
||||
public:
|
||||
GHInterfaces(const std::string _file);
|
||||
~GHInterfaces();
|
||||
|
||||
u_int64_t IndexFunctionOffsetVtable64(u_int64_t _function, off_t _vtable_address);
|
||||
u_int64_t IndexFunctionOffsetVtable32(u_int64_t _function, off_t _vtable_address);
|
||||
uintptr_t FindPattern(const std::vector<uint8_t> &_pattern, const std::vector<uint8_t> &_mask, size_t _size);
|
||||
void *CreateInterfaceFN(const std::string _class);
|
||||
void* GetBaseAddress();
|
||||
};
|
||||
```
|
||||
|
||||
`include/internals/icliententitylist.hpp`:
|
||||
|
||||
```hpp
|
||||
#include <stdint.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace CSGO
|
||||
{
|
||||
class IClientEntity
|
||||
{
|
||||
public:
|
||||
// Delete yourself.
|
||||
virtual void Release(void) = 0;
|
||||
|
||||
// Network origin + angles
|
||||
virtual const void *&GetAbsOrigin(void) const = 0;
|
||||
virtual const void *&GetAbsAngles(void) const = 0;
|
||||
|
||||
virtual void **GetMouth(void) = 0;
|
||||
|
||||
// Retrieve sound spatialization info for the specified sound on this entity
|
||||
// Return false to indicate sound is not audible
|
||||
virtual bool GetSoundSpatialization(void *&info) = 0;
|
||||
|
||||
virtual bool IsBlurred(void) = 0;
|
||||
virtual void* GetModelName(void) const = 0;
|
||||
};
|
||||
|
||||
class IClientEntityList
|
||||
{
|
||||
public:
|
||||
// Get IClientNetworkable interface for specified entity
|
||||
virtual void *GetClientNetworkable(int entnum) = 0;
|
||||
virtual void *GetClientNetworkableFromHandle(void *hEnt) = 0;
|
||||
virtual void *GetClientUnknownFromHandle(void *hEnt) = 0;
|
||||
|
||||
// NOTE: This function is only a convenience wrapper.
|
||||
// It returns GetClientNetworkable( entnum )->GetIClientEntity().
|
||||
virtual IClientEntity *GetClientEntity(int entnum) = 0;
|
||||
virtual IClientEntity *GetClientEntityFromHandle(unsigned long *hEnt) = 0;
|
||||
|
||||
// Returns number of entities currently in use
|
||||
virtual int NumberOfEntities(bool bIncludeNonNetworkable) = 0;
|
||||
|
||||
// Returns highest index actually used
|
||||
virtual int GetHighestEntityIndex(void) = 0;
|
||||
|
||||
// Sizes entity list to specified size
|
||||
virtual void SetMaxEntities(int maxents) = 0;
|
||||
virtual int GetMaxEntities() = 0;
|
||||
virtual void *GetClientNetworkableArray() = 0;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`include/internals/usercmd.hpp`:
|
||||
|
||||
```hpp
|
||||
#pragma once
|
||||
|
||||
namespace CSGO
|
||||
{
|
||||
|
||||
struct CUserCmd {
|
||||
enum {
|
||||
IN_ATTACK = 1 << 0,
|
||||
IN_JUMP = 1 << 1,
|
||||
IN_DUCK = 1 << 2,
|
||||
IN_FORWARD = 1 << 3,
|
||||
IN_BACK = 1 << 4,
|
||||
IN_USE = 1 << 5,
|
||||
IN_MOVELEFT = 1 << 9,
|
||||
IN_MOVERIGHT = 1 << 10,
|
||||
IN_ATTACK2 = 1 << 11,
|
||||
IN_SCORE = 1 << 16,
|
||||
IN_BULLRUSH = 1 << 22
|
||||
};
|
||||
void* vmt;
|
||||
int commandNumber;
|
||||
int tickCount;
|
||||
void* viewangles;
|
||||
void* aimdirection;
|
||||
float forwardmove;
|
||||
float sidemove;
|
||||
float upmove;
|
||||
int buttons;
|
||||
char impulse;
|
||||
int weaponselect;
|
||||
int weaponsubtype;
|
||||
int randomSeed;
|
||||
short mousedx;
|
||||
short mousedy;
|
||||
bool hasbeenpredicted;
|
||||
void* viewanglesBackup;
|
||||
int buttonsBackup;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
`include/vmt/VMThook.hpp`:
|
||||
|
||||
```hpp
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstddef>
|
||||
|
||||
class VMTHook
|
||||
{
|
||||
public:
|
||||
VMTHook(uint64_t *_vtable_address, int _size);
|
||||
~VMTHook();
|
||||
|
||||
void VMTInstallHook(unsigned int _index_function, uintptr_t address_function_hook);
|
||||
void VMTUninstall(unsigned int _index_function);
|
||||
uint64_t *VMTGetVTableCopy();
|
||||
|
||||
private:
|
||||
uint64_t *m_vtable;
|
||||
uint64_t *m_vtable_copy;
|
||||
size_t m_vtable_size;
|
||||
|
||||
inline void Memcpy(uint64_t *_dst, uint64_t *_src, int _size);
|
||||
};
|
||||
```
|
||||
|
||||
`sources/CMakeLists.txt`:
|
||||
|
||||
```txt
|
||||
# Information cmake
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
# set variables
|
||||
|
||||
set(CMAKE_SHARED_LIBRARY_PREFIX "")
|
||||
|
||||
# add subdirectory
|
||||
|
||||
# add executable and target libraries
|
||||
add_library( launcher_client SHARED LauncherClient.cpp)
|
||||
|
||||
target_include_directories (launcher_client PRIVATE
|
||||
../include/
|
||||
../
|
||||
../packages/
|
||||
../interfaces
|
||||
../submodules/lief/include
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE SOURCES
|
||||
*.cpp
|
||||
)
|
||||
|
||||
target_sources(launcher_client PRIVATE
|
||||
${SOURCES}
|
||||
)
|
||||
```
|
||||
|
||||
`sources/LauncherClient.cpp`:
|
||||
|
||||
```cpp
|
||||
#include <dlfcn.h>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include "config/config.hpp"
|
||||
#include "ghooks/GHooks.hpp"
|
||||
#include "internals/usercmd.hpp"
|
||||
#include "internals/icliententitylist.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
CSGO::IClientEntityList *ClientEntityList;
|
||||
|
||||
static bool (*CreateMove)(void *_this, float flInputSampleTime, CSGO::CUserCmd *cmd);
|
||||
bool CreateMoveHook(void *_this, float flInputSampleTime, CSGO::CUserCmd *cmd)
|
||||
{
|
||||
std::cout << "[*] Hooked Function CreateMove" << std::endl
|
||||
<< "Cmd.buttons = " << cmd->buttons << std::endl;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
auto player = ClientEntityList->GetClientEntity(i);
|
||||
if (player)
|
||||
std::cout << "Player " << std::dec << i << std::endl;
|
||||
}
|
||||
|
||||
return CreateMove(_this, flInputSampleTime, cmd);
|
||||
}
|
||||
|
||||
void ClientModeSharedHook()
|
||||
{
|
||||
GHooks hooks;
|
||||
|
||||
hooks.Start();
|
||||
|
||||
sleep(10);
|
||||
|
||||
// Hooks
|
||||
std::cout << "[*] Hooking Methods Class ClientModeShared" << std::endl;
|
||||
|
||||
VMTHook vmt_hook_client(hooks.getClassClientModeShared().vTable, hooks.getClassClientModeShared().vTableSize);
|
||||
|
||||
ClientEntityList = hooks.getClassClientEntityList();
|
||||
|
||||
CreateMove = reinterpret_cast<bool (*)(void *_this, float flInputSampleTime, CSGO::CUserCmd *cmd)>(hooks.getClassClientModeShared().vTable[25]);
|
||||
|
||||
vmt_hook_client.VMTInstallHook(25, (uint64_t)&CreateMoveHook);
|
||||
|
||||
*(uint64_t *)hooks.getClassClientModeShared().g_pClientMode = (uint64_t)vmt_hook_client.VMTGetVTableCopy();
|
||||
}
|
||||
|
||||
void ThreadHooks()
|
||||
{
|
||||
sleep(TIMEOUT); // wait csgo load is libraries
|
||||
|
||||
std::cout << "[*] Starting Hooks" << std::endl;
|
||||
|
||||
ClientModeSharedHook();
|
||||
}
|
||||
|
||||
void LauncherMain(int argc, const char **argv)
|
||||
{
|
||||
std::cout << "[*] Loading LauncherClient.so" << std::endl;
|
||||
|
||||
void *dl = dlopen(BACKUP_LAUNCHER, RTLD_NOW);
|
||||
if (dl)
|
||||
{
|
||||
void *LauncherMain = dlsym(dl, "LauncherMain");
|
||||
if (LauncherMain)
|
||||
{
|
||||
static void (*LauncherMain_o)(int argc, const char **argv) = reinterpret_cast<void (*)(int argc, const char **argv)>(LauncherMain);
|
||||
std::thread hooks_thread(ThreadHooks);
|
||||
|
||||
LauncherMain_o(argc, argv);
|
||||
}
|
||||
|
||||
dlclose(dl);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("[!] Erro in open library : " + std::string(BACKUP_LAUNCHER));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
`sources/ghooks/GHooks.cpp`:
|
||||
|
||||
```cpp
|
||||
#include "ghooks/GHooks.hpp"
|
||||
#include "interface/GHInterfaces.hpp"
|
||||
#include "config/config.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ucontext.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
size_t GHooks::m_page_size = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
// class
|
||||
GHooks::ClientModeShared clientModeShared;
|
||||
GHooks::CHLClient chlClient;
|
||||
|
||||
GHooks::GHooks()
|
||||
{
|
||||
}
|
||||
|
||||
GHooks::~GHooks()
|
||||
{
|
||||
}
|
||||
|
||||
void sig_trap_capture(int sig, siginfo_t *info, void *ucontext)
|
||||
{
|
||||
GHooks::GetClientModeSharedVTABLE(sig, info, ucontext);
|
||||
}
|
||||
|
||||
// Função de tratamento do sinal
|
||||
void GHooks::GetClientModeSharedVTABLE(int sig, siginfo_t *info, void *ucontext)
|
||||
{
|
||||
if (sig == SIGTRAP)
|
||||
{
|
||||
std::cout << "[*] Received SIGTRAP (INT3) signal." << std::endl;
|
||||
|
||||
ucontext_t *context = static_cast<ucontext_t *>(ucontext);
|
||||
|
||||
unsigned long long rax = context->uc_mcontext.gregs[REG_RAX];
|
||||
std::cout << "[*] RAX [0x" << std::hex << rax << "]" << std::endl;
|
||||
|
||||
clientModeShared.vTable = *(uint64_t **)rax; // get vtable class ClientModeShared
|
||||
clientModeShared.g_pClientMode = (uint64_t *)rax;
|
||||
clientModeShared.vTableSize = 0;
|
||||
while (clientModeShared.vTable[clientModeShared.vTableSize] != NULL)
|
||||
{
|
||||
++clientModeShared.vTableSize;
|
||||
}
|
||||
|
||||
strncpy((char *)chlClient.vTable[10] + 35, "\xFF\xE2", 2); // recover bytes
|
||||
|
||||
// adjustment permission in memory for read and exec
|
||||
if (mprotect(ALIGN_ADDR(chlClient.vTable[10]), m_page_size, PROT_READ | PROT_EXEC) != 0)
|
||||
{
|
||||
perror("[!] mprotect error ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GHooks::Start()
|
||||
{
|
||||
GHInterfaces inter(CLIENT_CLIENT);
|
||||
|
||||
void *vClient = inter.CreateInterfaceFN(CLIENT_DLL_INTERFACE_VERSION);
|
||||
ClientEntityList = reinterpret_cast<CSGO::IClientEntityList*>(inter.CreateInterfaceFN(VCLIENTENTITYLIST_INTERFACE_VERSION));
|
||||
|
||||
chlClient.vTable = *(uint64_t **)(vClient + 0x0); // get vtable class CHLClient
|
||||
chlClient.vTableSize = 0;
|
||||
while (chlClient.vTable[chlClient.vTableSize] != NULL)
|
||||
{
|
||||
++chlClient.vTableSize;
|
||||
}
|
||||
|
||||
// Get Pointer pClientMode
|
||||
{
|
||||
struct sigaction sa;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = sig_trap_capture;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
if (sigaction(SIGTRAP, &sa, nullptr) == -1)
|
||||
{
|
||||
perror("[!] sigaction error ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// adjustment permission in memory for write
|
||||
if (mprotect(ALIGN_ADDR(chlClient.vTable[10]), m_page_size, PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NONE) != 0)
|
||||
{
|
||||
perror("[!] mprotect error ");
|
||||
}
|
||||
// insert signal int3 (breakpoint)
|
||||
strncpy((char *)chlClient.vTable[10] + 35, "\xCC\x00", 2);
|
||||
}
|
||||
|
||||
GHooks::ClientModeShared GHooks::getClassClientModeShared()
|
||||
{
|
||||
return clientModeShared;
|
||||
}
|
||||
|
||||
GHooks::CHLClient GHooks::getClassCHLClient()
|
||||
{
|
||||
return chlClient;
|
||||
}
|
||||
|
||||
CSGO::IClientEntityList *GHooks::getClassClientEntityList()
|
||||
{
|
||||
return ClientEntityList;
|
||||
}
|
||||
```
|
||||
|
||||
`sources/interface/GHInterfaces.cpp`:
|
||||
|
||||
```cpp
|
||||
#include "interface/GHInterfaces.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
||||
GHInterfaces::GHInterfaces(const std::string _file) : m_file(_file),
|
||||
m_dl(dlopen(m_file.c_str(), RTLD_LAZY | RTLD_NOLOAD))
|
||||
{
|
||||
dladdr(m_dl, &m_info);
|
||||
}
|
||||
|
||||
GHInterfaces::~GHInterfaces()
|
||||
{
|
||||
}
|
||||
|
||||
u_int64_t GHInterfaces::IndexFunctionOffsetVtable64(u_int64_t _function, off_t _vtable_address)
|
||||
{
|
||||
return (((_function - _vtable_address) / 8) - 1);
|
||||
}
|
||||
|
||||
u_int64_t GHInterfaces::IndexFunctionOffsetVtable32(u_int64_t _function, off_t _vtable_address)
|
||||
{
|
||||
return (((_function - _vtable_address) / 4) - 1);
|
||||
}
|
||||
|
||||
bool GHInterfaces::Memcmp(const uint8_t *_data, const std::vector<uint8_t> &_pattern, const std::vector<uint8_t> &_mask)
|
||||
{
|
||||
for (size_t i = 0; i < _pattern.size(); ++i)
|
||||
{
|
||||
if (*_data++ != _pattern[i] && _mask[i] != '?')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uintptr_t GHInterfaces::FindPattern(const std::vector<uint8_t> &_pattern, const std::vector<uint8_t> &_mask, size_t _size)
|
||||
{
|
||||
uintptr_t address = reinterpret_cast<uintptr_t>(m_info.dli_fbase);
|
||||
uintptr_t end_address = 0;
|
||||
|
||||
std::cout << "[*] Scanning memory in base address : 0x" << std::hex << address << "\n";
|
||||
for (size_t i = 0; i < _size; i++)
|
||||
{
|
||||
end_address = address + i;
|
||||
if (GHInterfaces::Memcmp(reinterpret_cast<uint8_t *>(end_address), _pattern, _mask))
|
||||
{
|
||||
std::cout << "[*] Scan found memory in address : 0x" << end_address << "\n";
|
||||
return end_address;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "[*] Not found pattern, end memory : 0x" << end_address << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *GHInterfaces::CreateInterfaceFN(const std::string _class)
|
||||
{
|
||||
if (m_dl)
|
||||
{
|
||||
// get InterfaceRegs pointer 1 attempt (better case)
|
||||
void *create_interface = dlsym(m_dl, "s_pInterfaceRegs");
|
||||
if (create_interface)
|
||||
{
|
||||
for (const InterfaceReg *current = *reinterpret_cast<InterfaceReg **>(create_interface); current; current = current->m_pNext)
|
||||
{
|
||||
if (std::string(current->m_pName).find(_class) != std::string::npos)
|
||||
{
|
||||
std::cout << "[*] Found class " << _class << " Address " << current->m_pNext << std::endl;
|
||||
return current->m_CreateFn();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "[*] Getting Interface 2 attempt " << std::endl;
|
||||
void *create_interface = dlsym(m_dl, "CreateInterface");
|
||||
|
||||
static void *(*CreateInterfaceFn)(const char *pName, int *pReturnCode);
|
||||
|
||||
CreateInterfaceFn = reinterpret_cast<void *(*)(const char *pName, int *pReturnCode)>(create_interface);
|
||||
|
||||
void *CreateFn = CreateInterfaceFn(_class.c_str(), nullptr);
|
||||
if (CreateFn != (void *)IFACE_FAILED)
|
||||
{
|
||||
std::cout << "[*] Found class " << _class << " Address " << CreateFn << std::endl;
|
||||
return CreateFn;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "[*] Not found interface " << _class << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("[*] Error dl " + std::string(dlerror()));
|
||||
}
|
||||
}
|
||||
|
||||
void* GHInterfaces::GetBaseAddress()
|
||||
{
|
||||
return m_info.dli_fbase;
|
||||
}
|
||||
```
|
||||
|
||||
`sources/vmt/VMThook.cpp`:
|
||||
|
||||
```cpp
|
||||
#include "vmt/VMThook.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
VMTHook::VMTHook(uint64_t *_vtable_address, int _size) : m_vtable(_vtable_address),
|
||||
m_vtable_size(_size)
|
||||
|
||||
{
|
||||
m_vtable_copy = new uint64_t[_size]; // first allocate array of row pointer
|
||||
|
||||
Memcpy(m_vtable_copy, _vtable_address, _size);
|
||||
|
||||
std::cout << "[*] VTable [" << _vtable_address << "] successfully copied" << std::endl;
|
||||
}
|
||||
|
||||
VMTHook::~VMTHook()
|
||||
{
|
||||
}
|
||||
|
||||
void VMTHook::VMTInstallHook(uint _index_function, uintptr_t address_function_hook)
|
||||
{
|
||||
if (_index_function > m_vtable_size)
|
||||
throw std::runtime_error("[!] Index exceeded VTable");
|
||||
|
||||
m_vtable_copy[_index_function] = address_function_hook;
|
||||
}
|
||||
|
||||
void VMTHook::VMTUninstall(uint _index_function)
|
||||
{
|
||||
if (_index_function > m_vtable_size)
|
||||
throw std::runtime_error("[!] Index exceeded VTable");
|
||||
|
||||
m_vtable_copy[_index_function] = m_vtable[_index_function];
|
||||
}
|
||||
|
||||
uint64_t *VMTHook::VMTGetVTableCopy()
|
||||
{
|
||||
return m_vtable_copy;
|
||||
}
|
||||
|
||||
void VMTHook::Memcpy(uint64_t *_dst, uint64_t *_src, int _size)
|
||||
{
|
||||
for (int i = 0; i < _size; i++)
|
||||
{
|
||||
_dst[i] = _src[i];
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
`tests/CMakeLists.txt`:
|
||||
|
||||
```txt
|
||||
# Information cmake
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
|
||||
include(GoogleTest)
|
||||
|
||||
# add subdirectory
|
||||
add_subdirectory( ../submodules/googletest build/googletest)
|
||||
|
||||
add_definitions(-DUNIT_TESTS)
|
||||
set(PROJECT_SOURCES
|
||||
Simple.cpp
|
||||
)
|
||||
|
||||
add_executable(model_test ${PROJECT_SOURCES})
|
||||
|
||||
target_include_directories (model_test PRIVATE
|
||||
../include/
|
||||
../packages/
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(model_test gtest gtest_main)
|
||||
```
|
||||
|
||||
`tests/Simple.cpp`:
|
||||
|
||||
```cpp
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
class Test : public testing::Test
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
TEST_F(Test, SimpleTest)
|
||||
{
|
||||
ASSERT_EQ(1,1);
|
||||
}
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user