Created
April 6, 2014 14:51
-
-
Save alterakey/10007077 to your computer and use it in GitHub Desktop.
An Rudimental ELF Dumper (for my own learning)
This file contains hidden or 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
/* dumper.c: An rudimental memory dumper for hunting some executable ELF images targetting Linux 2.4 and later on x86, for my own learning project. | |
* Copyright (C) 2014 Takahiro Yoshimura <[email protected]> | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
*/ | |
/* Related works: xocopy [1] and some SO topic [2]. | |
* [1] http://reverse.lostrealm.com/tools/xocopy.html | |
* [2] http://reverseengineering.stackexchange.com/questions/98/how-can-i-analyse-an-executable-with-no-read-permission | |
*/ | |
#include <stdio.h> | |
#include <sys/ptrace.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <sys/user.h> | |
#include <sys/syscall.h> | |
#include <fcntl.h> | |
#include <stdarg.h> | |
#include <sys/mman.h> | |
#define LO_USER 0x00001000UL | |
#define HI_USER 0xc0000000UL | |
/* Type for a 16-bit quantity. */ | |
typedef u_int16_t Elf32_Half; | |
/* Types for signed and unsigned 32-bit quantities. */ | |
typedef u_int32_t Elf32_Word; | |
/* Type of addresses. */ | |
typedef u_int32_t Elf32_Addr; | |
/* Type of file offsets. */ | |
typedef u_int32_t Elf32_Off; | |
#define EI_NIDENT (16) | |
typedef struct | |
{ | |
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ | |
Elf32_Half e_type; /* Object file type */ | |
Elf32_Half e_machine; /* Architecture */ | |
Elf32_Word e_version; /* Object file version */ | |
Elf32_Addr e_entry; /* Entry point virtual address */ | |
Elf32_Off e_phoff; /* Program header table file offset */ | |
Elf32_Off e_shoff; /* Section header table file offset */ | |
Elf32_Word e_flags; /* Processor-specific flags */ | |
Elf32_Half e_ehsize; /* ELF header size in bytes */ | |
Elf32_Half e_phentsize; /* Program header table entry size */ | |
Elf32_Half e_phnum; /* Program header table entry count */ | |
Elf32_Half e_shentsize; /* Section header table entry size */ | |
Elf32_Half e_shnum; /* Section header table entry count */ | |
Elf32_Half e_shstrndx; /* Section header string table index */ | |
} Elf32_Ehdr; | |
#define EI_CLASS 4 /* File class byte index */ | |
#define ELFCLASS32 1 /* 32-bit objects */ | |
/* Legal values for e_type (object file type). */ | |
#define ET_EXEC 2 /* Executable file */ | |
#define ET_DYN 3 /* Shared object file */ | |
/* Program segment header. */ | |
typedef struct | |
{ | |
Elf32_Word p_type; /* Segment type */ | |
Elf32_Off p_offset; /* Segment file offset */ | |
Elf32_Addr p_vaddr; /* Segment virtual address */ | |
Elf32_Addr p_paddr; /* Segment physical address */ | |
Elf32_Word p_filesz; /* Segment size in file */ | |
Elf32_Word p_memsz; /* Segment size in memory */ | |
Elf32_Word p_flags; /* Segment flags */ | |
Elf32_Word p_align; /* Segment alignment */ | |
} Elf32_Phdr; | |
/* Legal values for p_type (segment type). */ | |
#define PT_NULL 0 /* Program header table entry unused */ | |
#define PT_LOAD 1 /* Loadable program segment */ | |
/*----------------------------------------------------------------------------*/ | |
static void panic(const char *msg, ...) { | |
va_list vl; | |
char buf[1024 + 1] = {0}; | |
va_start(vl, msg); | |
vsnprintf(buf, 1024, msg, vl); | |
fprintf(stderr, "[-] %s\n", buf); | |
exit(2); | |
} | |
static int read_text(const int pid, const void *offset, void *buf, int size) { | |
const int words = size / sizeof(unsigned long); | |
for (int i=0; i<words; ++i) { | |
*(((unsigned long *)buf)+i) = ptrace(PTRACE_PEEKTEXT, pid, (((unsigned long *)offset)+i), 0); | |
} | |
return words; | |
} | |
static void *find_elf_header(const int pid, Elf32_Ehdr *out_hdr, const void *from) { | |
const unsigned char hdr[] = "\177ELF"; | |
if (!from) { | |
from = LO_USER; | |
} | |
for (; from<HI_USER; from += PAGE_SIZE) { | |
if (*(unsigned long *)hdr == ptrace(PTRACE_PEEKTEXT, pid, from, 0)) { | |
if (read_text(pid, from, out_hdr, sizeof(*out_hdr))) { | |
if (out_hdr->e_type == ET_DYN) { | |
fprintf(stderr, "[+] found shared object at %p\n", from); | |
return from; | |
} else if (out_hdr->e_type == ET_EXEC) { | |
fprintf(stderr, "[+] found ELF header at %p\n", from); | |
return from; | |
} | |
} | |
} | |
} | |
return 0; | |
} | |
int main(int argc, const char **argv) { | |
pid_t pid; | |
if (argc < 3) { | |
fprintf(stderr, "usage: %s <pages> <target> [args]\n", argv[0]); | |
exit(1); | |
} | |
pid = fork(); | |
if (!pid) { | |
ptrace(PTRACE_TRACEME, 0, NULL, NULL); | |
execv(argv[2], argv+3); | |
} else { | |
int status; | |
int pages = strtol(argv[1], 0, 10); | |
if (!pages) { | |
pages = 4; | |
} | |
wait(&status); | |
if (!WIFEXITED(status)) { | |
Elf32_Ehdr hdr; | |
const void *p = LO_USER; | |
for (p=find_elf_header(pid, &hdr, p); p; p=find_elf_header(pid, &hdr, p + sizeof(Elf32_Ehdr))) { | |
char fn[128 + 1] = ""; | |
snprintf(fn, 128, "dumper_%p.out", p); | |
const int fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); | |
if (fd >= 0) { | |
fprintf(stderr, "[+] dumping %d pages from %p\n", pages, p); | |
for (int page=0; page<pages; ++page) { | |
unsigned char buf[PAGE_SIZE] = {0}; | |
read_text(pid, (((const unsigned char *)p)+page), buf, PAGE_SIZE); | |
write(fd, buf, PAGE_SIZE); | |
} | |
close(fd); | |
} else { | |
perror("[-] open"); | |
exit(2); | |
} | |
} | |
kill(pid, SIGKILL); | |
} | |
} | |
return 0; | |
} |
This file contains hidden or 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
/* test.c: test target. | |
* This file is in public domain. | |
*/ | |
#include <stdio.h> | |
int main() { | |
char buf[128] = { 0 }; | |
printf("Tell your name: "); | |
gets(buf); | |
printf("Hello, %s.\n", buf); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment