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 ?
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.
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
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
!).
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).
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]