From: Rudolf Polzer Date: Mon, 4 Jun 2012 11:00:12 +0000 (+0200) Subject: also add a facility to read and scan DLL memory X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a4a282e4e5db439643c26f568c1d4abab6a9796b;p=xonotic%2Fdarkplaces.git also add a facility to read and scan DLL memory --- diff --git a/host_cmd.c b/host_cmd.c index 4d2b93b6..d25f61e5 100644 --- a/host_cmd.c +++ b/host_cmd.c @@ -2983,6 +2983,10 @@ void Host_InitCommands (void) Cmd_AddCommand ("pingplreport", Host_PingPLReport_f, "command sent by server containing client ping and packet loss values for scoreboard, triggered by pings command from client (not used by QW servers)"); Cmd_AddCommand ("fixtrans", Image_FixTransparentPixels_f, "change alpha-zero pixels in an image file to sensible values, and write out a new TGA (warning: SLOW)"); +#ifdef ANTICHEAT + Cmd_AddCommand ("checkmemory", Sys_AntiCheat_CheckMemory_f, "check memory for patterns"); +#endif + Cvar_RegisterVariable (&r_fixtrans_auto); Cvar_RegisterVariable (&team); diff --git a/quakedef.h b/quakedef.h index 6bd5ddfa..3b594916 100644 --- a/quakedef.h +++ b/quakedef.h @@ -32,6 +32,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define DP_FUNC_NORETURN #endif +#ifdef ANTICHEAT +#define _GNU_SOURCE // for memmem +#endif + #include #include #include diff --git a/sys.h b/sys.h index c4c8c559..acce3acf 100644 --- a/sys.h +++ b/sys.h @@ -116,7 +116,20 @@ void Sys_MakeProcessNice (void); void Sys_MakeProcessMean (void); // call this from main(); if it returns false, exit using return -qboolean anticheat_init(char **envp); +qboolean Sys_AntiCheat_Init(char **envp); +#ifdef ANTICHEAT +typedef enum +{ + CHECKMEMORY_N_A, + CHECKMEMORY_NODLL, + CHECKMEMORY_NOMATCH, + CHECKMEMORY_MATCHED +} +Sys_AntiCheat_CheckMemory_Result_t; +// dllsubstringmode: false = check only dlls without this substring, true = check only dlls with this substring +Sys_AntiCheat_CheckMemory_Result_t Sys_AntiCheat_CheckMemory(const char *dllsubstring, qboolean dllsubstringmode, const void *pattern, size_t length); +void Sys_AntiCheat_CheckMemory_f(void); +#endif #endif diff --git a/sys_linux.c b/sys_linux.c index bf7cd29b..50982ffb 100644 --- a/sys_linux.c +++ b/sys_linux.c @@ -150,7 +150,7 @@ void Sys_InitConsole (void) int main (int argc, char **argv, char **envp) { - if(!anticheat_init(envp)) + if(!Sys_AntiCheat_Init(envp)) return 42; signal(SIGFPE, SIG_IGN); diff --git a/sys_sdl.c b/sys_sdl.c index 4863ac76..aadbe83d 100644 --- a/sys_sdl.c +++ b/sys_sdl.c @@ -178,7 +178,7 @@ void Sys_InitConsole (void) int main (int argc, char *argv[], char *envp[]) { - if(!anticheat_init(envp)) + if(!Sys_AntiCheat_Init(envp)) return 42; signal(SIGFPE, SIG_IGN); diff --git a/sys_shared.c b/sys_shared.c index a2a3852b..8297a87a 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -648,7 +648,87 @@ void Sys_MakeProcessMean (void) # include # endif #endif -qboolean anticheat_init(char **envp) + +#ifdef ANTICHEAT +// whole function only exists if anticheat is enabled +Sys_AntiCheat_CheckMemory_Result_t Sys_AntiCheat_CheckMemory(const char *dllsubstring, qboolean dllsubstringmode, const void *pattern, size_t length) +{ +# ifdef __linux__ + Sys_AntiCheat_CheckMemory_Result_t ret = CHECKMEMORY_NODLL; + FILE *f = fopen("/proc/self/maps", "r"); + if(!f) + exit(42); + while(!feof(f)) + { + char buf[PATH_MAX+100], perm[5]; + char mapname[sizeof(buf)]; + void *begin, *end; + + if(fgets(buf, sizeof(buf), f) == 0) + break; + + mapname[0] = 0; + sscanf(buf, "%p-%p %4s %*x %*5s %*d %s", + &begin, &end, perm, mapname); + + if(mapname[0] == 0) + continue; + if(perm[0] != 'r') + continue; + if(mapname[0] == '[') + continue; + + if(dllsubstring && *dllsubstring) + if(!!strstr(mapname, dllsubstring) ^ dllsubstringmode) + continue; + + ret = CHECKMEMORY_NOMATCH; + + if(length) + { + if(memmem(begin, (unsigned char *) end - (unsigned char *) begin, pattern, length)) + { + ret = CHECKMEMORY_MATCHED; + break; + } + } + else + { + ret = CHECKMEMORY_MATCHED; + break; + } + } + fclose(f); + return ret; +# else + return CHECKMEMORY_N_A; +# endif +} +void Sys_AntiCheat_CheckMemory_f(void) +{ + Sys_AntiCheat_CheckMemory_Result_t r; + if(Cmd_Argc() != 4) + return; + r = Sys_AntiCheat_CheckMemory(Cmd_Argv(1), atoi(Cmd_Argv(2)), Cmd_Argv(3), strlen(Cmd_Argv(3))); + switch(r) + { + case CHECKMEMORY_NOMATCH: + Con_Printf("NOMATCH\n"); + break; + case CHECKMEMORY_MATCHED: + Con_Printf("MATCHED\n"); + break; + case CHECKMEMORY_NODLL: + Con_Printf("NODLL\n"); + break; + case CHECKMEMORY_N_A: + Con_Printf("N/A\n"); + break; + } +} +#endif + +qboolean Sys_AntiCheat_Init(char **envp) { #ifdef ANTICHEAT # define FAIL return false @@ -708,8 +788,8 @@ qboolean anticheat_init(char **envp) } } - // anti ptrace; also, make a forked process copy to detach from debuggers # ifndef WIN32 + // anti ptrace; also, make a forked process copy to detach from debuggers { pid_t pid = fork(); if(pid < 0) @@ -755,4 +835,3 @@ qboolean anticheat_init(char **envp) return true; } - diff --git a/sys_win.c b/sys_win.c index 695a0642..7462aa49 100644 --- a/sys_win.c +++ b/sys_win.c @@ -314,7 +314,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin global_hInstance = hInstance; - if(!anticheat_init(NULL)) + if(!Sys_AntiCheat_Init(NULL)) return 42; lpBuffer.dwLength = sizeof(MEMORYSTATUS);