12

I would like to decompile the Linux .so files.

  • Any tool to decompile .so files in MS-Windows based operating system ?
  • Any tools/methods to decompile .so files ?
  • 1
    any particular reason why you distinguish between SO files and regular ELFs? – 0xea Aug 21 '13 at 8:41
17

As 0xea said, the .so file are just regular executable files but packed in a dynamic library style.

I know that you asked specifically about MS-Windows tools, but I will ignore this as 0xea already replied about that. I will try to explain how to do it with UNIX tools.

Extract the functions from the library

A first step will be to extract the name of all the functions that are present in this library to know what it is looking like. I will use /usr/lib/libao.so.4.0.0 (a random library I took on my system which is small enough to be taken as an example).

First, run readelf on it to see a bit what you are on:

#> 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...]

You may notice that readelf detected an entrypoint. In fact, it does correspond to the procedure in charge of initializing the memory to get the library properly loaded. But, it is of no use for us.

Looking at the rest of the output of readelf -a, the dynamic symbol table (.dynsym) is quite informative because it contains entries like this:

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

In fact, every function from this dynamic library is in this list and you can extract it simply like this:

#> 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

What you get here, is the names of the functions which are in the .so plus the address of their code in the memory (first column).

Note that you can also get this information by using objdump like this:

#> 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

Disassemble each function

It is time now to use objdump (or a more advanced disassembler if you can get one). Given the list of functions and their address in the binary, you can simply run objdump for each function like this:

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

Note that, as objdump use linear sweep, the disassembly may not be exact (see the following example) and, you also will have to decide by yourself when it ends.

#> 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    $0x8,%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 ...]

And, that's about all (but, get a better disassembler than objdump!).

6

Linux shared object files are ELFs too! Any decompiler that works on "regular" ELF files will work for SO files too.

That said, you can use IDA Pro to disassemble them as usual. If you have IDA Pro licence with Hex-rays decompiler, you can use that. If you don't have Hex-rays, you can try ida-decompiler plugin to get some results. It's open source, but is far less advanced than Hex-rays.

The distinction between disassembling and decompiling is that disassembling the binary code will give you the assembly equivalent. Decompiling on the other hand implies the process of converting the raw assembly code into a higher level language (in this case C).

Decompiling assembly code is not an easy task, as many abstractions that higher level code has are lost on the assembly level. Recovering those abstractions is the difficult part.
For example, you usually lose variable names.

On the other hand, decompiling some bytecode into a higher language, like java bytecode to java, is somewhat easier because many of these abstractions are preserved in the bytecode.

Automatic decompilation of assembly code with current tools isn't perfect, it's meant to serve as a helper in revering. You can also manualy decompile assembly code to higher language by recognizing code constructs (like for loops, if statements, switches and similar).

5

you can use hteditor by seppel if disassembly is ok http://hte.sourceforge.net/

copy the .so file from linux machine with say samba

and feed the so file to hteditor

a sample using libc.so.6 from a damn small linux

assuming samba is up and running in vm and a shared folder in windows host is created say c:\sharedwithvm

from the linux machine 

cp ../..../lib/libc.so.6 /mnt//sharedwithvm

in the windows machine 

C:\>cd sharedwithvm

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

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

hteditor will open with hex view

f6 select elf\image

f8 symbols type fo

60490 │ func │ fopen                                ▲

double click to view the disassembly

<.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]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.