我正在尝试进行一个小实验,它基本上包括更改 ELF 文件的 EP 和执行 exit(9) 系统调用,而不返回到 OEP。如图所示,一切似乎都很好
但是,当我运行原始程序时,它会出现段错误而不是通过exit(9) 退出,我不知道为什么。这里到底发生了什么?
编辑: 这是我如何更改入口点:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <elf.h>
#include <stdint.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define INVALID_IDX -32
#define PAGE_SIZE 4096
int check_elf(uint8_t *, char **);
// exit(9)
unsigned char shellcode[] = "\x48\x31\xc0"
"\xb0\x3c"
"\x40\xb7\x09"
"\x0f\x05";
unsigned char nop_sled[] = "\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90"
"\x90\x90\xcc\x90\x90"
"\x90\x90\x90\x90\x90";
int main(int argc, char **argv)
{
int fd, i;
uint8_t *mapped_file;
struct stat st;
char *interp;
int magic = 1337;
Elf64_Ehdr *ehdr = NULL;
Elf64_Phdr *phdr = NULL;
Elf64_Shdr *shdr = NULL;
if (argc < 2)
{
printf("Usage: %s <executable>\n", argv[0]);
exit(EXIT_SUCCESS);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
{
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &st) < 0)
{
perror("fstat");
exit(EXIT_FAILURE);
}
/* map whole executable into memory */
mapped_file = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_file < 0)
{
perror("mmap");
exit(EXIT_FAILURE);
}
check_elf(mapped_file, argv);
ehdr = (Elf64_Ehdr *) mapped_file;
phdr = (Elf64_Phdr *) &mapped_file[ehdr->e_phoff];
shdr = (Elf64_Shdr *) &mapped_file[ehdr->e_shoff];
if (ehdr->e_type != ET_EXEC)
{
fprintf(stderr, "%s is not an ELF executable.\n", argv[1]);
exit(EXIT_FAILURE);
}
printf("Program entry point: %08x\n", ehdr->e_entry);
char jmp_code[7];
int text_found = 0;
uint64_t parasite_addr;
uint64_t text_end;
size_t parasite_len = strlen(shellcode);
int text_idx = INVALID_IDX;
for (i = 0; i < ehdr->e_phnum; ++i)
{
if (text_found)
{
phdr[i].p_offset += PAGE_SIZE;
continue;
}
if (phdr[i].p_type == PT_LOAD && phdr[i].p_flags == ( PF_R | PF_X))
{
// set parasite to the end of the text segment
parasite_addr = phdr[i].p_vaddr + phdr[i].p_filesz;
text_end = phdr[i].p_vaddr + phdr[i].p_filesz;
printf("TEXT SEGMENT ends at 0x%x\n", text_end);
text_idx = i;
puts("Changing entry point...");
ehdr->e_entry = (Elf64_Addr)parasite_addr;
memmove(mapped_file + phdr[i].p_offset + phdr[i].p_filesz,
shellcode, parasite_len);
phdr[i].p_filesz += parasite_len;
phdr[i].p_memsz += parasite_len;
text_found++;
}
}
//patch sections
for (i = 0; i < ehdr->e_shnum; ++i)
{
if (shdr->sh_offset >= parasite_addr)
shdr->sh_offset += PAGE_SIZE;
else
if (shdr->sh_size + shdr->sh_addr == parasite_addr)
shdr->sh_size += parasite_len;
}
ehdr->e_shoff += PAGE_SIZE;
close(fd);
}
int check_elf(uint8_t *mapped_file, char **argv)
{
const uint8_t magic[] = {0x7F, 'E', 'L', 'F'};
if (memcmp(magic, mapped_file, sizeof(magic)))
{
fprintf(stderr, "%s is not an ELF file.\n", argv[1]);
exit(EXIT_FAILURE);
}
return 1;
}
至于我试图更改其入口点的程序,它只是一个简单的 hello world。