# include <errno.h>
# endif
#endif
-static void anticheat_init(void)
+static void anticheat_init(char **envp)
{
#ifdef ANTICHEAT
#define FAIL exit(42)
- // anti ptrace; also, make a forked process copy to detach from debuggers
-# ifndef WIN32
- pid_t pid = fork();
- if(pid < 0)
- FAIL;
- if(pid == 0)
+ // anti LD_PRELOAD
+ // note that we're using envp here, so one doesn't simply hook into getenv()
+ static char *unsecure_envvars =
+ // UNSECURE_ENVVARS from glibc
+ "GCONV_PATH\0" // libraries are loaded from here
+ //"GETCONF_DIR\0" // harmless, can only fake getconf() output
+ //"HOSTALIASES\0" // harmless, just messes with DNS
+ "LD_AUDIT\0" // loads libraries
+ // "LD_DEBUG\0" // harmless, just shows data
+ // "LD_DEBUG_OUTPUT\0" // harmless, just shows data
+ "LD_DYNAMIC_WEAK\0" // changes name resolution
+ "LD_LIBRARY_PATH\0" // loads libraries
+ "LD_ORIGIN_PATH\0" // may load libraries
+ "LD_PRELOAD\0" // loads libraries
+ // "LD_PROFILE\0" // harmless, just creates profile
+ // "LD_SHOW_AUXV\0" // harmless, just shows data
+ // "LD_USE_LOAD_BIAS\0" // harmless
+ // "LOCALDOMAIN\0" // harmless, just messes with DNS
+ // "LOCPATH\0" // harmless, just messes with locales
+ // "MALLOC_TRACE\0" // harmless, just shows data
+ // "NIS_PATH\0" // harmless, just messes with DNS and user ID data
+ // "NLSPATH\0" // harmless, just messes with locales
+ // "RESOLV_HOST_CONF\0" // harmless, can cause private data to be printed from suid, but we're not suid
+ // "RES_OPTIONS\0" // harmless, just messes with DNS
+ // "TMPDIR\0" // harmless, we don't use temp files anyway
+ // "TZDIR\0" // harmless, just enables time travel
+ // EXTRA_UNSECURE_ENVVARS from glibc
+ "LD_AOUT_LIBRARY_PATH\0" // loads libraries
+ "LD_AOUT_PRELOAD\0" // loads libraries
+ ;
+
+ while(*envp)
{
- // nothing to do here
+ char *p = unsecure_envvars;
+ while(*p)
+ {
+ char *q = envp[0];
+ while(*p && *p == *q)
+ {
+ ++p;
+ ++q;
+ }
+ if(*p == 0 && *q == '=')
+ FAIL; // match!
+ // next!
+ while(*p)
+ ++p;
+ ++p;
+ }
+ ++envp;
}
- else
+
+ // anti ptrace; also, make a forked process copy to detach from debuggers
+# ifndef WIN32
{
- // parent
- int status;
- if(ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
- {
- kill(pid, SIGKILL);
+ pid_t pid = fork();
+ if(pid < 0)
FAIL;
+ if(pid == 0)
+ {
+ // nothing to do here
}
- for(;;)
+ else
{
- if(waitpid(pid, &status, 0) == (pid_t) -1)
- {
- if(errno == ECHILD) // process no longer exists
- FAIL;
- }
- if(WIFEXITED(status))
+ // parent
+ int status;
+ if(ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0)
{
- exit(WEXITSTATUS(status));
+ kill(pid, SIGKILL);
+ FAIL;
}
- if(WIFSTOPPED(status))
+ for(;;)
{
- printf("ptrace: continue... (signal: %d)\n", (int) WSTOPSIG(status));
- if(ptrace(PTRACE_CONT, pid, (void *) WSTOPSIG(status), NULL) < 0)
+ if(waitpid(pid, &status, 0) == (pid_t) -1)
{
- perror("okay.png");
+ if(errno == ECHILD) // process no longer exists
+ FAIL;
+ }
+ if(WIFEXITED(status))
+ {
+ exit(WEXITSTATUS(status));
+ }
+ if(WIFSTOPPED(status))
+ {
+ printf("ptrace: continue... (signal: %d)\n", (int) WSTOPSIG(status));
+ if(ptrace(PTRACE_CONT, pid, (void *) WSTOPSIG(status), NULL) < 0)
+ {
+ perror("okay.png");
+ }
}
}
+ // never gonna get to here
}
- // never gonna get to here
}
# endif
-
#endif
}
-int main (int argc, char **argv)
+int main (int argc, char **argv, char **envp)
{
- anticheat_init();
+ anticheat_init(envp);
signal(SIGFPE, SIG_IGN);