c语言分析程序,用c语言分析elf的简单程序

这个程序用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的问题.

你可能感兴趣的:(c语言分析程序)