hook Linuxカーネル関数によるプロセス/スレッドの作成と破棄の監視
6239 ワード
Linuxは実際にはスレッドというものがありますが、具体的にはカーネルの中にはプロセスグループの頭+軽量レベルのプロセスがあります.
Linusに感谢しすぎて、仕事量が一瞬で下りてきて、カーネルスレッド/プロセスに差がなくて、1セットのものを书いて2セットともやったと言って、どうせあの連中も分からない...
すべてのプロセスの作成はdo_によって行われます.fork()カーネル関数で行い、すべてのプロセスの破棄はdo_exit()は,システム呼び出しなどはこの2つの関数のパッケージにすぎない.
たとえば、次のように、プロセス/スレッドの作成に関連するシステム呼び出しの処理関数です.の
hookはこの2つの関数ですべての作成破壊を監視することができます.
どのようにhookするかについて、飞客雑志でいくつかのinline hookを见つけて、すべてhook関数の入り口のアセンブリを修正して、JMPを挿入して自分のコードまで走ってから手动でスタックJMPをバランスさせて帰って、疲れません额、、
そしてこのPh 4 nt 0 m Security Teamグループの記事を見てhttp://blog.csdn.net/lucien_cc/article/details/7544834
残念なことに、このグループの現在のメインステーションはもう訪問できません.Google Sitesではグループの以前の文章を見つけることができます.
http://www.80vul.com/新しい駅のようです
OK、帰ってきて、文章は入り口を変えないで、hook関数の中で下層関数を呼び出すcallを修正すると言って、簡単に実現したようです.の
見てみろforkとdo_exitのコード
コードはよく分かりましたdo_exitはprofile_に呼び出されますtask_exit、そしてプロセスは必死です..の
do_forkはcopyを呼び出しますプロセスコピープロセス、copy_の場合プロセスが成功すると、プロセスは作成に成功し、最後にPID値を返します.
SOは,この2回の関数呼び出しのcall文を修正するだけですべての作成と破棄を監視できる.
最後の実装コードは次のとおりです.
アンインストールカーネルをマウントし、dmesgは出力を表示します.
OK、いい、、、、、
Linusに感谢しすぎて、仕事量が一瞬で下りてきて、カーネルスレッド/プロセスに差がなくて、1セットのものを书いて2セットともやったと言って、どうせあの連中も分からない...
すべてのプロセスの作成はdo_によって行われます.fork()カーネル関数で行い、すべてのプロセスの破棄はdo_exit()は,システム呼び出しなどはこの2つの関数のパッケージにすぎない.
たとえば、次のように、プロセス/スレッドの作成に関連するシステム呼び出しの処理関数です.の
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
int __user *parent_tidptr, *child_tidptr;
clone_flags = regs.ebx;
newsp = regs.ecx;
parent_tidptr = (int __user *)regs.edx;
child_tidptr = (int __user *)regs.edi;
if (!newsp)
newsp = regs.esp;
return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr);
}
/*
* This is trivial, and on the face of it looks like it
* could equally well be done in user mode.
*
* Not so, for quite unobvious reasons - register pressure.
* In user mode vfork() cannot have a stack frame, and if
* done by calling the "clone()" system call directly, you
* do not have enough call-clobbered registers to hold all
* the information you need.
*/
asmlinkage int sys_vfork(struct pt_regs regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL);
}
hookはこの2つの関数ですべての作成破壊を監視することができます.
どのようにhookするかについて、飞客雑志でいくつかのinline hookを见つけて、すべてhook関数の入り口のアセンブリを修正して、JMPを挿入して自分のコードまで走ってから手动でスタックJMPをバランスさせて帰って、疲れません额、、
そしてこのPh 4 nt 0 m Security Teamグループの記事を見てhttp://blog.csdn.net/lucien_cc/article/details/7544834
残念なことに、このグループの現在のメインステーションはもう訪問できません.Google Sitesではグループの以前の文章を見つけることができます.
http://www.80vul.com/新しい駅のようです
OK、帰ってきて、文章は入り口を変えないで、hook関数の中で下層関数を呼び出すcallを修正すると言って、簡単に実現したようです.の
見てみろforkとdo_exitのコード
fastcall NORET_TYPE void do_exit(long code)
{
struct task_struct *tsk = current;
struct taskstats *tidstats;
int group_dead;
unsigned int mycpu;
profile_task_exit(tsk);
WARN_ON(atomic_read(&tsk->fs_excl));
...
}// ,
long do_fork(unsigned long clone_flags,
...
{
struct task_struct *p;
int trace = 0;
struct pid *pid = alloc_pid();
...
p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
if (!IS_ERR(p)) {
...
} else {
free_pid(pid);
nr = PTR_ERR(p);
}
return nr;
}
コードはよく分かりましたdo_exitはprofile_に呼び出されますtask_exit、そしてプロセスは必死です..の
do_forkはcopyを呼び出しますプロセスコピープロセス、copy_の場合プロセスが成功すると、プロセスは作成に成功し、最後にPID値を返します.
SOは,この2回の関数呼び出しのcall文を修正するだけですべての作成と破棄を監視できる.
最後の実装コードは次のとおりです.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/smp_lock.h>
MODULE_LICENSE("GPL");
#define _FORK_copy_process 0xc04234f9
#define _EXIT_profile_task_exit 0xc04268cf
#define _DO_EXIT_ 0xc0427ec1
#define _DO_FORK_ 0xc0424944 // /boot/System.map-$(uname -r)
//CR0 ,
#define CLEAR_CR0 asm ("pushl %eax
\t" \
"movl %cr0, %eax
\t" \
"andl $0xfffeffff, %eax
\t" \
"movl %eax, %cr0
\t" \
"popl %eax");
#define SET_CR0 asm ("pushl %eax
\t" \
"movl %cr0, %eax
\t" \
"orl $0x00010000, %eax
\t" \
"movl %eax, %cr0
\t" \
"popl %eax");
struct task_struct *(*orig_copy_process)(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
int pid); //
static struct task_struct *my_copy_process(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr,
int pid)
{
struct task_struct * ret;
ret = (*orig_copy_process)(clone_flags,stack_start,regs,stack_size,parent_tidptr,child_tidptr,pid);
if(!IS_ERR(ret))
printk("---z---\tPID:%d fork %d successed!
",current->pid,pid);
else
printk("---z---\tPID:%d fork %d failed!
",current->pid,pid);
return ret;
}
void (*orig_profile_task_exit)(struct task_struct * task);
void my_profile_task_exit(struct task_struct * task)
{// , CONFIG_PROFILING=n ,profile_task_exit , , centos 5.5 , 。。。。
printk("---z---\tPID:%d exited!
",current->pid);
}
static int replace_fun(unsigned long handle, unsigned long old_fun, unsigned long new_fun)
{
unsigned char *p = (unsigned char *)handle;
int i = 0;
while(1)
{
if(i++ > 128)
return 0;
if(*p == 0xe8)
{//e8 GCC call,
if((*(int *)(p+1) + (unsigned long)p + 5) == old_fun)
{//so e8 ,
*(int *)(p+1) = new_fun - (unsigned long)p - 5;
return 1;
}
}
p++;
}
}
static int _init_module(void ) {
printk("---z---\t+++++++++++
");
orig_copy_process = _FORK_copy_process;
orig_profile_task_exit = _EXIT_profile_task_exit;
lock_kernel();
CLEAR_CR0
replace_fun(_DO_FORK_, _FORK_copy_process, (unsigned long)my_copy_process);
replace_fun(_DO_EXIT_, _EXIT_profile_task_exit, (unsigned long)my_profile_task_exit);
SET_CR0
unlock_kernel();
return 0;
}
static void _cleanup_module(void) {
printk("---z---\t---------
");
lock_kernel();
CLEAR_CR0
replace_fun(_DO_FORK_, (unsigned long)my_copy_process, _FORK_copy_process);
replace_fun(_DO_EXIT_, (unsigned long)my_profile_task_exit, _EXIT_profile_task_exit);
SET_CR0
unlock_kernel();
}
module_init(_init_module);
module_exit(_cleanup_module);
アンインストールカーネルをマウントし、dmesgは出力を表示します.
---z--- +++++++++++
---z--- PID:12668 exited!
---z--- PID:642 fork 12671 successed!
---z--- PID:12671 exited!
---z--- PID:4422 fork 12672 successed!
---z--- PID:12672 exited!
---z--- PID:6992 fork 12673 successed!
---z--- PID:11 fork 12674 successed!
---z--- PID:12674 fork 12675 successed!
---z--- PID:12675 exited!
---z--- PID:12674 exited!
---z--- ---------
OK、いい、、、、、