常用逆向工具小结(1)

1. strings命令:

这个命令可以用于扫描ELF文件(可执行程序、动态链接库、编译产生的目标文件)中可打印的字符串。

如果不加任何命令行参数,strings将输出ELF文件头中,位于.data段、.rodata段以及符号表中的常量字符串。

如果添加-a,将对整个ELF文件进行扫描,输出全部字符串,包括段名,比如.data、.bss等字符串。


2. file命令:

这个命令可以用于确定某个文件具体类型。本质上,是根据具体的ELF文件头中的幻数字段(Magic)来确定具体文件类型。

补充:ELF文件头的结构:

typedef struct {

unsigned char  e_ident[16];  //幻数,16字节

uint16_t  e_type;

uint16_t  e_machine;

int32_t    e_version;

uint32_t  e_entry;

uint32_t  e_phoff;

uint32_t  e_shoff;

int32_t    e_flags;

uint16_t  e_ehsize;

uint16_t  e_phentsize;

uint16_t  e_shnum;

uint16_t  e_shstrndx;

};


3. nm命令:

这个命令是names的缩写,顾名思义,就是用来查看二进制文件符号表中各个符号的名称、地址及类型。

在ELF文件中,符合分为不同的类型:

1)  U:符号未定义,说明该符号在别的文件中定义。这种情况通常发生在主程序调用了某个库函数。

2)  D:表明当前符号定义于.data段,即位于已初始化数据段,表示一个初始化全局变量(非static)。

3)  B:表明当前符号定义于.bss段,即位于未初始化数据段,表示一个未初始化全局变量(非static)。

           其值表示在.bss段中的偏移量,一般情况下,.bss端分配于RAM。

4)  C:代表common symbol,本质上也是未初始化数据段。对于gcc编译的程序,未初始化全局变量(可能被别的obj引用)其类型为C。

           和B不同的是,该符号表示对应变量只有在链接时才进行内存分配,其值表示该符号需要的字节数。

5)  T:表明当前符号定义于.text段,即代码段,比如全局函数(非static)。

6)  d: 和D本质上相同,表示当前变量是一个已初始化静态变量(static)。

7)  b: 和B本质上相同,表示当前变量是一个未初始化静态变量(static)。

8)  R: 只读数据段,即.rodata段。主要存放程序中定义的整型、字符串常量。

9)  A: 该符号的值是绝对的,在以后的链接过程中,不允许进行该表。

            这样的符号值,常常出现在中断向量表中,例如用符号来表示各个中断向量函数在中断向量表中的位置。

10) t: 和T本质上相同,表示当前符号定义于.text代码段,比如static函数。

举例:main.c

#include <stdio.h>


static int a = 100;
static int b;
extern int c;
int d = 101;
int e;


int func01()
{
}


static int func02()
{
}


int main()
{
    printf("a:%d,b:%d,c:%d,d:%d,e:%d\n",a,b,c,d,e);
}

采用以下命令分别编译:

gcc -c main.c

g++ -c main.c

对产生的main.o目标文件进行nm,得到的结果如下:

1) C目标文件:

0000000000000000 d a
0000000000000000 b b

                                 U c
0000000000000004 D d
0000000000000004 C e
0000000000000000 T func01
0000000000000006 t func02

000000000000000c T main
                                U printf

2) C++目标文件:

                                 U c
0000000000000004 D d
0000000000000000 B e
000000000000000c T main
                                 U printf
0000000000000000 T _Z6func01v
0000000000000000 d _ZL1a
0000000000000004 b _ZL1b
0000000000000006 t _ZL6func02v

可见:

1) C++会对static变量做名称修饰,对非static全局变量则不会进行名称修饰。

2) 对于未初始化全局变量e,gcc会设置该符号类型为e,g++则会设置该符号类型为B。

3) 非static全局变量/函数,一般符号类型标识为大写,static变量或函数,一般符号类型标识为小写。

4. ldd命令:

该命令是list dynamic dependencies的缩写,用于查看当前可执行程序依赖的所有动态链接库。

该命令很常用,具体用法参见ldd手册。


5.c++filt命令:

该命令主要用于将一个经过C++名称修饰(name mangling)的符号,还原为原始符号。

 




阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页