Disinfect.c
/* * = compile: * Gcc-o2 disinfect.c-o disinfect *./disinfect <executable> * * #include <stdarg.h> #include <std lib.h> #include <stdio.h> #include <string.h> #include <stdio.h> #include <unistd.h># Include <sys/types.h> #include <fcntl.h> #include <dirent.h> #include <sys/mman.h> #include <sys/stat.h> #include <elf.h> #include <errno.h>//elf related information typedef struct ELFDESC {ELF64_EHDR *ehdr; ELF64_PHDR *phdr; ELF64_SHDR *shdr; Elf64_addr textvaddr; Elf64_addr datavaddr; Program Head offset ELF64_ADDR Dataoff; size_t TextSize; size_t DataSize; uint8_t *mem; struct STAT st; char *path;} elfdesc_t;//Buffer # define TMP ". Disinfect_file.xyz"//If the Push/ret address is found in the normal x86_64 range//The description is normal/not within the normal range//770cd526 68 00000000 PUSH 0x0//770cd52b C3 retnuint32_t locate_orig_entry (elfdesc_t *elf) {uint32_t I, ENT Ry uint8_t *mem = elf->mem; for (i = 0; i < Elf->st.st_siZe i++) {if (mem[0] = = 0x68 && mem[5] = = 0xc3) {entry = * (uint32_t *) &mem[1]; If (entry >= 0x400000 && entry < 0X4FFFFF) return entry; }}//did not find return 0;} 770cd53a |. 31ED XOR ebp,ebp//770cd53c |. DEC ecx//770cd53d | 89d1 MOV ecx,edx//770cd53f |. 5E POP esi//770cd540 |. DEC eax//770cd541 | 89E2 MOV edx,espuint32_t locate_glibc_init_offset (elfdesc_t *elf) {uint32_t i; uint8_t *mem = elf->mem; for (i = 0; i < elf->st.st_size; i++) {if (mem[i + 0] = = 0x31 && mem[i + 1] = = 0xed &&am P Mem[i + 2] = = 0x49 && mem[i + 3] = = 0x89 && mem[i + 4] = = 0xd1 && mem[i + 5] = = 0x5e && Amp Mem[i + 6] = = 0x48 && mem[i + 7] = = 0x89 && mem[i + 8] = = 0xe2) return i; } return 0;} Remove Plt/got Hooksint Disinfect_pltgot (elfdesc_t *elf) {//file header Elf64_ehdr *ehdr = elf->ehdr; Program Head ELF64_PHDR *PHDR = elf->phdr; Section table header Elf64_shdr *SHDR = elf->shdr; Map base uint8_t *mem = elf->mem; Dynamic library symbol table Base Elf64_sym *symtab = NULL; Reposition Table Elf64_rela *rela = NULL; Elf64_addr Addr = 0, plt_addr = 0; Elf64_off plt_off = 0, Gotoff = 0; size_t plt_size = 0, symtab_size = 0, rela_size = 0; string table Base Address char *shstrtab = (char *) &mem[shdr[elf->ehdr->e_shstrndx].sh_offset]; char *strtab = NULL; uint8_t *gotptr, *PLT; int I, j, Symindex = 0, c = 0; Iterate through all section tables for (i = 0; i < ehdr->e_shnum; i++) {//Type switch (shdr[i].sh_type) {//Dynamic library symbols Case SHT_DYNSYM://symbol table Symtab = (Elf64_sym *) &mem[shdr[i].sh_offset]; Symtab_size = shdr[i].sh_size; For the symbol table segment, the Sh_link record is the list of strings used by the symbol table (typically. strtab) the index//.strtab offset of the corresponding segment table entry within the segment table Strtab = (char *) &mem[shdr[shdr[i].sh_link].sh_offset]; Break Reposition the section Table index of the section used Case Sht_rela:if (!STRCMP (&shstrtab[shdr[i].sh_name], ". Rela.plt")) { Reposition Table RelA = (Elf64_rela *) &mem[shdr[i].sh_offset]; Size rela_size = shdr[i].sh_size; } break; Program Data Case Sht_progbits:if (!STRCMP (&shstrtab[shdr[i].sh_name], ". Plt")) { PLT-related plt_off = Shdr[i].sh_offset; PLT_ADDR = shdr[i].sh_addr; Plt_size = shdr[i].sh_size; } break; }} if (Plt_off = = 0 | | symtab = = NULL | | rela = = NULL) {printf ("not found RELOCATION/SYMBOL/PLT info!!! \ n "); return-1; }//First PLT address PLT = &mem[plt_off]; Traverse all relocation table entries for (i = 0; i < rela_size/sizeof (Elf64_rela); i++) {//High 24-bit indicates that the reposition symbol corresponding symbol table entry has an index within the symbol table Symindex = Elf64_r_sym (Rela->r_info); Find the puts function symbol if (!strcmp (&strtab[symtab[elf64_r_sym (Rela->r_info)].st_name], "puts") in Symtab {p rintf ("Try disinfecting plt/got!!! \ n "); Gotoff = Elf->dataoff + (RELA->R_OFFSET-ELF->DATAVADDR); Gotptr = &mem[gotoff]; Addr = gotptr[0] + (Gotptr[1] << 8) + (Gotptr[2] << +) + (Gotptr[3] << 24); if (! ( Addr >= plt_addr && Addr < plt_addr + plt_size) {for (c = 0, j = 0; J < plt_size; J + = 1 6, C + +) {//Determine index number if (c = = Symindex) {printf ("Successfully disinfect Plt/got table! !! \ n "); * (uint32_t *) Gotptr = plt_addr + j + 6; return 0; }}} printf ("Plt/got table detoxification failed!!!" \ n "); return-1; }} return 0;} Try to disinfect the general 64-bit codeLoad base address for 0x400000int disinfect (elfdesc_t *elf) {size_t paddingsize; Elf64_phdr *PHDR = elf->phdr; Elf64_shdr *SHDR = elf->shdr; uint32_t text_offset = 0; char *strtab = NULL; uint8_t *mem = elf->mem; int i, Textfound, FD; ssize_t c, Last_chunk; If it is greater than 0x400000 if (elf->textvaddr >= 0x400000) {printf ("Not the feature you want to eliminate!!! \ n "); return-1; }//0x400000-the base address of the code snippet (reverse text technology for viruses)//calculate difference paddingsize = 0x400000-elf->textvaddr; If a hook is present, remove int ret = Disinfect_pltgot (ELF); Remove Magic Marker * (uint32_t *) &elf->ehdr->e_ident[ei_pad] = 0x00000000; PT_PHDR, Pt_interp forward phdr[0].p_offset-= paddingsize; Phdr[1].p_offset-= paddingsize; PhDr set back to normal for (Textfound = 0, i = 0; i < elf->ehdr->e_phnum; i++) {if (textfound) {phdr[ I].p_offset-= paddingsize; Continue } if (Phdr[i].p_type = = Pt_load && Phdr[i].p_offset = = 0 && phdr[i].p_flags & pf_x) {if (phdr[i].p_paddr = = phdr[i].p_vaddr) {phdr[i].p_vaddr + = paddingsize; Phdr[i].p_paddr + = Paddingsize; } else phdr[i].p_vaddr + = paddingsize; Resets the text segment size Phdr[i].p_filesz-= paddingsize; Phdr[i].p_memsz-= paddingsize; Phdr[i].p_align = 0x200000; Phdr[i + 1].p_align = 0x200000; Textfound = 1; }}//Offset Text_offset = Locate_glibc_init_offset (elf); Correction section Table Strtab = (char *) &mem[shdr[elf->ehdr->e_shstrndx].sh_offset]; for (i = 0; i < elf->ehdr->e_shnum; i++) {//As long as the infected part code is processed if (!strcmp (&strtab[shdr[i].sh_name], " . Text ")) {//remain unchanged if (Text_offset = = 0) continue; Shdr[i].sh_offset = text_offset-paddingsize; Shdr[i].sh_addr = (text_offset-paddingsize) + 0x400000; Continue } Shdr[i].sh_offset-= PaddiNgsize; }//Set PHDR and SHDR table Elf->ehdr->e_shoff-= paddingsize; Elf->ehdr->e_phoff-= paddingsize; Set back to normal oep elf->ehdr->e_entry = 0x400000 + text_offset; Elf->ehdr->e_entry-= paddingsize; Rebuilding elf if (fd = open (TMP, O_creat | O_trunc | O_wronly, Elf->st.st_mode)) < 0) return-1; if (c = Write (fd, mem, sizeof (ELF64_EHDR)))! = sizeof (ELF64_EHDR)) return-1; Mem + = paddingsize + sizeof (ELF64_EHDR); Last_chunk = elf->st.st_size-(paddingsize + sizeof (ELF64_EHDR)); if (c = Write (FD, mem, last_chunk))! = Last_chunk) return-1; if (Fchown (FD, Elf->st.st_uid, Elf->st.st_gid) < 0) return-1; Rename rename (TMP, Elf->path); return 0;} Load file int load_executable (const char *path, elfdesc_t *elf) {uint8_t *mem; ELF64_EHDR *ehdr; ELF64_PHDR *phdr; ELF64_SHDR *shdr; int FD; struct STAT st; int i; if (fd = open (path, o_rdonly)) < 0) {perror("open"); return-1; } fstat (FD, &st); MEM = mmap (NULL, St.st_size, prot_read| Prot_write, Map_private, FD, 0); if (mem = = map_failed) {perror ("mmap"); return-1; } EHDR = (ELF64_EHDR *) mem; PHDR = (ELF64_PHDR *) &mem[ehdr->e_phoff]; SHDR = (ELF64_SHDR *) &mem[ehdr->e_shoff]; elf->st = st; In order to find the code segment offset by 0 for (i = 0; i < ehdr->e_phnum; i++) {//not 0 for 1 0 or 0 switch (!!). Phdr[i].p_offset) {Case 0:elf->textvaddr = phdr[i].p_vaddr; Elf->textsize = Phdr[i].p_filesz; Break Case 1:elf->dataoff = Phdr[i].p_offset; ELF->DATAVADDR = phdr[i].p_vaddr; Elf->datasize = Phdr[i].p_filesz; Break }} elf->mem = mem; ELF->EHDR = EHDR; ELF->PHDR = PHDR; ELF->SHDR = SHDR; Elf->path = (char *) path; return 0;} Check if it is a virus int Test_for_skEksi (elfdesc_t *elf) {uint32_t Magic = * (uint32_t *) &elf->ehdr->e_ident[EI_PAD]; return (Magic = = 0X15D25); }int Main (int argc, char **argv) {elfdesc_t elf; if (ARGC < 2) {printf ("Usage:%s <executable>\n", argv[0]); Exit (0); }//Load Elf simultaneously save relevant information if (Load_executable (argv[1], &elf) < 0) {printf ("Load failed:%s\n", argv[1]); Exit (-1); }//Check for virus if (test_for_skeksi (&elf) = = 0) {printf ("File:%s, no infection virus\n", argv[1]); Exit (-1); } printf ("File:%s", already infected virus! Try Disinfection! \ n ", argv[1]); if (Disinfect (&elf) < 0) {printf ("Disinfection failed file:%s\n", argv[1]); Exit (-1); } printf ("Disinfection success:%s\n", argv[1]);}
Linux virus virus detoxification