Download as pdf or txt
Download as pdf or txt
You are on page 1of 11

04/11/2022, 13:37 Xeldax's Blog - Share it

XELDAX BLOG HOME


ABOUT
OOPS  

LINUX 2021-12-16 04:52:34


ELF STEVEN XELDAX

文件内
存执行
学习小

无文件攻击有很多中,在java中有内存马,在windows中
有PE反射加载,这些内存加载技术很大一定程度上能够帮
助我们规避蓝队防护软件的检测。但是在linux中很少有人
提及到ELF内存马的技术,其实主要原因在于ELF内存载
入很难解决延迟绑定和动态依赖库加载的问题,大部分elf
加载需要依靠memfd和shm这种linux特性的办法来做,而
这两种办法需要linux系统版本有一定的限制。
前言
memfd 无文件方法
shm 无文件方法
一种golang elf内存马的实现
推荐工具
run-embedded-elf-from-memory
fileless-xec
fireELF
go-memfd
memfd-exmaple

https://xeldax.top/article/linux_no_file_elf_mem_execute 1/11
04/11/2022, 13:37 Xeldax's Blog - Share it

memrun
XELDAX BLOG 参考资料
HOME
ABOUT
OOPS  

前言

一个elf内存马必须这些条件:
1. elf文件不落地
2. elf动态加载

关于elf文件其实有许多之前人提出过的不错的思路
http://www.hick.org/code/skape/papers/remote-library-
injection.pdf
https://grugq.github.io/docs/ul_exec.txt
http://z0mbie.daemonlab.org/infelf.html
http://phrack.org/issues/63/11.html
https://github.com/mak/pyself
https://blog.gdssecurity.com/labs/2017/9/5/linux-based-
inter-process-code-injection-without-ptrace2.html

这些研究者的所提出的内存加载更多使用的是汇编角度进行而我
们再本文主要还是偏向于linux一些特性的探究。
MEMFD 无文件方法
:允许我们在内存中创建一个文件,但是它
memfd_create
在内存中的存储并不会被映射到文件系统中
这是linux系统的底层调用函数memfd_create(2),它在内核3.17
中引入,会创建一个匿名文件并返回一个文件描述符指向它,该
文件表现和常规文件类同, 可以进行修改,截断,内存映射等
等,但不同的是,它存在于RAM当中。这就是可以被攻击者所
利用的,如果有办法将需要执行elf通过memfd_create(2)写入内
存中进行执行的话就可以达到我们的目的。
运行的elf从proc文件系统是可以看到memfd的特征的

https://xeldax.top/article/linux_no_file_elf_mem_execute 2/11
04/11/2022, 13:37 Xeldax's Blog - Share it

使用memfd很简单,只要使用特定的系统调用,然后使用write调
XELDAX 用将我们的HelfO写入到
BLOG M E
memfdA句柄就行。
BOUT
OOPS  

1. int anoyexec(const char *path, char argv[]){


2. int fd, fdm, filesize;
3. void *elfbuf;
4. char cmdline[256];
5.
6. fd = open(path, O_RDONLY);
7. filesize = lseek(fd, SEEK_SET, SEEK_END);
8. lseek(fd,SEEK_SET,SEEK_SET);
9. elfbuf = malloc(filesize);
10. read(fd, elfbuf, filesize);
11. close(fd);
12. fdm = syscall(__NR_memfd_create, "elf",
MFD_CLOEXEC);
13. ftruncate(fdm,filesize);
14. write(fdm, elfbuf, filesize);
15. free(elfbuf);
16. sprintf(cmdline, "/proc/self/fd/%d", fdm);
17. // argv[0] = cmdline;
18. execve(cmdline, argv, NULL);
19. printf("%s",argv[0]);
20. // free(elfbuf);
21. return -1;
22.
23. }

然后这个句柄本身就可以在bash下直接执行,当然也可以在c中
运行execve执行

https://xeldax.top/article/linux_no_file_elf_mem_execute 3/11
04/11/2022, 13:37 Xeldax's Blog - Share it

XELDAX BLOG HOME


ABOUT
OOPS  

使用memfd实现fork
1. int elf_mem_exe_fork(){
2. int fd;
3. pid_t child;
4. char buf[BUFSIZ] = "";
5. ssize_t br;
6.
7. fd = syscall(SYS_memfd_create, "foofile",0);
8. if(fd == -1){
9. perror("memfd_create");
10. exit(EXIT_FAILURE);
11. }
12. child = fork();
13. if(child == 0){
14. dup2(fd,1);
15. close(fd);
16. execlp("/bin/date","",NULL);
17. perror("execlp date");
18. } else if(child == -1){
19. perror("fork");
20. exit(EXIT_FAILURE);
21. }
22. waitpid(child, NULL,0);
23. lseek(fd,0,SEEK_SET);
24. br = read(fd, buf, BUFSIZ);
25. if(br == -1){
26. perror("read");
27. exit(EXIT_FAILURE);
https://xeldax.top/article/linux_no_file_elf_mem_execute 4/11
04/11/2022, 13:37 Xeldax's Blog - Share it

28. }
XELDAX BLOG 29. H O M=E0;

buf[br] ABOUT
OOPS  
30. printf("pid: %d\n",getpid());

31. printf("child sad: %s \n",buf);


32. pause();
33. exit(EXIT_SUCCESS);
34.
35. }

在其他语言一样如此,甚至使用起来还要更加简单一点,比如说
python

1. import ctypes
2. import os
3.
4. binary = open('/bin/date','rb').read()
5.
6. fd = ctypes.CDLL(None).syscall(319,"",1)
7.
8. final_fd = open('/proc/self/fd/'+str(fd),'wb')
9.
10. final_fd.write(binary)
11.
12. final_fd.close()
13.
14. os.execl('/proc/self/fd/'+str(fd),"")

SHM 无文件方法
这个方法最早发现于glibc 中fexecve这个方法所应用。

fexecve同样的功能很强大,它能使我们执行一个程序(同
execve),但是传递给这个函数的是文件描述符,而不是文件的
绝对路径。

memfd_create 是在kernel3.17才被引进来,fexecve是glibc的一
个函数,是在版本2.3.2之后才有的

https://xeldax.top/article/linux_no_file_elf_mem_execute 5/11
04/11/2022, 13:37 Xeldax's Blog - Share it

XELDAX BLOG HOME


ABOUT
OOPS  

关于fexecve用法如下:
1. #include <fcntl.h>
2. #include <stdio.h>
3. #include <stdlib.h>
4. #include <sys/mman.h>
5. #include <sys/stat.h>
6. #include <unistd.h>
7.
8. static char *args[] = {
9. "hic et nunc",
10. "-l",
11. "/dev/shm",
12. NULL
13. };
14.
15. extern char **environ;
16.
17. int main(void)
18. {
19. struct stat st;
20. void *p;
21. int fd, shm_fd, rc;
22.
23. shm_fd = shm_open("wurstverschwendung",
O_RDWR | O_CREAT, 0777);
24. if (shm_fd == -1) {
25. perror("shm_open");
26. exit(1);

https://xeldax.top/article/linux_no_file_elf_mem_execute 6/11
04/11/2022, 13:37 Xeldax's Blog - Share it

27. }
XELDAX BLOG 28. HOME
ABOUT
OOPS  
29. rc = stat("/bin/ls", &st);

30. if (rc == -1) {


31. perror("stat");
32. exit(1);
33. }
34.
35. rc = ftruncate(shm_fd, st.st_size);
36. if (rc == -1) {
37. perror("ftruncate");
38. exit(1);
39. }
40.
41. p = mmap(NULL, st.st_size, PROT_READ |
PROT_WRITE, MAP_SHARED,
42. shm_fd, 0);
43. if (p == MAP_FAILED) {
44. perror("mmap");
45. exit(1);
46. }
47.
48. fd = open("/bin/ls", O_RDONLY, 0);
49. if (fd == -1) {
50. perror("openls");
51. exit(1);
52. }
53.
54. rc = read(fd, p, st.st_size);
55. if (rc == -1) {
56. perror("read");
57. exit(1);
58. }
59. if (rc != st.st_size) {
60. fputs("Strange situation!\n", stderr);
61. exit(1);
62. }
63.
64. munmap(p, st.st_size);
65. close(shm_fd);
66.
67. shm_fd = shm_open("wurstverschwendung",
O_RDONLY, 0);
68. fexecve(shm_fd, args, environ);
69. perror("fexecve");
70. return 0;

https://xeldax.top/article/linux_no_file_elf_mem_execute 7/11
04/11/2022, 13:37 Xeldax's Blog - Share it

71. }
XELDAX BLOG HOME
ABOUT
OOPS  
编译的时候使用gcc -lrt不然会报错,提示找不到shm_open的符

运行以后可以看到执行了ls,当然我们去/dev/shm下也能够看到
这个文件,和memfd一模一样我们能够在bash中执行这个二进

一种GOLANG ELF 内存马


的实现
这是在run embeded elf 上修改的项目,使用asm内联汇编修改
满足golang elf rt0_linux的堆栈空间迁移,然后jmp到rt0_linux入
口点从而实现的内存加载方式。
项目地址如下:
1. https://github.com/merlinxcy/memory_execute_golang_e

推荐工具

https://xeldax.top/article/linux_no_file_elf_mem_execute 8/11
04/11/2022, 13:37 Xeldax's Blog - Share it

RUN-EMBEDDED-ELF-
XELDAX BLOG HOME
ABOUT
OOPS  
FROM-MEMORY

https://github.com/AXDOOMER/run-embedded-elf-from-
memory

FILELESS-XEC
https://github.com/ariary/fileless-xec

FIREELF
https://github.com/rek7/fireELF

GO-MEMFD

https://xeldax.top/article/linux_no_file_elf_mem_execute 9/11
04/11/2022, 13:37 Xeldax's Blog - Share it

https://github.com/justincormack/go-memfd

XELDAX BLOG HOME


ABOUT
OOPS  

MEMFD-EXMAPLE
https://github.com/a-darwish/memfd-examples

MEMRUN
https://github.com/guitmz/memrun

参考资料
参考资料

http://www.suphp.cn/anquanke/4/168204.html

https://b0ldfrev.gitbook.io/note/linux_operating_system/linux-
wu-wen-jian-zhi-hang-elf

https://blog.spoock.com/2019/08/27/elf-in-memory-execution/

https://blog.csdn.net/whatday/article/details/99430757?
utm_medium=distribute.pc_relevant.none-task-blog-
2%7Edefault%7ECTRLIST%7Edefault-
2.no_search_link&depth_1-
utm_source=distribute.pc_relevant.none-task-blog-

https://xeldax.top/article/linux_no_file_elf_mem_execute 10/11
04/11/2022, 13:37 Xeldax's Blog - Share it

2%7Edefault%7ECTRLIST%7Edefault-2.no_search_link

HOME
ABOUT

https://kevien.github.io/2018/02/20/linux%E4%B8%80%E7%A7
XELDAX BLOG OOPS  
%8D%E6%97%A0%E6%96%87%E4%BB%B6%E5%90%8E%

E9%97%A8%E6%8A%80%E5%B7%A7(%E8%AF%91%E6%9
6%87)/

https://cloud.tencent.com/developer/article/1590998

https://www.anquanke.com/post/id/168791#h2-0

https://www.anquanke.com/post/id/168204#h2-1

BINARY
 1978

https://xeldax.top/article/linux_no_file_elf_mem_execute 11/11

You might also like