最后利用xocopy把可执行代码dump出来
gcc xocopy.c -o xocopy -m32 ./xocopy /utumno/utumno0 ./xocopy -a 0x08049000 /utumno/utumno0 objdump -D utumno0.out (Disassembly of section .rodata:) 080484b8 <.rodata>: 80484b8: 03 00 add (%eax),%eax 80484ba: 00 00 add %al,(%eax) 80484bc: 01 00 add %eax,(%eax) 80484be: 02 00 add (%eax),%al "aathaeyiew" 80484c0: 61 popa 80484c1: 61 popa 80484c2: 74 68 je 804852c <__libc_start_main@plt+0x23c> 80484c4: 61 popa 80484c5: 65 gs 80484c6: 79 69 jns 8048531 <__libc_start_main@plt+0x241> 80484c8: 65 gs 80484c9: 77 00 ja 80484cb <__libc_start_main@plt+0x1db> "Read me! :P" 80484cb: 52 push %edx 80484cc: 65 gs 80484cd: 61 popa 80484ce: 64 20 6d 65 and %ch,%fs:0x65(%ebp) 80484d2: 21 20 and %esp,(%eax) 80484d4: 3a 50 00 cmp 0x0(%eax),%dl到这里应该算就结束了,下面再介绍一种方法来解这一题
#define _GNU_SOURCE #include <stdio.h> #include <stdint.h> #include <dlfcn.h> int puts(const char *s) { int i; char *pt; // Variable to store the original puts function. just incase we need it. static void* (*my_puts)(const char*s) = NULL; if (!my_puts){ // Store the original puts function. my_puts = dlsym(RTLD_NEXT, "puts"); } // Start looking at stack addresses printf("%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x-"); // Display our hooked printf("Hooked-%s", s); // Run through the memory space. for( i = 0x804841a; i < 0x80484cb; i++) { pt = i; printf("%c", *pt); printf(""); } return 0; }
gcc -m32 -fPIC -c hookputs.c ld -shared -m elf_i386 -o hookputs.so hookputs.o -ldl objdump -d hookputs.so Disassembly of section .text: 00000240 <puts>: 240: 55 push %ebp 241: 89 e5 mov %esp,%ebp 243: 53 push %ebx 244: 83 ec 24 sub $0x24,%esp那么进入puts时的栈环境是
root@today:~/Desktop/utumno/utumno0# ssh utumno0@178.79.134.250 utumno0@178.79.134.250's password: utumno0 utumno0@melinda:~$ cd /tmp/utumno0 utumno0@melinda:/tmp/utumno0$ gcc -m32 -fPIC -c hookputs.c utumno0@melinda:/tmp/utumno0$ ld -shared -m elf_i386 -o hookputs.so hookputs.o -ldl utumno0@melinda:/tmp/utumno0$ LD_PRELOAD="./hookputs.so" ltrace /utumno/utumno0 ERROR: ld.so: object './hookputs.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored. failed to initialize process 24891: No such file or directory couldn't open program '/utumno/utumno0': No such file or directory utumno0@melinda:/tmp/utumno0$ f7fd52c0-0-0-ffffd5d8-f7ff0500-ffffd604-f7fd5210-1-f7fc9000-ffffd5d8-804841a-80484cb--- ffffd674-ffffd67c-f7e5510d-f7fc93c4-f7ffd000-804843b-80484c0Hooked-Read me! :Pffffffb8(?) 00() 00() 00() 00() ffffffc9(?) ffffffc3(?) 66(f) ffffff90(?) 66(f) ffffff90(?) 66(f) ffffff90(?) 66(f) ffffff90(?) 66(f) ffffff90(?) 66(f) ffffff90(?) 66(f) ffffff90(?) ffffff90(?) 55(U) 57(W) 31(1) ffffffff(?) 56(V) 53(S) ffffffe8(?) fffffff5(?) fffffffe(?) ffffffff(?) ffffffff(?) ffffff81(?) ffffffc3(?) 71(q) 12() 00() 00() ffffff83(?) ffffffec(?) 1c() ffffff8b(?) 6c(l) 24($) 30(0) ffffff8d(?) ffffffb3(?) 0c(...) ffffffff(?) ffffffff(?) ffffffff(?) ffffffe8(?) 3d(=) fffffffe(?) ffffffff(?) ffffffff(?) ffffff8d(?) ffffff83(?) 08) ffffffff(?) ffffffff(?) ffffffff(?) 29()) ffffffc6(?) ffffffc1(?) fffffffe(?) 02() ffffff85(?) fffffff6(?) 74(t) 27(') ffffff8d(?) ffffffb6(?) 00() 00() 00() 00() ffffff8b(?) 44(D) 24($) 38(8) ffffff89(?) 2c(,) 24($) ffffff89(?) 44(D) 24($) 08) ffffff8b(?) 44(D) 24($) 34(4) ffffff89(?) 44(D) 24($) 04() ffffffff(?) ffffff94(?) ffffffbb(?) 08) ffffffff(?) ffffffff(?) ffffffff(?) ffffff83(?) ffffffc7(?) 01() 39(9) fffffff7(?) 75() ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) ffffff90(?) fffffff3(?) ffffffc3(?) 00() 00() 53(S) ffffff83(?) ffffffec(?) 08) ffffffe8(?) ffffff83(?) fffffffe(?) ffffffff(?) ffffffff(?) ffffff81(?) ffffffc3(?) ffffffff(?) 11() 00() 00() ffffff83(?) ffffffc4(?) 08) 5b([) ffffffc3(?) 03() 00() 00() 00() 01() 00() 02() 00() 61(a) 61(a) 74(t) 68(h) 61(a) 65(e) 79(y) 69(i) 65(e) 77(w) 00()
xocopy.c
/* xocopy - Program for copying an executable with execute but no read perms. * Copyright (C) 2002, 2003 Dion Mendel. * * 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. */ /* * A simple program to obtain a readable copy of an executable which has * execute, but no read permission. It works by executing the process * - to load the process into memory - then dumping the memory image. * * Does not work for suid apps under linux 2.2.x. * Only works for elf files for which the elf header and program header table * are part of the loadable text segment (default for gcc). * * Generally, any data that appears in the file after loadable segments that * extend their size (usually shdr) will not be recovered. * * NOTE: This is a proof of concept program. It is not robust. * NOTE: Does not work on linux kernels between 2.4.21-pre6 .. 2.4.21-rc2 * due to an incorrect ptrace patch being applied to those kernels. */ /* undefine this if there is no elf.h file on the system */ #define HAVE_ELF_H #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <signal.h> #ifdef HAVE_ELF_H # include <elf.h> #endif #include <sys/types.h> #include <sys/ptrace.h> #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h> /*----------------------------------------------------------------------------*/ #ifdef __FreeBSD__ # define PTRACE_PEEKTEXT PT_READ_I # define PTRACE_PEEKDATA PT_READ_D # define PTRACE_TRACEME PT_TRACE_ME # define PTRACE_KILL PT_KILL #endif /* __FreeBSD__ */ /*----------------------------- ELF Definition -------------------------------*/ #ifndef HAVE_ELF_H /* 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; /* The ELF file header. This appears at the start of every ELF file. */ #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 */ #endif /* Elf Definition */ /*----------------------------------------------------------------------------*/ /* this is the word datatype returned by ptrace for PEEK* */ #define PTRACE_WORD int32_t /* * PAGE_SIZE - the size of a memory page * LO_USER - the lowest address accessible from user space (% PAGE_SIZE) * HI_USER - the highest address accessible from user space (% PAGE_SIZE) */ #if defined (__linux__) # define PAGE_SIZE 4096U # define LO_USER 4096U # define HI_USER 0xc0000000U #elif defined (__FreeBSD__) # define PAGE_SIZE 4096U # define LO_USER 4096U # define HI_USER 0xbfc00000U #else ERROR UNKNOWN OPERATING SYSTEM #endif #define PAGE_MASK (~(PAGE_SIZE-1)) /* ---------------- useful functions possibly found in libc ---------------- */ static char * basename (char *pathname) { char *ptr; ptr = strrchr(pathname, '/'); return ptr ? ptr + 1 : pathname; } static int tolower (int c) { if ('A' <= c && c <= 'Z') return c + 'a' - 'A'; return c; } /* * Reads a given number of bytes from the text segment. * num_bytes must be a multiple of the word size */ static int read_text_segment (pid_t pid, unsigned int addr, char *buf, size_t num_bytes) { int i; int num_words; /* determine number of words required to read num_bytes */ num_words = num_bytes / sizeof(PTRACE_WORD); if ((num_bytes % sizeof(PTRACE_WORD)) != 0) num_words++; for (i = 0; i < num_words; i++) { *(((PTRACE_WORD *) buf) + i ) = ptrace(PTRACE_PEEKTEXT, pid, addr + i * sizeof(PTRACE_WORD), 0); if (errno != 0) { char msg[1024]; snprintf(msg, sizeof(msg), "ptrace(PTRACE_PEEKTEXT, pid, 0x%08x, 0)", addr + i * sizeof(PTRACE_WORD)); perror(msg); return 0; } } return 1; } /*---------------------------------------------------------------------------*/ #define LO_PAGE_ADDR(phdr) ((phdr)->p_offset & PAGE_MASK) #define HI_PAGE_ADDR(phdr) (((phdr)->p_offset + ((phdr)->p_filesz) + PAGE_SIZE - 1) & PAGE_MASK) #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define INTERSECTS(off1, size1, off2, size2) ( ((off1) < (off2)) ? ((off2) < (off1) + (size1)) : ((off1) < ((off2) + (size2))) ) /* * Prints warning message for the bytes in the file that couldn't be recovered. * Uses 0/0 for offset/size to signal end of all lost data. */ static void warn_lost_data (pid_t pid, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, unsigned int offset, unsigned int size) { static unsigned int last_offset = 0; /* for recording last offset */ static unsigned int last_size = 0; /* and size - initialised to zero */ int p; if (offset != 0 && size != 0) { if ((last_offset + last_size) == offset) { /* join offsets */ last_size += size; return; } } if (last_offset != 0 && last_size != 0) { fprintf(stderr, "could not recover data - %d bytes at file offset %d\n", last_size, last_offset); for (p = 0; p < ehdr->e_phnum; p++) { if (phdr[p].p_type != PT_NULL) { if (INTERSECTS(last_offset, last_size, phdr[p].p_offset, phdr[p].p_filesz)) { fprintf(stderr, " ! data from phdr[%d] was not recovered\n", p); } } } if ((ehdr->e_shnum != 0) && INTERSECTS(last_offset, last_size, ehdr->e_shoff, ehdr->e_shnum * ehdr->e_shentsize)) { fprintf(stderr, " ! section header table was not recovered\n"); } } /* record this offset and size */ last_offset = offset; last_size = size; } /* * Writes the memory pages to the given filename. Requires that ehdr and phdr * are in loaded memory. */ static int create_file (char *filename, pid_t pid, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, size_t file_size) { FILE *fptr; Elf32_Phdr *this_phdr; char page[PAGE_SIZE]; int i, p; int num_pages; unsigned int *pages; unsigned int end_segment_address; int okay, last_page; num_pages = (file_size + PAGE_SIZE - 1) / PAGE_SIZE; pages = malloc(num_pages * sizeof(*pages)); if (pages == NULL) { fprintf(stderr, "malloc failed\n"); return 0; } /* map memory pages to position in file */ for (i = 0; i < num_pages; i++) { pages[i] = 0; for (p = 0; p < ehdr->e_phnum; p++) { this_phdr = &phdr[p]; if (this_phdr->p_type == PT_LOAD) { if (LO_PAGE_ADDR(this_phdr) <= (i * PAGE_SIZE) && ((i + 1) * PAGE_SIZE) <= HI_PAGE_ADDR(this_phdr)) { /* check for lost data in the last page of the segment */ end_segment_address = this_phdr->p_offset + this_phdr->p_filesz; last_page = end_segment_address < ((i + 1) * PAGE_SIZE); if (last_page && (this_phdr->p_memsz > this_phdr->p_filesz)) { warn_lost_data(pid, ehdr, phdr, end_segment_address, ((i + 1) * PAGE_SIZE) - end_segment_address); } pages[i] = phdr[p].p_vaddr - phdr[p].p_offset + (i * PAGE_SIZE); break; } } } /* warn about lost data if no memory page maps to file */ if (pages[i] == 0) warn_lost_data(pid, ehdr, phdr, i * PAGE_SIZE, PAGE_SIZE); } /* signal that an attempt to recover all pages has been made */ warn_lost_data(pid, ehdr, phdr, 0, 0); /* write memory pages to file */ okay = 0; if ( (fptr = fopen(filename, "wb")) != NULL) { for (i = 0; i < num_pages; i++) { if (pages[i] != 0) { if (! read_text_segment(pid, pages[i], page, PAGE_SIZE)) { fclose(fptr); free(pages); return 0; } } else { memset(page, '\0', PAGE_SIZE); } fwrite(page, 1, MIN(file_size, PAGE_SIZE), fptr); file_size -= PAGE_SIZE; } fclose(fptr); okay = 1; } else { char msg[1024]; snprintf(msg, sizeof(msg), "couldn't create file `%s'", filename); perror(msg); } free(pages); return okay; } /* * Error check before writing the memory pages to disk. */ static int save_to_file (char *filename, pid_t pid, unsigned int addr, size_t file_size) { char page[PAGE_SIZE]; Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; int okay; okay = 0; if (read_text_segment(pid, addr, page, PAGE_SIZE)) { /* ensure 32bit elf binary */ ehdr = (Elf32_Ehdr *) page; if (page[EI_CLASS] == ELFCLASS32 && ehdr->e_type == ET_EXEC) { /* ensure program header table is in same page as elf header */ if ((ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize) < PAGE_SIZE) { phdr = (Elf32_Phdr *) (page + ehdr->e_phoff); okay = create_file(filename, pid, ehdr, phdr, file_size); } else { fprintf(stderr, "program header table could not be found\n"); } } else { fprintf(stderr, "no 32bit elf executable, found at addr 0x%08x\n", addr); } } return okay; } #define NUM_ELF_HEADERS 10 /* * Searches memory for an elf header. */ static unsigned int find_elf_header (pid_t pid) { int i; char *elf_hdr = "\177ELF"; Elf32_Ehdr hdr; unsigned int possible[NUM_ELF_HEADERS]; int num_possible; unsigned int addr; PTRACE_WORD word; int found_elf_header; num_possible = 0; /* search each page to see if elf header is found */ for (addr = LO_USER; addr < HI_USER; addr += PAGE_SIZE) { found_elf_header = 0; word = ptrace(PTRACE_PEEKTEXT, pid, addr, 0); if ((errno == 0) && (word == *((PTRACE_WORD *) elf_hdr))) { if (read_text_segment(pid, addr, (char *) &hdr, sizeof(hdr))) { if (hdr.e_type == ET_EXEC) found_elf_header = 1; else if (hdr.e_type == ET_DYN) fprintf(stderr, "discarding shared library at " "virtual memory address 0x%08x\n", addr); } } if (found_elf_header) { if (num_possible == NUM_ELF_HEADERS) { fprintf(stderr, "too many possible elf headers found (> %d)\n", NUM_ELF_HEADERS); return 0; } possible[num_possible] = addr; num_possible++; } } if (num_possible == 0) { /* no elf header found */ return 0; } else if (num_possible == 1) { /* a single elf header was found */ fprintf(stdout, "using elf header at virtual memory address " " 0x%08x\n", possible[0]); return possible[0]; } else { /* need to resolve conflicts - let user decide */ fprintf(stderr, "multiple elf headers found:\n"); for (i = 0; i < num_possible; i++) { printf(" 0x%08x\n", possible[i]); } return 0; } } int main (int argc, char *argv[]) { char *filename; char out_filename[8192]; char buf[1024]; struct stat stat_buf; pid_t pid; int status; int ret_val; size_t file_size; unsigned int addr; int bad_usage; filename = NULL; addr = 0; /* process args: assigning values to bad_usage filename and possibly addr */ bad_usage = 1; if (argc == 2) { filename = argv[1]; bad_usage = 0; } else if (argc == 4) { filename = argv[3]; if (strcmp(argv[1], "-a") == 0) { if ((argv[2][0] == '0') && (tolower(argv[2][1]) == 'x')) addr = strtol(argv[2], NULL, 16); else addr = strtol(argv[2], NULL, 10); if (errno != ERANGE) bad_usage = 0; } } if (bad_usage) { fprintf(stderr, "Obtains an executable copy of a binary with execute " "but no read permission\n" "Usage: %s [-a addr] <file>\n" " where addr is the memory address of the elf header\n", argv[0]); exit(EXIT_FAILURE); } if (stat(filename, &stat_buf) != 0) { snprintf(buf, sizeof(buf), "couldn't stat file `%s'", filename); perror(buf); exit(EXIT_FAILURE); } /* remember file size of original file */ file_size = stat_buf.st_size; if ( (pid = fork()) == 0) { /* child */ if (ptrace(PTRACE_TRACEME, 0, 0, 0) == 0) { execl(filename, filename, NULL); snprintf(buf, sizeof(buf), "couldn't exec `%s'", filename); perror(buf); } else { perror("ptrace(PTRACE_TRACEME, ...)"); } _exit(EXIT_FAILURE); } ret_val = EXIT_FAILURE; if (waitpid(pid, &status, WUNTRACED) == pid) { if (!WIFEXITED(status)) { /* SIGTRAP is delivered to child after execve */ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { if (addr == 0) addr = find_elf_header(pid); if (addr != 0) { snprintf(out_filename, sizeof(out_filename), "%s.out", basename(filename)); if (save_to_file(out_filename, pid, addr, file_size)) { chmod(out_filename, 00755); fprintf(stdout, "created file `%s'\n", out_filename); ret_val = EXIT_SUCCESS; } } else { fprintf(stderr, "couldn't find elf header in memory\n"); } } else { fprintf(stderr, "didn't receive SIGTRAP after execve\n"); } /* kill child as we are finished */ ptrace(PTRACE_KILL, pid, 0, 0); } } else { perror("waitpid"); } return(ret_val); }
原文:http://blog.csdn.net/shuimuyq/article/details/51082602