Skip to content

Instantly share code, notes, and snippets.

@alterakey
Created April 6, 2014 14:51
Show Gist options
  • Save alterakey/10007077 to your computer and use it in GitHub Desktop.
Save alterakey/10007077 to your computer and use it in GitHub Desktop.
An Rudimental ELF Dumper (for my own learning)
/* 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;
}
/* 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