0

I have extracted the .so binary libTheArmKing.so (located in lib directory in apk file) from a hack of World War Heroes game (an Android game) from Plantimod Forum.

file output:

libTheArmKing.so: ELF 32-bit LSB pie executable, ARM, EABI5 version 1 (SYSV), corrupted program header size, stripped

readelf output:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          712948 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           17 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         28
  Section header string table index: 27

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        00000134 000134 000013 00   A  0   0  1
  [ 2] .dynsym           DYNSYM          00000148 000148 006210 10   A  3   1  4
  [ 3] .dynstr           STRTAB          00006358 006358 007038 00   A  0   0  1
  [ 4] .hash             HASH            0000d390 00d390 0028a8 04   A  2   0  4
  [ 5] .rel.dyn          REL             0000fc38 00fc38 000c50 08   A  2   0  4
  [ 6] .rel.plt          REL             00010888 010888 0002a8 08  AI  2   7  4
  [ 7] .plt              PROGBITS        00010b30 010b30 000410 00  AX  0   0  4
  [ 8] .text             PROGBITS        00010f40 010f40 048398 00  AX  0   0  4
  [ 9] .turn             PROGBITS        000592d8 0592d8 000044 00  AX  0   0  4
  [10] .main             PROGBITS        0005931c 05931c 001ba8 00  AX  0   0  4
  [11] .maria            PROGBITS        0005aec4 05aec4 000010 00  AX  0   0  4
  [12] .ARM.extab        PROGBITS        0005aed4 05aed4 002808 00   A  0   0  4
  [13] .ARM.exidx        ARM_EXIDX       0005d6dc 05d6dc 000f80 08  AL  8   0  4
  [14] .rodata           PROGBITS        0005e660 05e660 00340c 00   A  0   0 16
  [15] .data.rel.ro[...] PROGBITS        00063688 062688 000048 00  WA  0   0  4
  [16] .fini_array       FINI_ARRAY      000636d0 0626d0 000008 00  WA  0   0  4
  [17] .init_array       INIT_ARRAY      000636d8 0626d8 000010 00  WA  0   0  4
  [18] .data.rel.ro      PROGBITS        000636e8 0626e8 00063c 00  WA  0   0  8
  [19] .dynamic          DYNAMIC         00063d24 062d24 000108 08  WA  3   0  4
  [20] .got              PROGBITS        00063e30 062e30 0001d0 00  WA  0   0  4
  [21] .data             PROGBITS        00064000 063000 04af6c 00  WA  0   0  8
  [22] .ced              PROGBITS        000aef6c 0adf6c 000020 00  WA  0   0  4
  [23] .bss              NOBITS          000aef90 0adf8c 06dc04 00  WA  0   0  8
  [24] .comment          PROGBITS        00000000 0adf8c 000023 01  MS  0   0  1
  [25] .note.gnu.go[...] NOTE            00000000 0adfb0 00001c 00      0   0  4
  [26] .ARM.attributes   ARM_ATTRIBUTES  00000000 0adfcc 00002f 00      0   0  1
  [27] .shstrtab         STRTAB          00000000 0adffb 0000f8 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  y (purecode), p (processor specific)

There are no section groups in this file.
readelf: Error: The e_phentsize field in the ELF header is less than the size of an ELF program header

When I load this .so into IDA, IDA cannot detect it as ELF, and only show Binary File. Also, it cannot detect the entry point automatically.

I think the mod author made this corruption on purpose to make it harder to reverse engineering his mod.

Here is the binary.

So my question is: How to fix the header of this .so to make it loadable to IDA?

Thank you!

EDIT 1: Ghidra is able to load and detect this as ELF, but skipped some sections due to incorrect address.

1 Answer 1

1

If you use a hex editor and set e_phentsize (offset 0x2a) to 0x20 it works fine, I believe 0x20 is standard for 32bit.

$ readelf -l libTheArmKing.so 

Elf file type is DYN (Shared object file)
Entry point 0x0
There are 8 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00100 0x00100 R   0x4
  INTERP         0x000134 0x00000134 0x00000134 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /system/bin/linker]
  LOAD           0x000000 0x00000000 0x00000000 0x61a6c 0x61a6c R E 0x1000
  LOAD           0x062688 0x00063688 0x00063688 0x4b904 0xb950c RW  0x1000
  DYNAMIC        0x062d24 0x00063d24 0x00063d24 0x00108 0x00108 RW  0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0
  EXIDX          0x05d6dc 0x0005d6dc 0x0005d6dc 0x00f80 0x00f80 R   0x4
  GNU_RELRO      0x062688 0x00063688 0x00063688 0x00978 0x00978 RW  0x8

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .dynsym .dynstr .hash .rel.dyn .rel.plt .plt .text .turn .main .maria .ARM.extab .ARM.exidx .rodata 
   03     .data.rel.ro.local .fini_array .init_array .data.rel.ro .dynamic .got .data .ced .bss 
   04     .dynamic 
   05     
   06     .ARM.exidx 
   07     .data.rel.ro.local .fini_array .init_array .data.rel.ro .dynamic .got 

Detailed info:

You can calculate the correct sizes by running man 5 elf and looking at the Elf32_Phdr or Elf64_Phdr structure definitions and adding up their element sizes, giving you 0x20 for Elf32_Phdr and 0x38 for Elf64_Phdr.

   typedef struct {
       uint32_t   p_type;
       Elf32_Off  p_offset;
       Elf32_Addr p_vaddr;
       Elf32_Addr p_paddr;
       uint32_t   p_filesz;
       uint32_t   p_memsz;
       uint32_t   p_flags;
       uint32_t   p_align;
   } Elf32_Phdr;

   typedef struct {
       uint32_t   p_type;
       uint32_t   p_flags;
       Elf64_Off  p_offset;
       Elf64_Addr p_vaddr;
       Elf64_Addr p_paddr;
       uint64_t   p_filesz;
       uint64_t   p_memsz;
       uint64_t   p_align;
   } Elf64_Phdr;
2
  • Thanks! That worked for me! But how did you find this?
    – raspiduino
    Commented Aug 4, 2022 at 8:58
  • 1
    Edited the answer to provide more information. Fiddling with header fields is a common trick that's easy to implement, many fields can be zeroed or mangled and the executable or library will still work fine. Commented Aug 4, 2022 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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