2012-05-11 27 views
3

我想分析一個沒有調試信息(Linux)的程序的核心轉儲。分析應該在C中自動完成,所以 GDB。如何從核心轉儲中提取EBP和ESP?

正如我在GDB中看到的,可以通過命令info registers獲取堆棧指針的頂部和堆棧基址指針(ESP和EBP)。當我上下堆棧時(命令updown),我看到當前幀的寄存器的更新版本。

我的問題是,我在哪裏可以在覈心轉儲中找到這些信息?我知道在包含NT_PRSTATUS,NT_PRPSINFO和NT_AUXV的核心轉儲中有一個NOTE部分。但令人遺憾的是,我找不到有關這些筆記的任何信息。 GDB如何構建框架,它從哪裏獲取信息?

回答

5

首先,你需要閱讀ELF規範,然後讀取功能elf_core_dump()在linux/FS/binfmt_elf.c去了解如何核心轉儲文件被組織。但無論如何,你可以檢查下面的程序。

#include <stdio.h> 
#include <elf.h> 
#include <sys/types.h> 
#include <unistd.h> 
#include <fcntl.h> 
#include <stdlib.h> 
#include <sys/procfs.h> 

int main (int argc, char **arg) 
{ 
Elf32_Ehdr *elfh; 
Elf32_Shdr *elfsh; 
Elf32_Phdr *elfphdr; 
char *p = NULL; 
char buf[1000], sbuf[1000]; 
int ret, fd, i = 0, size; 

if (argc < 2) { 
    printf("\nUsage: corenotes <core>\n"); 
    return 0; 
} 

fd = open(arg[1], O_RDONLY); 
if (fd < 0) { 
    perror("open"); 
    return 0; 
} 

/* Read ELF header*/ 
ret = read(fd, buf, sizeof(*elfh)); 
if (!ret) { 
    perror("Error Reading the ELF Header"); 
    goto cl; 
} 
elfh = (Elf32_Ehdr *) buf; 
/* Is it ELF*/ 
if ((elfh->e_ident[0] != 0x7f) || (elfh->e_ident[1] != 'E') || 
    (elfh->e_ident[2] != 'L') || (elfh->e_ident[3] != 'F')) { 
    printf("\nUnrecongised File Format"); 
    goto cl; 
} 

/* 
* read program headers and print 
*/ 
size = elfh->e_phnum * elfh->e_phentsize; 
p = malloc(size); 

lseek(fd, elfh->e_phoff, SEEK_SET); 
ret = read(fd, p, size); 
if (ret != size) { 
    printf("\nCannot read Program Header"); 
    goto cl; 
} 
elfphdr = (Elf32_Phdr *)p; 
for (i = 0; i < elfh->e_phnum; i++) { 
    if (elfphdr->p_type == PT_NOTE) { 
     unsigned char *pdata; 
     struct note { 
      unsigned int namesz; 
      unsigned int descsz; 
      unsigned int type; 
     }; 
     struct note *not; 
     int pad; 

     pdata = malloc(elfphdr->p_filesz); 
     lseek(fd, elfphdr->p_offset, SEEK_SET); 
     ret = read(fd, pdata, elfphdr->p_filesz); 
     not = (struct note *) pdata; 
     printf("\n%s", pdata + sizeof (*not)); 
     pad = 4 - (not->namesz % 4); 
     if (not->type == NT_PRSTATUS) { 
      struct elf_prstatus *prs; 

      prs = (struct elf_prstatus *)(pdata + sizeof(*not) + not->namesz + pad); 
      printf("\nProgram Received %d", prs->pr_cursig); 
      printf("\nPending Signals %08x", prs->pr_sigpend); 
      printf("\nHold Signals %08x", prs->pr_sighold); 
      printf("\nPID of the process %d", prs->pr_pid); 
      printf("\nPPID of the process %d", prs->pr_ppid); 
      printf("\nEBX: %08x", prs->pr_reg[0]); 
      printf("\nECX: %08x", prs->pr_reg[1]); 
      printf("\nEDX: %08x", prs->pr_reg[2]); 
      printf("\nESI: %08x", prs->pr_reg[3]); 
      printf("\nEDI: %08x", prs->pr_reg[4]); 
      printf("\nEBP: %08x", prs->pr_reg[5]); 
      printf("\nEAX: %08x", prs->pr_reg[6]); 
      printf("\nXDS: %08x", prs->pr_reg[7]); 
      printf("\nXES: %08x", prs->pr_reg[8]); 
      printf("\nXFS: %08x", prs->pr_reg[9]); 
      printf("\nXGS: %08x", prs->pr_reg[10]); 
      printf("\nORG_EAX: %08x", prs->pr_reg[11]); 
      printf("\nEIP: %08x", prs->pr_reg[12]); 
      printf("\nECS: %08x", prs->pr_reg[13]); 
      printf("\nEFLAGS: %08x", prs->pr_reg[14]); 
      printf("\nESP: %08x", prs->pr_reg[15]); 
      printf("\nXSS: %08x", prs->pr_reg[16]); 
      pdata = pdata + sizeof(*not) + not->namesz + pad + sizeof(struct elf_prstatus); 
     } 
     not = (struct note *)pdata; 
     if (not->type == NT_PRPSINFO) { 
      struct elf_prpsinfo *prs; 
      printf("\n\nNT_PRPSINF\n"); 
      pad = 4 - (not->namesz % 4); 
      prs = (struct elf_prpsinfo *)(pdata + sizeof(*not) + not->namesz + pad); 
      printf("\nName of the Exe %s", prs->pr_fname); 
     } 
    // free(pdata); 
    } 
    elfphdr++; 
} 
    free(p);  
    printf("\n\n"); 
    cl: 
    close(fd); 
    return 0; 
} 
+0

請在此重現您的答案的相關部分,以便SO用戶不必指望您提供的鏈接上提供的源代碼。 –

+0

大腦,你想要我在這裏粘貼代碼?這是一個很大的代碼,這就是爲什麼我不把它粘貼在這裏。如果這不是問題,我會在這裏粘貼代碼。 – mohanreddykv

+1

是的,在這裏發佈。別擔心,喬爾會拿起存儲賬單。 –