Chinaunix首页 | 论坛 | 博客
  • 博客访问: 192532
  • 博文数量: 38
  • 博客积分: 2010
  • 博客等级: 大尉
  • 技术积分: 424
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-19 12:41
文章分类

全部博文(38)

文章存档

2017年(2)

2016年(1)

2010年(8)

2009年(27)

我的朋友

分类: LINUX

2009-10-13 20:15:51

这个程序用C语言分析实现了elf的header以及section header, 最后找出自定义section里面的内容。
自定义section的方法我已经在上一篇“linux elf文件格式学习心得”中讲解了。
源代码如下:
/*****************************************************************************
 * include header file
 *****************************************************************************/
#include
#include
#include   /* elf header file */
#include

/*****************************************************************************
 * define value block
 *****************************************************************************/
#define APP_FILE_NAME       "selfsection"
#define APP_SELFDEF_SECTION "selfsection"
#define START_TAG           "SELFDEF_SECTION"

/*****************************************************************************
 * function block
 *****************************************************************************/
static int Read_Ushort(FILE *fp, unsigned short *value)
{
    unsigned char lsb = 0;
    unsigned char msb = 0;
   
    if(fp == NULL)
    {
        return -1;
    }
    msb = (unsigned char)fgetc(fp);
    lsb = (unsigned char)fgetc(fp);
    *value = lsb;
    *value = ((*value) << 8) | msb;
    return 0;
}

static int Read_Ulong(FILE *fp, unsigned long *value)
{
    unsigned char lsb0,lsb1 = 0;
    unsigned char msb0,msb1 = 0;
   
    if(fp == NULL)
    {
        return -1;
    }
   
    msb0 = (unsigned char)fgetc(fp);
    msb1 = (unsigned char)fgetc(fp);
    lsb0 = (unsigned char)fgetc(fp);
    lsb1 = (unsigned char)fgetc(fp);
    *value = lsb1;
    *value = ((*value) << 8) | lsb0;
    *value = ((*value) << 8) | msb1;
    *value = ((*value) << 8) | msb0;
    return 0;
   
}

static int Read_Elf_Ehdr(FILE* fp, Elf32_Ehdr *ehdr)
{
    fread(&ehdr->e_ident,16,1,fp);
    Read_Ushort(fp,&ehdr->e_type);
    Read_Ushort(fp,&ehdr->e_machine);
    Read_Ulong(fp,&ehdr->e_version);
    Read_Ulong(fp,&ehdr->e_entry);
    Read_Ulong(fp, &ehdr->e_phoff);
    Read_Ulong(fp,&ehdr->e_shoff);
    Read_Ulong(fp,&ehdr->e_flags);
    Read_Ushort(fp,&ehdr->e_ehsize);
    Read_Ushort(fp,&ehdr->e_phentsize);
    Read_Ushort(fp,&ehdr->e_phnum);
    Read_Ushort(fp,&ehdr->e_shentsize);
    Read_Ushort(fp,&ehdr->e_shnum);
    Read_Ushort(fp,&ehdr->e_shstrndx);
   
    return 0;
}

static int get_section_info(FILE* fp, Elf32_Shdr *sHdr)
{
    Read_Ulong(fp, &sHdr->sh_name);
    Read_Ulong(fp, &sHdr->sh_type);
    Read_Ulong(fp, &sHdr->sh_flags);
    Read_Ulong(fp, &sHdr->sh_addr);
    Read_Ulong(fp, &sHdr->sh_offset);
    Read_Ulong(fp, &sHdr->sh_size);
    Read_Ulong(fp, &sHdr->sh_link);
    Read_Ulong(fp, &sHdr->sh_info);
    Read_Ulong(fp, &sHdr->sh_addralign);
    Read_Ulong(fp, &sHdr->sh_entsize);
   
    return 0;
}

int chk_self_def_section(FILE *fp, Elf32_Off sh_offset)
{
    unsigned char szBuf[strlen(START_TAG)];
    memset(szBuf, 0, sizeof(szBuf));
    fseek(fp, sh_offset, SEEK_SET);
    fread(szBuf, strlen(START_TAG), 1, fp);
    printf("#######################offset =%x\n", sh_offset);
    if(sh_offset == 0x6e8)
        printf("len=%d, szBuf=%s\n", strlen(START_TAG), szBuf);
   
    if(strncmp(szBuf, START_TAG, strlen(START_TAG)) == 0)
    {
        return 0;
    }
   
    return -1;
}
static void process_app_info(FILE *fp, Elf32_Shdr *section)
{
    unsigned char szBuf[1024];

    rewind(fp);
    fseek(fp, section->sh_offset, SEEK_SET);
    memset(szBuf, 0, sizeof(szBuf));
    fread(szBuf, section->sh_size, 1, fp);
    printf("%s\n", szBuf);
}

int main(void)
{
    int i                   = 0;
    int nRet                = 0;
 int strtab_cnt          = 0;
 int strtab_idx          = 0;
 int selfdef_section_idx = 0;
 Elf32_Ehdr elfFHeader;
    Elf32_Shdr section; /* define one section structure */
 FILE *fp;
 
 fp = fopen(APP_FILE_NAME, "rb");
 if(fp == NULL)
 {
  printf("error open file\n");
  return -1;
 }
 memset(&elfFHeader, 0, sizeof(Elf32_Ehdr));
 Read_Elf_Ehdr(fp, &elfFHeader);
 printf("section header offset=%x\n", elfFHeader.e_shoff);
 printf("each section size=%x\n",  elfFHeader.e_shentsize);
 printf("section num=%x\n",    elfFHeader.e_shnum);
    for(i = 0; i < elfFHeader.e_shnum; i++)
    {
        /* reset fp */
        fseek(fp,
              elfFHeader.e_shoff + i * elfFHeader.e_shentsize,
              SEEK_SET);
        get_section_info(fp, §ion);
        printf("ind=%d: name=%x; type=%x; flags=%x; addr=%x; offset=%x; size=%x; link=%x; \n\tinfo=%x; addraliggn=%x; entsiz=%x;\n", i,
   section.sh_name, section.sh_type,
   section.sh_flags, section.sh_addr,
   section.sh_offset, section.sh_size,
   section.sh_link, section.sh_info,
   section.sh_addralign, section.sh_entsize);
        nRet = chk_self_def_section(fp, section.sh_offset);
        if(nRet == 0)
        {
            process_app_info(fp, §ion);
            break;
        }
    }
    if(i == elfFHeader.e_shnum)
    {
        printf("Appinfo not found!\n");
        fclose(fp);
        return -1;
    }
 fclose(fp);
    return 0;
}

PS:
1. 我曾尝试找到STRTAB这个类型的section来,判断section header里面section名字字串的位置,再查找self_def_section在section header中的index。但是这样有风险,我用的编译器编译出来的elf文件,始终不能在shstrtab中读取到.plt这个section的名字。
2. 这里,我用了一个较苯的算法,读一个section就根据这个section的offset找到对应文件的地方判断是否是自定义section内容,如果不是就继续读取下一个section,知道读取到自定section为止。
这种方法虽然笨了点,但是一定可以找到自定义section,而且效率是稳定的。
3. 当然,自定义section一般在section header里面比较靠后,可以从最后一个section往前读取,效率更高。
4. Read_Ulong 和Read_Ushort要根据情况,这里是linux elf文件因此有little endian的问题.
 
阅读(2756) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~