我想反编译Linux .so文件。


是否可以在基于MS-Windows的操作系统中反编译.so文件的任何工具? br />

评论

区分SO文件和常规ELF的任何特殊原因?

#1 楼

正如0xea所说,.so文件只是常规的可执行文件,但以动态库样式打包。

我知道您是专门询问MS-Windows工具的,但由于0xea已经答复,我将忽略它那。我将尝试说明如何使用UNIX工具。

从库中提取函数

第一步将是提取所有函数的名称。出现在这个库中以了解它的外观。我将使用/usr/lib/libao.so.4.0.0(我在系统上使用的随机库,它很小,仅作为示例)。

首先,在其上运行readelf来了解一下您所使用的内容:

#> readelf -a /usr/lib/libao.so.4.0.0

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:                              DYN (Shared object file)
Machine:                           Advanced Micro Devices X86-64
Version:                           0x1
Entry point address:               0x1fb0
Start of program headers:          64 (bytes into file)
Start of section headers:          35392 (bytes into file)
Flags:                             0x0
Size of this header:               64 (bytes)
Size of program headers:           56 (bytes)
Number of program headers:         6
Size of section headers:           64 (bytes)
Number of section headers:         29
Section header string table index: 28

[...lots of tables and other information...]


您可能会注意到readelf检测到一个入口点。实际上,它确实与负责初始化内存以正确加载库的过程相对应。但是,这对我们没有用。

看看readelf -a的其余输出,动态符号表(.dynsym)很有用,因为它包含如下条目:

43: 00000000000038e0  1302 FUNC    GLOBAL DEFAULT   13 ao_play@@LIBAO4_1.1.0


实际上,此动态库中的每个函数都在此列表中,您可以像以下这样简单地提取它:

#> readelf -a /usr/lib/libao.so.4.0.0 | grep LIBAO4_1.1.0 | grep FUNC

43: 00000000000038e0  1302 FUNC    GLOBAL DEFAULT   13 ao_play@@LIBAO4_1.1.0
44: 0000000000003670   177 FUNC    GLOBAL DEFAULT   13 ao_append_option@@LIBAO4_1.1.0
45: 00000000000040e0    70 FUNC    GLOBAL DEFAULT   13 ao_driver_info@@LIBAO4_1.1.0
46: 0000000000002d40  2349 FUNC    GLOBAL DEFAULT   13 ao_initialize@@LIBAO4_1.1.0
48: 0000000000003ef0   484 FUNC    GLOBAL DEFAULT   13 ao_default_driver_id@@LIBAO4_1.1.0
49: 0000000000003e00   144 FUNC    GLOBAL DEFAULT   13 ao_close@@LIBAO4_1.1.0
50: 0000000000005070   239 FUNC    GLOBAL DEFAULT   13 ao_open_file@@LIBAO4_1.1.0
51: 0000000000005160     7 FUNC    GLOBAL DEFAULT   13 ao_open_live@@LIBAO4_1.1.0
52: 0000000000003730    18 FUNC    GLOBAL DEFAULT   13 ao_append_global_option@@LIBAO4_1.1.0
53: 0000000000003790   326 FUNC    GLOBAL DEFAULT   13 ao_shutdown@@LIBAO4_1.1.0
54: 0000000000004130    16 FUNC    GLOBAL DEFAULT   13 ao_driver_info_list@@LIBAO4_1.1.0
55: 0000000000003750    60 FUNC    GLOBAL DEFAULT   13 ao_free_options@@LIBAO4_1.1.0
56: 0000000000004140    13 FUNC    GLOBAL DEFAULT   13 ao_is_big_endian@@LIBAO4_1.1.0
57: 0000000000003e90    92 FUNC    GLOBAL DEFAULT   13 ao_driver_id@@LIBAO4_1.1.0


您在这里得到的是.so中的功能名称以及它们在内存中的代码地址(第一列)。

请注意,您也可以使用objdump获得此信息像这样:

#> objdump -T /usr/lib/libao.so.4.0.0 | grep LIBAO4_1.1.0 | grep DF
00000000000038e0 g    DF .text  0000000000000516  LIBAO4_1.1.0 ao_play
0000000000003670 g    DF .text  00000000000000b1  LIBAO4_1.1.0 ao_append_option
00000000000040e0 g    DF .text  0000000000000046  LIBAO4_1.1.0 ao_driver_info
0000000000002d40 g    DF .text  000000000000092d  LIBAO4_1.1.0 ao_initialize
0000000000003ef0 g    DF .text  00000000000001e4  LIBAO4_1.1.0 ao_default_driver_id
0000000000003e00 g    DF .text  0000000000000090  LIBAO4_1.1.0 ao_close
0000000000005070 g    DF .text  00000000000000ef  LIBAO4_1.1.0 ao_open_file
0000000000005160 g    DF .text  0000000000000007  LIBAO4_1.1.0 ao_open_live
0000000000003730 g    DF .text  0000000000000012  LIBAO4_1.1.0 ao_append_global_option
0000000000003790 g    DF .text  0000000000000146  LIBAO4_1.1.0 ao_shutdown
0000000000004130 g    DF .text  0000000000000010  LIBAO4_1.1.0 ao_driver_info_list
0000000000003750 g    DF .text  000000000000003c  LIBAO4_1.1.0 ao_free_options
0000000000004140 g    DF .text  000000000000000d  LIBAO4_1.1.0 ao_is_big_endian
0000000000003e90 g    DF .text  000000000000005c  LIBAO4_1.1.0 ao_driver_id


反汇编每个函数

现在是时候使用objdump(或者如果可以的话,可以使用更高级的反汇编程序) 。给定函数列表及其二进制地址,您可以为每个函数简单地运行objdump,如下所示:

objdump -d /usr/lib/libao.so.4.0.0 --start-address=0x3730


请注意,由于objdump使用线性扫描,因此拆卸可能不准确(请参见以下示例),并且还必须自行决定何时结束。

#> objdump -d /usr/lib/libao.so.4.0.0 --start-address=0x3730

/usr/lib/libao.so.4.0.0:     file format elf64-x86-64

Disassembly of section .text:
0000000000003730 <ao_append_global_option>:
 3730:       48 89 f2                mov    %rsi,%rdx
 3733:       48 89 fe                mov    %rdi,%rsi
 3736:       48 8d 3d cb 52 20 00    lea    0x2052cb(%rip),%rdi
 373d:       e9 4e e6 ff ff          jmpq   1d90 <ao_append_option@plt>
 3742:       66 66 66 66 66 2e 0f    data32 data32 data32 data32 nopw %cs:0x0(%rax,%rax,1)
 3749:       1f 84 00 00 00 00 00 

0000000000003750 <ao_free_options>:
 3750:       55                      push   %rbp
 3751:       53                      push   %rbx
 3752:       48 89 fb                mov    %rdi,%rbx
 3755:       48 83 ec 08             sub    q4312078qx8,%rsp
 3759:       48 85 ff                test   %rdi,%rdi
 375c:       74 27                   je     3785 <ao_free_options+0x35>
 375e:       66 90                   xchg   %ax,%ax
 3760:       48 8b 3b                mov    (%rbx),%rdi
 3763:       48 8b 6b 10             mov    0x10(%rbx),%rbp
 3767:       e8 c4 e5 ff ff          callq  1d30 <free@plt>
 376c:       48 8b 7b 08             mov    0x8(%rbx),%rdi
 3770:       e8 bb e5 ff ff          callq  1d30 <free@plt>
 3775:       48 89 df                mov    %rbx,%rdi
 3778:       48 89 eb                mov    %rbp,%rbx
 377b:       e8 b0 e5 ff ff          callq  1d30 <free@plt>
 [... clip ...]


而且,仅此而已(但是,要获得比objdump更好的反汇编程序!)。

评论


很好的解释:)

– BlueBerry-Vignesh4303
13年8月23日在4:33

#2 楼

Linux共享对象文件也是ELF!任何适用于“常规” ELF文件的反编译器也适用于SO文件。

也就是说,您可以像往常一样使用IDA Pro拆卸它们。如果您拥有带有Hex-rays反编译器的IDA Pro许可证,则可以使用它。如果您没有Hex-ray,可以尝试使用ida-decompiler插件来获得一些结果。它是开源的,但远没有Hex-ray先进。

反汇编和反编译之间的区别在于,反汇编二进制代码将使您获得等效的汇编代码。另一方面,反编译意味着将原始汇编代码转换为更高级别的语言(在本例中为C)的过程。

反汇编代码并不是一件容易的事,因为许多抽象需要更高级别的代码在装配级别丢失了。恢复这些抽象是困难的部分。
例如,您通常会丢失变量名。

另一方面,将某些字节码反编译为高级语言(如将Java字节码转换为Java)则较为容易,因为其中许多抽象都保留在字节码中。

使用当前工具对汇编代码进行自动反汇编并不是完美的,它可以作为崇敬的助手。您还可以通过识别代码构造(例如用于循环,if语句,开关等)来手动将汇编代码反编译为高级语言。

#3 楼

如果可以反汇编,则可以通过seppel使用hteditor。 >然后将so文件提供给hteditor
从该死的小型linux使用libc.so.6的示例

假设samba在vm中已启动并正在运行,并且在创建Windows主机
c:\sharedwithvm

from the linux machine 



in the windows machine 

C:\>cd sharedwithvm

C:\sharedwithvm>dir /b
libc.so.6

C:\sharedwithvm>f:\hteditor22\ht-2.0.22-win32.exe libc.so.6


hteditor将以十六进制视图打开

f6 select elf\image

f8 symbols type fo

60490 │ func │ fopen                                ▲


双击以查看反汇编

<.text> @00060490  push ebp
fopen+0
   ..... ! ;********************************************************
   ..... ! ; function fopen (global)
   ..... ! ;********************************************************
   ..... ! fopen:                          ;xref c189a7 c262da c74722
   ..... !                                 ;xref c93c74 c94cd5 cd23c4
   ..... !                                 ;xref cd3617 cd37c6 cd3a1a
   ..... !                                 ;xref cd7061 cd717f cd729f
   ..... !                                 ;xref ce50e3 ce67e6 ce7581
   ..... !                                 ;xref cef095 cf0302
   ..... !   push        ebp
   60491 !   mov         ebp, esp
   60493 !   sub         esp, 18h
   60496 !   mov         [ebp-4], ebx
   60499 !   mov         eax, [ebp+0ch]
   6049c !   call        sub_15c8d
   604a1 !   add         ebx, offset_cab57
   604a7 !   mov         dword ptr [esp+8], 1
   604af !   mov         [esp+4], eax
   604b3 !   mov         eax, [ebp+8]