Hiểu những gì một nhị phân Linux đang làm


52

Gần đây tôi có một nhiệm vụ để hiểu một chương trình Linux nhị phân. Tuy nhiên, chương trình ở dạng nhị phân.

Tôi đã sử dụng các lệnh file, stringsobjdumpđể có một ý kiến nhỏ của những gì nó đang làm gì, và những gì các chức năng nó được gọi.

Có vẻ như nhị phân được biên dịch với thông tin gỡ lỗi. Tôi có thể tìm hiểu thêm về nó?


3
Bạn có ý tưởng về việc nhị phân đó đang làm gì không? Bạn có nghi ngờ nó là một số phần mềm độc hại được thiết kế để gây hại cho hệ thống của bạn? Nếu có, điều đó sẽ đi vào câu hỏi (vì sau đó bạn cần có biện pháp phòng ngừa đặc biệt để hạn chế tác hại có thể xảy ra)
Basile Starynkevitch

Đó là một thách thức pháp y.

1
ldd và strace là bạn bè của bạn
user2497

Câu trả lời:


83

Bao gồm các lệnh bạn đã sử dụng, tôi sẽ cố gắng hết sức để chi tiết những gì có thể được thực hiện để thực hiện một số thao tác pháp y trong một tệp thực thi.

Lệnh khiêm tốn stringscó thể hữu ích để trực quan hóa các thông báo lỗi văn bản đưa ra gợi ý về các chức năng nhị phân. Đây cũng là một cách đơn giản để phát hiện các tệp nhị phân đóng gói như trong ví dụ (thường gặp với các tệp nhị phân phần mềm độc hại):

$strings exe_file
UPX!
...
PROT_EXEC|PROT_WRITE failed.
$Info: This file is packed with the UPX executable packer http://upx.sf.net $
$Id: UPX 3.91 Copyright (C) 1996-2013 the UPX Team. All Rights Reserved. $
...
UPX!

chuỗi - in chuỗi ký tự có thể in trong tệp.
Đối với mỗi tệp được cung cấp, chuỗi GNU in các chuỗi ký tự có thể in dài ít nhất 4 ký tự (hoặc số được cung cấp với các tùy chọn bên dưới) và được theo sau bởi một ký tự không thể in được.

file cho phép xem các thuộc tính thực thi, cụ thể là:

  • kiến trúc mà nó nhắm đến;
  • HĐH;
  • nếu liên kết động hoặc tĩnh;
  • nếu biên dịch với thông tin gỡ lỗi hay không.

Trong ví dụ này, "không bị tước" biểu thị nó đã được biên dịch với thông tin gỡ lỗi đi kèm.

$ file exe_file
exe_file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.18, BuildID[sha1]=6f4c5f003e19c7a4bbacb30af3e84a41c88fc0d9, not stripped

filekiểm tra từng đối số trong một nỗ lực để phân loại nó. Có ba bộ kiểm tra, được thực hiện theo thứ tự này: kiểm tra hệ thống tập tin, kiểm tra ma thuật và kiểm tra ngôn ngữ. Thử nghiệm đầu tiên thành công khiến loại tệp được in.

objdump tạo danh sách tháo gỡ của một tệp thực thi:

$ objdump -d exe_file
ls:     file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
__text:
100000f20:      55      pushq   %rbp
100000f21:      48 89 e5        movq    %rsp, %rbp
100000f24:      48 83 c7 68     addq    $104, %rdi
100000f28:      48 83 c6 68     addq    $104, %rsi
100000f2c:      5d      popq    %rbp
100000f2d:      e9 58 36 00 00  jmp     13912
100000f32:      55      pushq   %rbp
100000f33:      48 89 e5        movq    %rsp, %rbp
100000f36:      48 8d 46 68     leaq    104(%rsi), %rax
100000f3a:      48 8d 77 68     leaq    104(%rdi), %rsi
...............

objdump cũng cho phép biết trình biên dịch được sử dụng để biên dịch tệp thực thi nhị phân:

$ objdump -s --section .comment exe_file

exe_file:     file format elf64-x86-64

Contents of section .comment:
 0000 4743433a 2028474e 55292034 2e342e37  GCC: (GNU) 4.4.7
 0010 20323031 32303331 33202852 65642048   20120313 (Red H
 0020 61742034 2e342e37 2d313129 00        at 4.4.7-11).

objdump cũng liệt kê các chức năng bên ngoài được liên kết động trong thời gian chạy:

$ objdump -T exe_file

true:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __uflow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 getenv
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strncmp
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 _exit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __fpending
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 textdomain
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fclose
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 bindtextdomain
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 dcgettext
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __ctype_get_mb_cur_max
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strlen
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.4   __stack_chk_fail
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 mbrtowc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strrchr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 lseek
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memset
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fscanf
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 close
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memcmp
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fputs_unlocked
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 calloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strcmp
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14  memcpy
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fileno
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 malloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fflush
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 nl_langinfo
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 ungetc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __freading
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 realloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fdopen
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 setlocale
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __printf_chk
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 error
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 open
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fseeko
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_atexit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 exit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fwrite
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __fprintf_chk
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 mbsinit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 iswprint
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3   __ctype_b_loc
0000000000207228 g    DO .bss   0000000000000008  GLIBC_2.2.5 stdout
0000000000207220 g    DO .bss   0000000000000008  GLIBC_2.2.5 __progname
0000000000207230  w   DO .bss   0000000000000008  GLIBC_2.2.5 program_invocation_name
0000000000207230 g    DO .bss   0000000000000008  GLIBC_2.2.5 __progname_full
0000000000207220  w   DO .bss   0000000000000008  GLIBC_2.2.5 program_invocation_short_name
0000000000207240 g    DO .bss   0000000000000008  GLIBC_2.2.5 stderr

objdumphiển thị thông tin về một hoặc nhiều tệp đối tượng. Các tùy chọn kiểm soát thông tin cụ thể để hiển thị. Thông tin này chủ yếu hữu ích cho các lập trình viên đang làm việc trên các công cụ biên dịch, trái ngược với các lập trình viên chỉ muốn chương trình của họ biên dịch và làm việc.

Bạn có thể chạy nhị phân trong một VM chỉ được tạo và sau đó loại bỏ chỉ với mục đích chạy nhị phân. Sử dụng strace, ltrace, gdbsysdigđể tìm hiểu thêm về những gì nhị phân được thực hiện ở cấp cuộc gọi hệ thống tại thời gian chạy.

$strace exe_file
open("/opt/sms/AU/mo/tmp.RqBcjY", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
open("/opt/sms/AU/mo/tmp.PhHkOr", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
open("/opt/sms/AU/mo/tmp.q4MtjV", O_RDWR|O_CREAT|O_EXCL, 0600) = 5

stracechạy lệnh được chỉ định cho đến khi nó thoát. Nó chặn và ghi lại các cuộc gọi hệ thống được gọi bởi một quy trình và các tín hiệu được nhận bởi một quy trình. Tên của mỗi cuộc gọi hệ thống, đối số và giá trị trả về của nó được in trên lỗi tiêu chuẩn hoặc tệp được chỉ định với tùy chọn -o.

$ltrace exe_file
_libc_start_main(0x400624, 1, 0x7ffcb7b6d7c8, 0x400710 <unfinished ...>  
time(0)                                                                              = 1508018406  
srand(0x59e288e6, 0x7ffcb7b6d7c8, 0x7ffcb7b6d7d8, 0)                                 = 0  
sprintf("mkdir -p -- '/opt/sms/AU/mo'", "mkdir -p -- '%s'", "/opt/sms/AU/mo")        = 28  
system("mkdir -p -- '/opt/sms/AU/mo'" <no return ...>  
--- SIGCHLD (Child exited) ---  
<... system resumed> )                                                               = 0  
rand(2, 0x7ffcb7b6d480, 0, 0x7f9d6d4622b0)                                           = 0x2d8ddbe1  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 3  
sprintf("/opt/sms/AU/mo/tmp.XXXXXX", "%s/tmp.XXXXXX", "/opt/sms/AU/mo")      = 29  
mkstemp(0x7ffcb7b6d5c0, 0x40080b, 0x40081a, 0x7ffffff1)                              = 4  
+++ exited (status 0) +++  

ltracelà một chương trình chỉ đơn giản là chạy lệnh được chỉ định cho đến khi nó thoát. Nó chặn và ghi lại các cuộc gọi thư viện động được gọi bởi quá trình thực thi và các tín hiệu được nhận bởi quá trình đó. Nó cũng có thể chặn và in các cuộc gọi hệ thống được thực hiện bởi chương trình.

Nó cũng có thể được gỡ lỗi từng bước với gdb.

Mục đích của trình gỡ lỗi như GDB là cho phép bạn xem những gì đang diễn ra '' bên trong '' một chương trình khác trong khi nó thực thi.

Để theo dõi / tạo các bãi chứa nhiều hoạt động hệ thống của nó chạy nó, hãy sử dụng sysdig như trong:

#sudo sysdig proc.name=exe_file
……………….
11569 19:05:40.938743330 1 exe_file (35690) > getpid 
11570 19:05:40.938744605 1 exe_file (35690) < getpid 
11571 19:05:40.938749018 1 exe_file (35690) > open 
11572 19:05:40.938801508 1 exe_file (35690) < open fd=3(<f>/opt/sms/AU/mo/tmp.MhVlrl) name=/opt/sms/AU/mo/tmp.XXXXMhVlrl flags=39(O_EXCL|O_CREAT|O_RDWR) mode=0 
11573 19:05:40.938811276 1 exe_file (35690) > getpid 
11574 19:05:40.938812431 1 exe_file (35690) < getpid 
11575 19:05:40.938813171 1 exe_file (35690) > open 
11576 19:05:40.938826313 1 exe_file (35690) < open fd=4(<f>/opt/sms/AU/mo/tmp.5tlBSs) name=/opt/sms/AU/mo/tmp.5tlBSs flags=39(O_EXCL|O_CREAT|O_RDWR) mode=0 
11577 19:05:40.938848592 1 exe_file (35690) > getpid 
11578 19:05:40.938849139 1 exe_file (35690) < getpid 
11579 19:05:40.938849728 1 exe_file (35690) > open 
11580 19:05:40.938860629 1 exe_file (35690) < open fd=5(<f>/opt/sms/AU/mo/tmp.CJWQjA) name=/opt/sms/AU/mo/tmp.CJWQjA flags=39(O_EXCL|O_CREAT|O_RDWR) mode=0 

sysdiglà một công cụ để xử lý sự cố, phân tích và khai thác hệ thống. Nó có thể được sử dụng để chụp, lọc và giải mã các cuộc gọi hệ thống và các sự kiện hệ điều hành khác. sysdig có thể được sử dụng để kiểm tra các hệ thống trực tiếp hoặc để tạo các tệp theo dõi có thể được phân tích ở giai đoạn sau.

sysdig bao gồm một ngôn ngữ lọc mạnh mẽ, có đầu ra tùy chỉnh và có thể được mở rộng thông qua các tập lệnh Lua, được gọi là đục.

Chúng tôi sẽ xử lý một lần nữa với các analisys tĩnh của chính tệp nhị phân trong phần còn lại của câu trả lời này.

ldd exe_file liệt kê các thư viện mà nó sử dụng;

$ ldd exe_file
    linux-vdso.so.1 (0x00007ffdf83bd000)  
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f14d9b32000)  
    /lib64/ld-linux-x86-64.so.2 (0x000055ededaea000)  

ldd in các đối tượng chia sẻ (thư viện dùng chung) theo yêu cầu của từng chương trình hoặc đối tượng chia sẻ được chỉ định trên dòng lệnh.

size -A exe_file

$ size -A exe_file  
exe_file  :  
section              size      addr  
.interp                28   4194816  
.note.ABI-tag          32   4194844  
.note.gnu.build-id     36   4194876  
.gnu.hash              28   4194912  
.dynsym               216   4194944  
.dynstr                90   4195160  
.gnu.version           18   4195250  
.gnu.version_r         32   4195272  
.rela.dyn              24   4195304  
.rela.plt             168   4195328  
.init                  24   4195496  
.plt                  128   4195520  
.text                 664   4195648  
.fini                  14   4196312  
.rodata                51   4196328  
.eh_frame_hdr          36   4196380  
.eh_frame             124   4196416  
.ctors                 16   6293696  
.dtors                 16   6293712  
.jcr                    8   6293728  
.dynamic              400   6293736  
.got                    8   6294136  
.got.plt               80   6294144  
.data                   4   6294224  
.bss                   16   6294232  
.comment               45         0  
Total                2306


$ size -d ls
   text    data     bss     dec     hex filename
 122678    4664    4552  131894   20336 ls

sizeTiện ích GNU liệt kê các kích thước phần --- và tổng kích thước --- cho mỗi đối tượng hoặc tệp lưu trữ objfile trong danh sách đối số của nó. Theo mặc định, một dòng đầu ra được tạo cho mỗi tệp đối tượng hoặc từng mô-đun trong kho lưu trữ.

readelf -x .rodata exe_file liệt kê các chuỗi tĩnh

$ readelf -x .rodata exe_file 

Hex dump of section '.rodata':
  0x004007e8 01000200 00000000 00000000 00000000 ................
  0x004007f8 6d6b6469 72202d70 202d2d20 27257327 mkdir -p -- '%s'
  0x00400808 0025732f 746d702e 58585858 58585858 .%s/tmp.XXXXXXXX
  0x00400818 585800                              XX.

readelf -h exe_file lấy thông tin tiêu đề ELF

$ readelf -h exe_file   
ELF Header:  
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00   
  Class:                             ELF64  
  Data:                              2's complement, little endian  
  Version:                           1 (current)  
  OS/ABI:                            UNIX - System V  
  ABI Version:                       0  
  Type:                              EXEC (Executable file)  
  Machine:                           Advanced Micro Devices X86-64  
  Version:                           0x1  
  Entry point address:               0x400540  
  Start of program headers:          64 (bytes into file)  
  Start of section headers:          3072 (bytes into file)  
  Flags:                             0x0  
  Size of this header:               64 (bytes)  
  Size of program headers:           56 (bytes)  
  Number of program headers:         8  
  Size of section headers:           64 (bytes)  
  Number of section headers:         30  
  Section header string table index: 27  

readelf -s exe_file hiển thị biểu tượng

$ readelf -s exe_file 

Symbol table '.dynsym' contains 9 entries:  
   Num:    Value          Size Type    Bind   Vis      Ndx Name  
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND   
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__  
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)  
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND system@GLIBC_2.2.5 (2)  
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sprintf@GLIBC_2.2.5 (2)  
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mkstemp@GLIBC_2.2.5 (2)  
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND srand@GLIBC_2.2.5 (2)  
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND rand@GLIBC_2.2.5 (2)  
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND time@GLIBC_2.2.5 (2)  

Symbol table '.symtab' contains 69 entries:  
   Num:    Value          Size Type    Bind   Vis      Ndx Name  
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND   
     1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1   
     2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2   
     3: 000000000040023c     0 SECTION LOCAL  DEFAULT    3   
     4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4   
     5: 0000000000400280     0 SECTION LOCAL  DEFAULT    5   
     6: 0000000000400358     0 SECTION LOCAL  DEFAULT    6   
     7: 00000000004003b2     0 SECTION LOCAL  DEFAULT    7   
     8: 00000000004003c8     0 SECTION LOCAL  DEFAULT    8   
     9: 00000000004003e8     0 SECTION LOCAL  DEFAULT    9   
    10: 0000000000400400     0 SECTION LOCAL  DEFAULT   10   
    11: 00000000004004a8     0 SECTION LOCAL  DEFAULT   11   
    12: 00000000004004c0     0 SECTION LOCAL  DEFAULT   12   
    13: 0000000000400540     0 SECTION LOCAL  DEFAULT   13   
    14: 00000000004007d8     0 SECTION LOCAL  DEFAULT   14   
    15: 00000000004007e8     0 SECTION LOCAL  DEFAULT   15   
    16: 000000000040081c     0 SECTION LOCAL  DEFAULT   16   
    17: 0000000000400840     0 SECTION LOCAL  DEFAULT   17   
    18: 00000000006008c0     0 SECTION LOCAL  DEFAULT   18   
    19: 00000000006008d0     0 SECTION LOCAL  DEFAULT   19   
    20: 00000000006008e0     0 SECTION LOCAL  DEFAULT   20   
    21: 00000000006008e8     0 SECTION LOCAL  DEFAULT   21   
    22: 0000000000600a78     0 SECTION LOCAL  DEFAULT   22   
    23: 0000000000600a80     0 SECTION LOCAL  DEFAULT   23   
    24: 0000000000600ad0     0 SECTION LOCAL  DEFAULT   24   
    25: 0000000000600ad8     0 SECTION LOCAL  DEFAULT   25   
    26: 0000000000000000     0 SECTION LOCAL  DEFAULT   26   
    27: 000000000040056c     0 FUNC    LOCAL  DEFAULT   13 call_gmon_start  
    28: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c  
    29: 00000000006008c0     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_LIST__  
    30: 00000000006008d0     0 OBJECT  LOCAL  DEFAULT   19 __DTOR_LIST__  
    31: 00000000006008e0     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__  
    32: 0000000000400590     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux  
    33: 0000000000600ad8     1 OBJECT  LOCAL  DEFAULT   25 completed.6349  
    34: 0000000000600ae0     8 OBJECT  LOCAL  DEFAULT   25 dtor_idx.6351  
    35: 0000000000400600     0 FUNC    LOCAL  DEFAULT   13 frame_dummy  
    36: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c  
    37: 00000000006008c8     0 OBJECT  LOCAL  DEFAULT   18 __CTOR_END__  
    38: 00000000004008b8     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__  
    39: 00000000006008e0     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__  
    40: 00000000004007a0     0 FUNC    LOCAL  DEFAULT   13 __do_global_ctors_aux  
    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS    exe_file.c  
    42: 0000000000600a80     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_  
    43: 00000000006008bc     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end  
    44: 00000000006008bc     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start  
    45: 00000000006008e8     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC  
    46: 0000000000600ad0     0 NOTYPE  WEAK   DEFAULT   24 data_start  
    47: 0000000000400700     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini  
    48: 0000000000400540     0 FUNC    GLOBAL DEFAULT   13 _start  
    49: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__  
    50: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses  
    51: 00000000004007d8     0 FUNC    GLOBAL DEFAULT   14 _fini  
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_  
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND system@@GLIBC_2.2.5  
    54: 00000000004007e8     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used  
    55: 0000000000600ad0     0 NOTYPE  GLOBAL DEFAULT   24 __data_start  
    56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND sprintf@@GLIBC_2.2.5  
    57: 00000000004007f0     0 OBJECT  GLOBAL HIDDEN    15 __dso_handle  
    58: 00000000006008d8     0 OBJECT  GLOBAL HIDDEN    19 __DTOR_END__  
    59: 0000000000400710   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init  
    60: 0000000000600ad4     0 NOTYPE  GLOBAL DEFAULT  ABS __bss_start  
    61: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mkstemp@@GLIBC_2.2.5  
    62: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND srand@@GLIBC_2.2.5  
    63: 0000000000600ae8     0 NOTYPE  GLOBAL DEFAULT  ABS _end  
    64: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND rand@@GLIBC_2.2.5  
    65: 0000000000600ad4     0 NOTYPE  GLOBAL DEFAULT  ABS _edata  
    66: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND time@@GLIBC_2.2.5  
    67: 0000000000400624   207 FUNC    GLOBAL DEFAULT   13 main  
    68: 00000000004004a8     0 FUNC    GLOBAL DEFAULT   11 _init  

readelfhiển thị thông tin về một hoặc nhiều tệp đối tượng định dạng ELF. Các tùy chọn kiểm soát thông tin cụ thể để hiển thị.

elffile ... là các tệp đối tượng cần kiểm tra. Các tệp ELF 32 bit và 64 bit được hỗ trợ, cũng như các tệp lưu trữ chứa các tệp ELF.

nm exe_file liệt kê các ký hiệu từ bảng đối tượng:

$ nm exe_file   
0000000000600ad4 A __bss_start  
000000000040056c t call_gmon_start  
0000000000600ad8 b completed.6349  
00000000006008c8 d __CTOR_END__  
00000000006008c0 d __CTOR_LIST__  
0000000000600ad0 D __data_start  
0000000000600ad0 W data_start  
00000000004007a0 t __do_global_ctors_aux  
0000000000400590 t __do_global_dtors_aux  
00000000004007f0 R __dso_handle  
00000000006008d8 D __DTOR_END__  
0000000000600ae0 b dtor_idx.6351  
00000000006008d0 d __DTOR_LIST__  
00000000006008e8 d _DYNAMIC  
0000000000600ad4 A _edata  
0000000000600ae8 A _end  
00000000004007d8 T _fini  
0000000000400600 t frame_dummy  
00000000004008b8 r __FRAME_END__  
0000000000600a80 d _GLOBAL_OFFSET_TABLE_  
                 w __gmon_start__  
00000000004004a8 T _init  
00000000006008bc d __init_array_end  
00000000006008bc d __init_array_start  
00000000004007e8 R _IO_stdin_used  
00000000006008e0 d __JCR_END__  
00000000006008e0 d __JCR_LIST__  
                 w _Jv_RegisterClasses  
0000000000400700 T __libc_csu_fini  
0000000000400710 T __libc_csu_init  
                 U __libc_start_main@@GLIBC_2.2.5  
0000000000400624 T main  
                 U mkstemp@@GLIBC_2.2.5  
                 U rand@@GLIBC_2.2.5  
                 U sprintf@@GLIBC_2.2.5  
                 U srand@@GLIBC_2.2.5  
0000000000400540 T _start  
                 U system@@GLIBC_2.2.5  
                 U time@@GLIBC_2.2.5  

nm liệt kê các ký hiệu từ các tệp đối tượng objfile .... Nếu không có tệp đối tượng nào được liệt kê dưới dạng đối số, thì giả sử tệp a.out.

Bên cạnh việc phân tách nhị phân với objdump, một bộ dịch ngược cũng có thể được sử dụng.

Để dịch ngược, gần đây tôi đã thực hiện một thử thách kỹ thuật khi tôi cần dịch ngược hai tệp nhị phân linux 64 bit.

Tôi đã thử sử dụng Boomerang và Snowman. Dự án Boomerang dường như bị bỏ rơi, và tôi không ấn tượng về những hạn chế của cả hai. Một số lựa chọn thay thế khác, hoặc là nguồn mở / phần mềm miễn phí / cũ, bao gồm một cái gần đây được phát hành bởi Avast, chỉ dịch ngược các tệp nhị phân 32 bit.

Cuối cùng tôi đã thử bản demo của Hopper trong MacOS (nó cũng có phiên bản Linux).

Hopper Disassembler, công cụ kỹ thuật đảo ngược cho phép bạn tháo rời, dịch ngược và gỡ lỗi các ứng dụng của bạn.

Phễu tháo rời và dịch ngược mã nhị phân 32 hoặc 64 bit cho OS / X, Linux và Windows. Nó có khả năng giải quyết các nhị phân lớn khi được cấp phép.

Nó cũng tạo ra các biểu đồ luồng của các chức năng của / cấu trúc chương trình và các biến.

Nó cũng đang được tích cực duy trì và cập nhật. Tuy nhiên nó là thương mại.

Tôi rất thích sử dụng nó và kết quả đầu ra đã mua một giấy phép. Giấy phép có giá cả phải chăng hơn nhiều so với tia hex bởi một cú sút xa.

Trong các bình luận của câu trả lời này, @ d33tah và @Josh cũng đề cập đến như là một lựa chọn thay thế nguồn mở radare2 cộng với giao diện đồ họa tương ứng Dao cắt tương tự như Hopper trong Linux, không thể sử dụng cá nhân cho nó vì tôi không sử dụng chúng.

Ngoài ra, vì nhị phân đích được biên dịch với thông tin gỡ lỗi, bạn có thể lấy lại tên gốc của các hàm và biến.

Đáng chú ý hơn, bạn sẽ không bao giờ lấy lại được các nhận xét trong mã nguồn vì chúng không được biên dịch theo bất kỳ cách nào thành các tệp thực thi nhị phân.

Cải thiện chất lượng của nguồn đầu ra, và sự hiểu biết về nhị phân sẽ luôn ngụ ý một số thời gian và công việc thám tử. Trình dịch ngược chỉ làm rất nhiều việc.

Ví dụ về đầu ra Hopper không có thông tin gỡ lỗi:

int EntryPoint(int arg0, int arg1, int arg2) {
    rdx = arg2;
    rbx = arg1;
    r12 = arg0;
    if (r12 <= 0x1) goto loc_100000bdf;

loc_10000093c:
    r15 = *(rbx + 0x8);
    if (strcmp(r15, "-l") == 0x0) goto loc_1000009c2;

loc_100000953:
    if (strcmp(r15, "-s") == 0x0) goto loc_100000a45;

Giao diện đồ họa Hopper cũng rất có thể sử dụng (một số chức năng được mở rộng cùng lúc trên hình ảnh này):

nhập mô tả hình ảnh ở đây

xem thêm câu hỏi liên quan Tại sao đúng và sai quá lớn?


1
Đừng quên strace -ftheo dõi các chủ đề / quy trình con. Có những lựa chọn để phân chia các đầu ra vào các tập tin riêng biệt cho mỗi PID, hoặc bạn có thể chỉ /12345 trong lessđể tìm kiếm và nổi bật dòng bắt đầu bằng PID bạn trong tâm đang. Nếu mọi thứ không quá lộn xộn với nhau (ví dụ như shell script bắt đầu khác các quy trình, không phải các chủ đề đồng thời), điều này có thể được sử dụng. Nhưng yeah, đó là cực kỳ hữu ích chỉ để xem những gì config / file khác một số mảnh bối rối của phần mềm đang cố gắng đọc, khi cố gắng tìm ra lý do tại sao nó không hài lòng với cách bạn cài đặt nó.
Peter Cordes

4
Câu trả lời chính xác! Tôi chỉ cần thêm radare2vào danh sách.
d33tah

2
Dao cắt là một trình bao bọc GUI xung quanh radare2, có vẻ như nó có thể giống với Hopper (nhưng miễn phí).
Josh

2
wrt ldd: Lưu ý rằng trong một số trường hợp (ví dụ: trong đó chương trình chỉ định trình thông dịch ELF khác với ld-linux.so), một số phiên bản của ldd có thể cố gắng lấy thông tin phụ thuộc bằng cách thử trực tiếp thực hiện chương trình (có thể dẫn đến để thực thi bất kỳ mã nào được định nghĩa trong trình thông dịch ELF của chương trình và có lẽ để thực thi chính chương trình đó). Vì vậy, bạn không bao giờ nên sử dụng ldd trên một tệp thực thi không đáng tin cậy, vì điều này có thể dẫn đến việc thực thi mã tùy ý. Một sự thay thế an toàn hơn khi giao dịch với các thực thi không đáng tin cậy là:
Pryftan

2
$ objdump -p / đường dẫn / đến / chương trình | grep NEEDED
Pryftan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.