您的位置:首页 > 运维架构 > Linux

linux中的nm命令简介

2017-12-13 14:09 323 查看
binutil里的工具中比较好用的有nm strip strings

strings这个命令能读取串,但我看到好多代码里面都是写死了密码,如果直接写在代码里面, 用strings扫描一下,就出来了。 一般是放在数据库中, 且加密。 要用的时候, 先读取再解密出来。 这样就不怕strings扫描了。

nm很简单, 但是还是有必要写几句, 聊表心意。  

        nm是names的缩写, nm命令主要是用来列出某些文件中的符号(说白了就是一些函数和全局变量等)。  下面, 我们一起来看看。

       test.h为:

[cpp]
view plain
copy

print?

void print();  

void print();


      test.c为:

[cpp]
view plain
copy

print?

#include <stdio.h>  
#include "test.h"  
  
void print()  
{  
    printf("rainy days\n");  
}  

#include <stdio.h>
#include "test.h"

void print()
{
printf("rainy days\n");
}


       main.c为:

[cpp]
view plain
copy

print?

#include "test.h"  
  
int main()  
{  
    print();  
    return 0;  
}  

#include "test.h"

int main()
{
print();
return 0;
}
      好, 我们看看nm命令的作用效果, 如下:

[plain]
view plain
copy

print?

[taoge@localhost learn_nm]$ nm *  
nm: main.c: File format not recognized  
nm: test.c: File format not recognized  
nm: test.h: File format not recognized  
[taoge@localhost learn_nm]$   

[taoge@localhost learn_nm]$ nm *
nm: main.c: File format not recognized
nm: test.c: File format not recognized
nm: test.h: File format not recognized
[taoge@localhost learn_nm]$
      ni ma, 啥都没有, 这说明nm对这类文件无用。

       继续看nm能否读取目标文件和可执行文件:

[plain]
view plain
copy

print?

[taoge@localhost learn_nm]$ ls  
main.c  test.c  test.h  
[taoge@localhost learn_nm]$ gcc -c test.c main.c   
[taoge@localhost learn_nm]$ gcc test.o main.o  
[taoge@localhost learn_nm]$ ./a.out   
rainy days  
[taoge@localhost learn_nm]$ nm *  
  
a.out:  
08049564 d _DYNAMIC  
08049630 d _GLOBAL_OFFSET_TABLE_  
0804849c R _IO_stdin_used  
         w _Jv_RegisterClasses  
08049554 d __CTOR_END__  
08049550 d __CTOR_LIST__  
0804955c D __DTOR_END__  
08049558 d __DTOR_LIST__  
0804854c r __FRAME_END__  
08049560 d __JCR_END__  
08049560 d __JCR_LIST__  
0804964c A __bss_start  
08049648 D __data_start  
08048450 t __do_global_ctors_aux  
08048330 t __do_global_dtors_aux  
080484a0 R __dso_handle  
         w __gmon_start__  
0804844a T __i686.get_pc_thunk.bx  
08049550 d __init_array_end  
08049550 d __init_array_start  
080483e0 T __libc_csu_fini  
080483f0 T __libc_csu_init  
         U __libc_start_main@@GLIBC_2.0  
0804964c A _edata  
08049654 A _end  
0804847c T _fini  
08048498 R _fp_hw  
08048290 T _init  
08048300 T _start  
0804964c b completed.5963  
08049648 W data_start  
08049650 b dtor_idx.5965  
08048390 t frame_dummy  
080483c8 T main  
080483b4 T print  
         U puts@@GLIBC_2.0  
nm: main.c: File format not recognized  
  
main.o:  
00000000 T main  
         U print  
nm: test.c: File format not recognized  
nm: test.h: File format not recognized  
  
test.o:  
00000000 T print  
         U puts  
[taoge@localhost learn_nm]$   

[taoge@localhost learn_nm]$ ls
main.c  test.c  test.h
[taoge@localhost learn_nm]$ gcc -c test.c main.c
[taoge@localhost learn_nm]$ gcc test.o main.o
[taoge@localhost learn_nm]$ ./a.out
rainy days
[taoge@localhost learn_nm]$ nm *

a.out:
08049564 d _DYNAMIC
08049630 d _GLOBAL_OFFSET_TABLE_
0804849c R _IO_stdin_used
w _Jv_RegisterClasses
08049554 d __CTOR_END__
08049550 d __CTOR_LIST__
0804955c D __DTOR_END__
08049558 d __DTOR_LIST__
0804854c r __FRAME_END__
08049560 d __JCR_END__
08049560 d __JCR_LIST__
0804964c A __bss_start
08049648 D __data_start
08048450 t __do_global_ctors_aux
08048330 t __do_global_dtors_aux
080484a0 R __dso_handle
w __gmon_start__
0804844a T __i686.get_pc_thunk.bx
08049550 d __init_array_end
08049550 d __init_array_start
080483e0 T __libc_csu_fini
080483f0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
0804964c A _edata
08049654 A _end
0804847c T _fini
08048498 R _fp_hw
08048290 T _init
08048300 T _start
0804964c b completed.5963
08049648 W data_start
08049650 b dtor_idx.5965
08048390 t frame_dummy
080483c8 T main
080483b4 T print
U puts@@GLIBC_2.0
nm: main.c: File format not recognized

main.o:
00000000 T main
U print
nm: test.c: File format not recognized
nm: test.h: File format not recognized

test.o:
00000000 T print
U puts
[taoge@localhost learn_nm]$
        可以看到, 对于目标文件和可执行文件而言, 均可以获得其中的函数, 如print函数。

        我们继续看静态库和动态库, 如下:

[plain]
view plain
copy

print?

[taoge@localhost learn_nm]$ ls  
main.c  test.c  test.h  
[taoge@localhost learn_nm]$ gcc -c test.c  
[taoge@localhost learn_nm]$ ar rcs libtest.a test.o  
[taoge@localhost learn_nm]$ gcc -shared -fPIC -o libtest.so test.o  
[taoge@localhost learn_nm]$ ls  
libtest.a  libtest.so  main.c  test.c  test.h  test.o  
[taoge@localhost learn_nm]$ nm lib*  
  
libtest.a:  
  
test.o:  
00000000 T print  
         U puts  
  
libtest.so:  
000014bc a _DYNAMIC  
00001590 a _GLOBAL_OFFSET_TABLE_  
         w _Jv_RegisterClasses  
000014a8 d __CTOR_END__  
000014a4 d __CTOR_LIST__  
000014b0 d __DTOR_END__  
000014ac d __DTOR_LIST__  
000004a0 r __FRAME_END__  
000014b4 d __JCR_END__  
000014b4 d __JCR_LIST__  
000015a4 A __bss_start  
         w __cxa_finalize@@GLIBC_2.1.3  
00000440 t __do_global_ctors_aux  
00000350 t __do_global_dtors_aux  
000014b8 d __dso_handle  
         w __gmon_start__  
00000419 t __i686.get_pc_thunk.bx  
000015a4 A _edata  
000015ac A _end  
00000478 T _fini  
000002ec T _init  
000015a4 b completed.5963  
000015a8 b dtor_idx.5965  
000003e0 t frame_dummy  
00000420 T print  
         U puts@@GLIBC_2.0  
[taoge@localhost learn_nm]$   

[taoge@localhost learn_nm]$ ls
main.c  test.c  test.h
[taoge@localhost learn_nm]$ gcc -c test.c
[taoge@localhost learn_nm]$ ar rcs libtest.a test.o
[taoge@localhost learn_nm]$ gcc -shared -fPIC -o libtest.so test.o
[taoge@localhost learn_nm]$ ls
libtest.a  libtest.so  main.c  test.c  test.h  test.o
[taoge@localhost learn_nm]$ nm lib*

libtest.a:

test.o:
00000000 T print
U puts

libtest.so:
000014bc a _DYNAMIC
00001590 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
000014a8 d __CTOR_END__
000014a4 d __CTOR_LIST__
000014b0 d __DTOR_END__
000014ac d __DTOR_LIST__
000004a0 r __FRAME_END__
000014b4 d __JCR_END__
000014b4 d __JCR_LIST__
000015a4 A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
00000440 t __do_global_ctors_aux
00000350 t __do_global_dtors_aux
000014b8 d __dso_handle
w __gmon_start__
00000419 t __i686.get_pc_thunk.bx
000015a4 A _edata
000015ac A _end
00000478 T _fini
000002ec T _init
000015a4 b completed.5963
000015a8 b dtor_idx.5965
000003e0 t frame_dummy
00000420 T print
U puts@@GLIBC_2.0
[taoge@localhost learn_nm]$
        可以看到, 我们可以从静态库和动态库中获取到函数名称, 如print函数。

        好, 我们再来看看全局变量的情形, 我们把main.c改为:

[cpp]
view plain
copy

print?

#include <stdio.h>  
  
int add(int x, int y)  
{  
    return x + y;  
}  
  
int aaa;  
int bbb = 1;  
char szTest[] = "good";  
  
int main()  
{  
    int ccc = 2;  
    return 0;  
}  

#include <stdio.h>

int add(int x, int y)
{
return x + y;
}

int aaa;
int bbb = 1;
char szTest[] = "good";

int main()
{
int ccc = 2;
return 0;
}
       然后用nm分析a.out(注意, 如果只有nm命令, 则默认a.out为其要处理的文件):

[plain]
view plain
copy

print?

[taoge@localhost learn_nm]$ ls  
main.c  
[taoge@localhost learn_nm]$ gcc main.c   
[taoge@localhost learn_nm]$ ./a.out   
[taoge@localhost learn_nm]$ nm a.out   
08049538 d _DYNAMIC  
08049604 d _GLOBAL_OFFSET_TABLE_  
0804847c R _IO_stdin_used  
         w _Jv_RegisterClasses  
08049528 d __CTOR_END__  
08049524 d __CTOR_LIST__  
08049530 D __DTOR_END__  
0804952c d __DTOR_LIST__  
08048520 r __FRAME_END__  
08049534 d __JCR_END__  
08049534 d __JCR_LIST__  
08049628 A __bss_start  
08049618 D __data_start  
08048430 t __do_global_ctors_aux  
08048310 t __do_global_dtors_aux  
08048480 R __dso_handle  
         w __gmon_start__  
0804842a T __i686.get_pc_thunk.bx  
08049524 d __init_array_end  
08049524 d __init_array_start  
080483c0 T __libc_csu_fini  
080483d0 T __libc_csu_init  
         U __libc_start_main@@GLIBC_2.0  
08049628 A _edata  
08049634 A _end  
0804845c T _fini  
08048478 R _fp_hw  
08048274 T _init  
080482e0 T _start  
08049630 B aaa  
08048394 T add  
0804961c D bbb  
08049628 b completed.5963  
08049618 W data_start  
0804962c b dtor_idx.5965  
08048370 t frame_dummy  
080483a2 T main  
08049620 D szTest  
[taoge@localhost learn_nm]$   

[taoge@localhost learn_nm]$ ls
main.c
[taoge@localhost learn_nm]$ gcc main.c
[taoge@localhost learn_nm]$ ./a.out
[taoge@localhost learn_nm]$ nm a.out
08049538 d _DYNAMIC
08049604 d _GLOBAL_OFFSET_TABLE_
0804847c R _IO_stdin_used
w _Jv_RegisterClasses
08049528 d __CTOR_END__
08049524 d __CTOR_LIST__
08049530 D __DTOR_END__
0804952c d __DTOR_LIST__
08048520 r __FRAME_END__
08049534 d __JCR_END__
08049534 d __JCR_LIST__
08049628 A __bss_start
08049618 D __data_start
08048430 t __do_global_ctors_aux
08048310 t __do_global_dtors_aux
08048480 R __dso_handle
w __gmon_start__
0804842a T __i686.get_pc_thunk.bx
08049524 d __init_array_end
08049524 d __init_array_start
080483c0 T __libc_csu_fini
080483d0 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
08049628 A _edata
08049634 A _end
0804845c T _fini
08048478 R _fp_hw
08048274 T _init
080482e0 T _start
08049630 B aaa
08048394 T add
0804961c D bbb
08049628 b completed.5963
08049618 W data_start
0804962c b dtor_idx.5965
08048370 t frame_dummy
080483a2 T main
08049620 D szTest
[taoge@localhost learn_nm]$
        可以看到, 不仅有add函数, 还有全局变量aaa, bbb和szTest, 要注意, aaa是未初始化的, 所以在Bss段, 而bbb、szTest是初始化了的, 所以在Data段。 值得注意的是, 并没有ccc, 因为ccc是局部变量, nm看不到的。 

        我们还应该注意到, 在上面看不到"good", 为啥呢? 因为nm是用来看szTest而非"good"的。 别忘了, 我们之前介绍过的strings命令可干这事, 如下:

[plain]
view plain
copy

print?

[taoge@localhost learn_nm]$ ls  
a.out  main.c  
[taoge@localhost learn_nm]$ strings a.out   
/lib/ld-linux.so.2  
__gmon_start__  
libc.so.6  
_IO_stdin_used  
__libc_start_main  
GLIBC_2.0  
PTRh  
[^_]  
good  
[taoge@localhost learn_nm]$   

[taoge@localhost learn_nm]$ ls
a.out  main.c
[taoge@localhost learn_nm]$ strings a.out
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
__libc_start_main
GLIBC_2.0
PTRh
[^_]
good
[taoge@localhost learn_nm]$


        nm命令主要列出特性文件中的符号信息, 具体更加详细的用法, 请问man, 我就不再过多介绍了。

转自 http://blog.csdn.net/stpeace/article/details/47089585
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: