王朝网络
分享
 
 
 

远程shell特洛伊木马病毒

王朝厨房·作者佚名  2007-01-05
宽屏版  字体: |||超大  

综述

2001年9月5日,Qualys发布了一个关于基于Linux病毒的安全报警。这个病毒叫作"远程shell特洛伊木马(Remote Shell Trojan)",攻击Linux ELF格式的二进制可执行文件。它具有复制自己的能力:当被运行时,它就会感染所有/bin目录和当前目录下的所有二进制文件。除此之外,这个病毒还产生一个进程,在5503 UDP端口上监听。当这个进程收到一个特制的报文之后,就通过一个系统调用连接到源地址。

细节

通常,在UNIX系统中病毒不算是一种真正的威胁。一个病毒工作在普通用户权限下的病毒是不能感染没有写权限的二进制文件的。不过每次执行被感染的可执行文件,它就会感染当前目录下的二进制可执行文件,因此还是有一定的威胁的。一旦在root权限下,不小心执行了被病毒感染的文件,它就会感染这个/bin目录下的文件。一旦执行了象ls之类常用的系统命令,当前目录下的所有目录中的二进制可执行文件都会被感染。攻击者还可以通过RST的后门进程获得更高的权限。

来源

RST是处于研究目的开发的,只在内部使用。研究它的目标是分析如何使病毒在非root权限条件下,影响通常的Linux工作环境。然而,事情却并没有按照研究人员设想的方向发展。一个被感染的二进制可执行文件意外地把这个病毒泄露出实验室。

现在最关心的问题是如何阻止这个病毒的传播,以及尽可能地从被感染的主机中清除这个病毒。现在公众还不清楚发送到后门进程的报文格式。然而,将来通过逆向工程,人们可以获得这些技术细节。

解决方案

最好能够使二进制可执行文件将来能够具有对RST的免疫力。把ELF文件正文段增加4096字节,是正文段和数据段之间的空洞(hole)消失,可以提高系统对RST病毒的免疫力。采取了这种措施以后,RST病毒就没有空间在二进制可执行文件中写入自身的代码了。

这段清除病毒的代码非常简单易用。用户能够决定是否递归地自动检测清除RST病毒。或者对二进制可执行文件一个一个地使用这个清除程序,在这种模式下,系统管理者可以知道二进制可执行文件是否感染,是否具有免疫能力。

清除程序的简单用法:

% perl Recurse.pl remove

结论

再次建议所有使用Linux系统的人运行这个检测程序检查系统是否被感染。即使系统没有被感染,也应该采取措施使系统具有免疫能力。只有这样才可以使系统免受感染。

代码

Recurse.pl

#!/usr/bin/perl

use strict;

sub RecursiveDeinfect($);

my $path_to_cleaner = "./kill";

my $options_to_cleaner = "";

my $verbose;

if($ARGV[0] eq "-v") { $verbose = shift; }

$_ = $ARGV[0];

if(/detect/) {

$options_to_cleaner = "1";

print "Recursively detecting trojan starting in: ", $ARGV[1] "/", "

";

} elsif(/remove/) {

$options_to_cleaner = "2";

print "Recursively removing trojan starting in: ", $ARGV[1] "/", "

";

} elsif(/immune/) {

$options_to_cleaner = "4";

print "Recursively making all binaries starting in: ", $ARGV[1] "/", "immune

";

} else {

print "usage: $0 [-v] mode [startdir]

".

"where mode is one of the following:

".

" detect : Recursively detect trojan

".

" remove : Recursively remove trojan if trojan is present.

".

" immune : Recursively remove trojan if trojan is present.

".

" Make all innocent binaries immune for future infection

".

"The default startdir is /

";

exit(0);

}

RecursiveDeinfect($ARGV[1] "/");

sub RecursiveDeinfect($) {

my $startdir = shift;

my $filename;

my $ret;

return unless(opendir(my $DH, $startdir));

print "Checking $startdir for infected binaries..

" if($verbose);

while($filename = readdir($DH)) {

next if($filename eq "." or $filename eq "..");

next if(-l "$startdir/$filename");

stat("$startdir/$filename");

RecursiveDeinfect("$startdir/$filename") && next if(-d _);

next unless(-f _ && -x _);

$ret = qx($path_to_cleaner $options_to_cleaner $startdir/$filename 2>/dev/null);

if($options_to_cleaner eq "1" && $ret =~ /much alive/m) {

warn "$startdir/$filename: Trojan Detected.

";

} elsif($options_to_cleaner eq "2" && $ret =~ /trojan disabled/m) {

warn "$startdir/$filename: Trojan Detected and Removed

";

}

}

closedir($DH);

}

kill.c

/* RST trojan manipulator program

*

* this is an RST-remover code, it has the following features:

* 1. Detect RST trojans on the specified executable

* 2. Disable RST on the specified binary and during that process make

* the binary immune to further infection attempts

* 3. Make an innocent, not-infected binary immune to infection attempts

*/

#include

#include

#include

#include

#include

#include

#include

/* Disable_trojan()

* disables a trojan in an infected binary, making the binary immune to

* any further infection attempts */

int Disable_trojan(FILE *fp)

{

unsigned int i, padding, poffset, psize, oldentry;

Elf32_Phdr textseg, dataseg;

Elf32_Ehdr ehdr;

// move to the beginning of the file

if (fseek(fp, 0, SEEK_SET) != 0) goto err;

// read ELF binary header

if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) goto err;

if (ehdr.e_type != ET_EXEC) goto err;

// find text segment and data segment headers

if (fseek(fp, ehdr.e_phoff, SEEK_SET) != 0) goto err;

for (i=0;i {

if (fread(&textseg, sizeof(textseg), 1, fp) != 1) goto err;

if (textseg.p_offset == 0) break;

}

if (fread(&dataseg, sizeof(dataseg), 1, fp) != 1) goto err;

if (textseg.p_offset != 0)

{

/* wtf?! no text segment ??? */

goto err;

}

// do calculations

padding = dataseg.p_vaddr - (textseg.p_vaddr + textseg.p_filesz);

if (padding >= 4096)

return 0; /* Sheww, binary is not infected */

psize = (textseg.p_vaddr + textseg.p_filesz) - ehdr.e_entry;

poffset = (textseg.p_offset + textseg.p_filesz) - psize;

if (psize != 4096)

return 0; /* Binary already cleaned */

// read original entry point, that according to my reverse engineering

// is stored on the parasite at offset 1

if (fseek(fp, poffset+1, SEEK_SET)!=0) goto err;

if (fread(&oldentry, 4, 1, fp) != 1) goto err;

// restore the binarys entry point to point to the real program again,

// avoiding the execution of the parasite code.

// this pernamently disables the parasite code and makes the binary immune

// to further infection attempts.

ehdr.e_entry = oldentry;

if (fseek(fp, 0, SEEK_SET) != 0) goto err;

if (fwrite(&ehdr, sizeof(ehdr), 1, fp) != 1) goto err;

return 1; /* all done */

err: ;

return -1;

}

/* DisplayStatus()

* display the infection status of the specified binary */

int DisplayStatus(FILE *fp)

{

unsigned int i, padding, poffset, psize, oldentry;

Elf32_Phdr textseg, dataseg;

Elf32_Ehdr ehdr;

// move to the beginning of the file

if (fseek(fp, 0, SEEK_SET) != 0) goto err1;

// read ELF binary header

if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) goto err1;

if (ehdr.e_type != ET_EXEC) goto err1;

// find text segment and data segment headers

if (fseek(fp, ehdr.e_phoff, SEEK_SET) != 0) goto err1;

for (i=0;i {

if (fread(&textseg, sizeof(textseg), 1, fp) != 1) goto err1;

if (textseg.p_offset == 0) break;

}

if (fread(&dataseg, sizeof(dataseg), 1, fp) != 1) goto err1;

if (textseg.p_offset != 0)

{

/* wtf?! no text segment ??? */

goto err1;

}

// do calculations

padding = dataseg.p_vaddr - (textseg.p_vaddr + textseg.p_filesz);

psize = (textseg.p_vaddr + textseg.p_filesz) - ehdr.e_entry;

poffset = (textseg.p_offset + textseg.p_filesz) - psize;

printf("Estimated parasite offset : %d

",poffset);

printf("Binary infection status : ");

if (padding >= 4096)

printf("Not infected. not immune.

");

else if (psize != 4096)

printf("Trojan disabled, immune.

");

else

printf("Trojan is very much alive!

");

fflush(stdout);

return 0;

err1: ;

return -1;

}

int movedata(FILE *fp, int src_offset, int dst_offset, const int size)

{

char data[size];

int sloc;

// save current location

sloc = ftell(fp);

// move to source offset and read data

if (fseek(fp, src_offset, SEEK_SET) != 0) return -1;

fread(&data,size,1,fp);

// write data to destination offset

if (fseek(fp, dst_offset, SEEK_SET) != 0) return -1;

fwrite(&data,size,1,fp);

// return to original position

fseek(fp,sloc,SEEK_SET);

return 0;

}

/* make_immune()

* turns an innocent binary into an uninfectable binary */

int make_immune(FILE *fp)

{

unsigned int i, padding, poffset, psize, oldentry;

Elf32_Phdr textseg, dataseg;

struct stat stat;

Elf32_Ehdr ehdr;

// get file status

if (fstat(fileno(fp), &stat)<0) return -1;

// move to the beginning of the file

if (fseek(fp, 0, SEEK_SET) != 0) return -1;

// read ELF binary header

if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) return -1;

if (ehdr.e_type != ET_EXEC) return -1;

// find text segment and data segment headers

if (fseek(fp, ehdr.e_phoff, SEEK_SET) != 0) return -1;

for (i=0;i {

if (fread(&textseg, sizeof(textseg), 1, fp) != 1) return -1;

if (textseg.p_offset == 0) break;

}

if (fread(&dataseg, sizeof(dataseg), 1, fp) != 1) return -1;

if (textseg.p_offset != 0)

{

/* wtf?! no text segment ??? */

return -1;

}

// do calculations

padding = dataseg.p_vaddr - (textseg.p_vaddr + textseg.p_filesz);

psize = (textseg.p_vaddr + textseg.p_filesz) - ehdr.e_entry;

poffset = textseg.p_offset + textseg.p_filesz;

if (padding < 4096)

return 0; /* Already infected or already immune */

// Update segment header table

if (fseek(fp, ehdr.e_phoff, SEEK_SET) != 0) return -1;

for (i=0;i {

Elf32_Phdr phdr;

if (fread(&phdr, sizeof(phdr), 1, fp) != 1) return -1;

if (phdr.p_offset >= poffset)

{

phdr.p_offset += 4096;

goto writedown;

}

if (phdr.p_offset == 0)

{

phdr.p_filesz += 4096;

phdr.p_memsz += 4096;

goto writedown;

}

continue;

writedown: ;

if (fseek(fp, -1 * sizeof(phdr), SEEK_CUR) != 0) return -1;

if (fwrite(&phdr, sizeof(phdr), 1, fp) != 1) return -1;

}

// update section header table

if (fseek(fp, ehdr.e_shoff, SEEK_SET) != 0) return -1;

for (i=0;i {

Elf32_Shdr section;

if (fread(§ion, sizeof(section), 1, fp) != 1) return -1;

if (section.sh_offset > poffset)

{

section.sh_offset += 4096;

if (fseek(fp, -1 * sizeof(section), SEEK_CUR) != 0) return -1;

if (fwrite(§ion,sizeof(section),1,fp) != 1) return -1;

}

}

// physically move data from (poffset->eof), 4096 bytes forward

if (movedata(fp, poffset, poffset+4096, stat.st_size - poffset) != 0)

return -1; /* Fuck! */

// all done!

return 1;

}

int main(int argc, char *argv[])

{

FILE *fp;

int op;

if (argc < 3)

{

printf("usage: %s

",argv[0]);

printf("Available operations:

");

printf("1 display trojan status on the specified binary

");

printf("2 remove the trojan from a specified binary

");

printf("3 make an innocent binary immune

");

printf("4 remove trojan/if innocent binary then make immune

");

printf("5 check if trojan is currently running on the system

");

printf("

");

return -1;

}

op = atoi(argv[1]);

/* Run status check if operation 5 was selected */

if (op == 5)

{

struct flock lock;

int fd;

// try to open the trojans lockfile

if ((fd = open("/tmp/982235016-gtkrc-429249277", O_RDWR)) < 0)

{

printf("Trojan lockfile does not exist.

");

goto testok;

}

// try to lock the trojans lockfile

memset(&lock, 0, sizeof(lock));

lock.l_type = F_WRLCK;

if (fcntl(fd, F_SETLK, &lock) < 0)

{

perror("fcntl");

printf("ALERT! A Trojan remote access process is currently running!!

");

return 0;

}

printf("Trojan process is not currently running however trojan traces were discovered.

");

return 0;

testok: ;

printf("Trojan is not currently running on this system.

");

return 0;

}

/* Otherwise, open target binary file */

if (!(fp = fopen(argv[2], "r+b")))

{

fprintf(stderr, "Unable to open %s for reading/writing (%s)

",argv[2],strerror(errno));

return -1;

}

/* Implement the rest of the operations */

switch(op)

{

case 2: /* Remove trojan */

{

switch(Disable_trojan(fp))

{

case -1:

fprintf(stderr, "An error has occured (%s)

",strerror(errno));

return -1;

break;

case 0:

printf("%s: trojan not present

",argv[2]);

break;

case 1:

printf("%s: trojan disabled

",argv[2]);

break;

}

}

break;

case 1: /* Display infection status */

DisplayStatus(fp);

break;

case 3: /* Make an innocent binary immune */

switch (make_immune(fp))

{

case -1:

fprintf(stderr, "An error has occured (%s)

",strerror(errno));

return -1;

break;

case 0:

printf("%s: already immune.

",argv[2]);

return 0;

break;

case 1:

printf("%s: binary is now immune.

",argv[2]);

break;

}

break;

case 4: /* Remove trojan and make innocent binaries immune */

{

switch(Disable_trojan(fp))

{

case -1:

fprintf(stderr, "An error has occured (%s)

",strerror(errno));

return -1;

break;

case 0:

if (make_immune(fp) == 1)

printf("%s: trojan not present. innocent binary turned immune.

",argv[2]);

else

printf("%s: immune binary.

",argv[2]);

break;

case 1:

printf("%s: trojan disabled

",argv[2]);

break;

}

}

break;

default:

printf("Operation %d not implemented

",op);

return -1;

break;

}

}

makefile

all:

#

clear

#####################################

# Compiling antivirus program ##

#####################################

gcc kill.c -o temp

##########################################################

## Making the antivirus binary immune to RST infections ##

##########################################################

cp temp kill ; ./temp 4 kill ; rm -f temp

##########################################################

## All done, run perl Recurse.pl for RST detection, ##

## and removal options. ##

## -- anonymous research team ##

##########################################################

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝网络 版权所有