使用c语言的分析elf文件的代码,Android逆向进阶-ELF文件分析(3)

0x00 前言

内容

1.Program Headers 程序分析

2.Section 分析

3.字符串表

4.符号表

0x01 Program Headers 分析

首先来看一个结构体

typedef struct {

Elf32_Word p_type;

Elf32_Off p_offset;

Elf32_Addr p_vaddr;

Elf32_Addr p_paddr;

Elf32_Word p_filesz;

Elf32_Word p_memsz;

Elf32_Word p_flags;

Elf32_Word p_align;

} Elf32_phdr;

p_type

描述段的类型,或者如何解释此数组元素的信息。

o_1c7ogfkp313tl1s1s10ml1e7m9upa.png-j.jpg

010 Editor分析

o_1c7ogkkju1f9o11c8mii1r66icra.png-j.jpg

使用c语言实现程序编写。

o_1c7oic3qtstu19qo1sh6hpinp0a.png-j.jpg

printf("--------第%d个Program Headers--------\n",1);

printf("p_type:");

for (i = 0; i < 4; i++)

{

c = fgetc(fp);

j = c;

hex_str = inttohex(j);

h1[i] = j;

if (j < 9){

printf("0%s ", hex_str);

}

else

{

printf("%s ", hex_str);

}

}

E_type(h1[0]);

p_offset

此成员给出从文件头到该段第一个字节的偏移。

010 editor 分析

o_1c7oitdhl3rs15vicfs1spv1cf9a.png-j.jpg

c语言分析

o_1c7oiv86o1bl147m1qo81uu43tia.png-j.jpg

printf("p_offset:");

for (i = 0; i < 4; i++)

{

c = fgetc(fp);

j = c;

hex_str = inttohex(j);

h1[i] = j;

if (j < 9){

printf("0%s ", hex_str);

}

else

{

printf("%s ", hex_str);

}

}

printf("(%s H)", inttohex(h1[0]));

p_vaddr

此成员给出段的第一个字节将被放到内存中的虚拟地址。

010 editor 对比分析

o_1c7oj5nac1bnt1cjq5uf1cs14hqa.png-j.jpg

c语言分析

o_1c7ojcc1f6451um11gkgskqkd7a.png-j.jpg

关键代码

printf("p_vaddr:");

for (i = 0; i < 4; i++)

{

c = fgetc(fp);

j = c;

hex_str = inttohex(j);

h1[i] = j;

if (j < 9){

printf("0%s ", hex_str);

}

else

{

printf("%s ", hex_str);

}

}

printf("(%s H)\n", inttohex(h1[0]));

p_paddr

此成员仅用于与物理地址相关的系统中。因为 System V 忽略所有应用程序的物理地址信息,此字段对与可执行文件和共享目标文件而言具体内容是未指定的。

010 Editor 对比分析

o_1c7ojiknb3h1n3g1hmshbj1pmma.png-j.jpg

c语言代码:

和上面一样继续向下读取就可以了。

p_filesz

此成员给出段在文件映像中所占的字节数。可以为 0

010 editor

o_1c7ojq5cf3l0l0791o1q7k1lmsa.png-j.jpg

c语言程序展示。

o_1c7oko52uta31d68673ncp9lja.png-j.jpg

关键代码:

printf("p_filesz:");

for (i = 0; i < 4; i++)

{

c = fgetc(fp);

j = c;

h1[i] = j;

hex_str = inttohex(j);

if (j < 9){

if (j >= 0){

printf("0%s ", hex_str);

}

else

{

j = 256 + j;

h1[i] = j;

if (i == 0)

{

j1 = j;

}

hex_str = inttohex(j);

if (j<9)

printf("0%s ", hex_str);

else

printf("%s ", hex_str);

}

}

else

{

printf("%s ", hex_str);

}

}

hex_str = inttohex(h1[1]);

printf("(");

if (h1[1] < 9){

if (h1[1] >= 0){

printf("0%s", hex_str);

}

else

{

h1[1] = 256 + h1[1];

hex_str = inttohex(h1[1]);

if (h1[1]<9)

printf("0%s", hex_str);

else

printf("%s", hex_str);

}

}

else

{

printf("%s", hex_str);

}

hex_str = inttohex(h1[0]);

if (h1[0] < 9){

if (h1[0] >= 0){

printf("0%s", hex_str);

}

else

{

h1[0] = 256 + h1[0];

hex_str = inttohex(h1[0]);

if (h1[0]<9)

printf("0%s", hex_str);

else

printf("%s", hex_str);

}

}

else

{

printf("%s", hex_str);

}

printf(" H)\n");

p_memsz

此成员给出段在内存映像中占用的字节数。可以为 0。

010 editor

o_1c7oks0qb1p86e421rpe8dq1vhea.png-j.jpg

c语言核心代码

printf("p_memsz:");

for (i = 0; i < 4; i++)

{

c = fgetc(fp);

j = c;

h1[i] = j;

hex_str = inttohex(j);

if (j < 9){

if (j >= 0){

printf("0%s ", hex_str);

}

else

{

j = 256 + j;

h1[i] = j;

if (i == 0)

{

j1 = j;

}

hex_str = inttohex(j);

if (j<9)

printf("0%s ", hex_str);

else

printf("%s ", hex_str);

}

}

else

{

printf("%s ", hex_str);

}

}

hex_str = inttohex(h1[1]);

printf("(");

if (h1[1] < 9){

if (h1[1] >= 0){

printf("0%s", hex_str);

}

else

{

h1[1] = 256 + h1[1];

hex_str = inttohex(h1[1]);

if (h1[1]<9)

printf("0%s", hex_str);

else

printf("%s", hex_str);

}

}

else

{

printf("%s", hex_str);

}

hex_str = inttohex(h1[0]);

if (h1[0] < 9){

if (h1[0] >= 0){

printf("0%s", hex_str);

}

else

{

h1[0] = 256 + h1[0];

hex_str = inttohex(h1[0]);

if (h1[0]<9)

printf("0%s", hex_str);

else

printf("%s", hex_str);

}

}

else

{

printf("%s", hex_str);

}

printf(" H)\n");

p_flags

此成员给出与段相关的标志。

#define PF_X        0x1 /* Executable. */

#define PF_W        0x2 /* Writable. */

#define PF_R        0x4 /* Readable. */

010 editor

o_1c7omljvr1jha1kac1gek1acdn9ia.png-j.jpg

p_align

可加载的进程段的 p_vaddr 和 p_offset 取值必须合适,相对于对页面大小的取模而言。此成员给出段在文件中和内存中如何对齐。数值 0 和 1 表示不需要对齐。否则 p_align 应该是个正整数,并且是 2 的幂次数,p_vaddr 和 p_offset 对 p_align取模后应该相等。

o_1c7omuviojj5dd11hoe1hub1ahka.png-j.jpg

总结

整个Program head 就分析完了。

o_1c7oneh1tbibdoi180hgcu1ndga.png-j.jpg

0x02 Sections

(1). 目标文件中的每个节区都有对应的节区头部描述它,反过来,有节区头部不意味着有节区。

(2). 每个节区占用文件中一个连续字节区域(这个区域可能长度0)。

(3). 文件中的节区不能重叠,不允许一个字节存在于两个节区中的情况发生。

(4). 目标文件中可能包含非活动空间(INACTIVE SPACE)。这些区域不属于任何头部和节区,其内容未指定。

1.Section head

typedef struct{

Elf32_Word sh_name;

Elf32_Word sh_type;

Elf32_Word sh_flags;

Elf32_Addr sh_addr;

Elf32_Off sh_offset;

Elf32_Word sh_size;

Elf32_Word sh_link;

Elf32_Word sh_info;

Elf32_Word sh_addralign;

Elf32_Word sh_entsize;

}Elf32_Shdr;

这里有具体的说明。

o_1c7oo9h6u147k1nmd1ecmpp3fsma.png-j.jpg

o_1c7ooad1l17fn1vujpkmdgm43oa.png-j.jpg

sh_type字段

o_1c7ooch6s1j2qdj31k5hpd2ekja.png-j.jpg

o_1c7ooddvfokv1js3k0qjrk1b3sa.png-j.jpg

还有一些特殊字节,这里就不再赘述了。有兴趣的可以自己研究一下。

0x03 字符串表

字符串表节区包含以 NULL(ASCII 码 0)结尾的字符序列,通常称为字符串。

对字符串的引用通常以字符串在字符串表中的下标给出。

一般,第一个字节(索引为 0)定义为一个空字符串。

允许存在空的字符串表节区,其节区头部的 sh_size 成员应该为 0。

0x04 符号表

使用

readelf -s 1.so

进行查看。

o_1c7ooolnph3ver3121l1o5q3ua.png-j.jpg

恩,这个留着以后有时间慢慢来分析。

2018年3月4日23:17:26退水了退水了88

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值