/* * decloak - find hidden processes by brute forcing pID space * Copyright (C) 2006 Eli Fulkerson * * updates and whatnot are likely to be found at http://www.elifulkerson.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include using namespace std; /* Linux likes to poop out if a single PID forks too often. This is why we do an outer and inner pid rather than just a single loop. In testing, fork() began to fail slightly past a 4000 count Two drawbacks come from this number (since we aren't talking between children at all): - if its very large, our counter doesn't work to know that we are done - we can only detect errant processes within the FORKS_PER_CHILD, not at the borders where the two outer children touch... its possible that child 1 will scan pIDs 200-4200 and come up clean, then the second child will hit 4202-8202, never noticing that 4101 is occupied. My advice: run the program a few more times, they can't hide forever. */ #define FORKS_PER_CHILD 4000 #define PLAIN "\033[0m" #define BOLD "\033[1m" #define RED "\033[1m" #define NAME "decloak" void usage() { cout << "Usage: ./" << NAME << endl; cout << endl; cout << "Will brute force the PID space on the system via fork(). If consecutive" << endl; cout << "fork()'s return non-consecutive PID's, it is assumed that a process has been" << endl; cout << "discovered at that PID. At that point the PID in question will be queried for" << endl; cout << "additional information." << endl; cout << endl; cout << "Output: " << endl; cout << "PID - a 'discovered' process id" << endl; cout << "PRI - the value returned by getpriority(PRIO_PROCESS, PID)" << endl; cout << "SID - the value returned by getsid(PID)" << endl; cout << "PGID - the value returned by getpgid(PID)" << endl; cout << "COMMAND - the contents of /proc/PID/cmdline" << endl; cout << endl; cout << "Caveats:" << endl; cout << "- This script is occasionally unable to realize that it has already covered the pID space." << endl; cout << "and may repeat itself several times before it reaches its sanity check. Don't Panic." << endl; cout << endl; cout << "- The pID space check is imperfect, there is a chance that 1 out of every " << FORKS_PER_CHILD << endl; cout << "processes will slip through the cracks. My advice? Run it twice." << endl; cout << endl; cout << NAME << ", Copyright 2006 - Eli Fulkerson" << endl; cout << "This utility lives at http://www.elifulkerson.com" << endl; } /* check to see if a pID exists in the /proc fileystem... if it does, print out the cmdline arguments. Regardless, return true if you find it, false if you do not... */ bool proc_cmdline( int pID ) { char filename[100]; int exists; string line; sprintf(filename, "/proc/%d/cmdline", pID); ifstream procfile (filename); if (procfile.is_open()) { while (!procfile.eof() ) { getline (procfile, line); cout << line << endl; } } else { cout << RED <<" ERROR!! No /proc/" << pID << "/cmdline entry!!" << PLAIN << endl; } } void proc_getpgid(int pID) { int pgid; errno = 0; pgid = getpgid(pID); if (errno != 0) { printf(RED "ERR " PLAIN ); } else { printf("%5d ", pgid); } } void proc_getpriority(int pID) { int priority; errno = 0; priority = getpriority(PRIO_PROCESS, pID); if (errno != 0) { printf(RED "ERR " PLAIN); } else { printf("%3d ", priority); } } void proc_getsid(int pID) { int sid; errno = 0; sid = getsid( pID); if (errno != 0) { printf(RED "ERR " PLAIN); } else { printf("%5d ", sid); } } int main(int argc, const char *argv[]) { for (int x=0; x first_pid) { done = true; } outside_count++; // sanity... because if our own pID is less than FORKS_PER_CHILD below the max, our counter // doesn't notice when we are rolled over ( our outside children will never have // a pID > than ours in that situation, since it rolls too early if (outside_count * FORKS_PER_CHILD > 120000) { cout << "Sanity count hit, aborting..." << endl; done = true; } } }