upx 源码分析

upx 源码分析

主程序入口: main.cpp --->upx_main 对选项进行处理-

work.cpp: do_files() --> work.cpp: do_one_file()--: 先对要压缩的文件进行检查,使用 pm.pack(&fo); 调用pack 函数对文件进行

packmaster.cpp: pack() ---> getPacker ()--> try_pack()--> 对各种pack header 进行初始化--》do_pack()

参考如下:

【源码分析】UPX 源码分析 - binLep's Blog

UPX源码分析——加壳篇

upx 源码分析 脱壳

Using reverse engineering techniques to see how a common malware packer works - Detectify Labs

UPX源码分析——加壳篇_江西省遂川县杰出青年代表的博客-CSDN博客_linux upx 加壳

elf 文件解析

程序的本质之二ELF文件的文件头、section header和program header_tanglinux的博客-CSDN博客

pack1() :

PackLinuxElf64::generateElfHdr (this=0x5555557952c0, fo=0x7fffffffd1e0, proto=0x5555556ab160 <stub_amd64_linux_elf_fold>, brka=24696) at p_lx_elf.cpp:3030 #1 0x00005555555c21c5 in PackLinuxElf64amd::pack1 (this=0x5555557952c0, fo=0x7fffffffd1e0, ft=...) at p_lx_elf.cpp:3808 #2 0x00005555555f3d8a in PackUnix::pack (this=0x5555557952c0, fo=0x7fffffffd1e0) at p_unix.cpp:293 #3 0x000055555560e030 in Packer::doPack (this=0x5555557952c0, fo=0x7fffffffd1e0) at packer.cpp:100 #4 0x0000555555618315 in PackMaster::pack (this=0x7fffffffd2b0, fo=0x7fffffffd1e0) at packmast.cpp:262 #5 0x0000555555635f42 in do_one_file (iname=0x7fffffffe1ba "a", oname=0x7fffffffd890 "a.000") at work.cpp:158 #6 0x0000555555636377 in do_files (i=1, argc=2, argv=0x7fffffffdde8) at work.cpp:271 #7 0x00005555555a55a6 in main (argc=2, argv=0x7fffffffdde8) at main.cpp:1539

源码分析

stub/amd64-linux.elf-entry.h:0x1850,到文件尾部内容如下读取出来的内容,用于loader 初始化section,symbols, relocations

        Sections:
            Idx Name          Size      VMA               LMA               File off  Algn  Flags
              0 ELFMAINX      0000000f  0000000000000000  0000000000000000  00000040  2**0  CONTENTS, RELOC, READONLY
              1 NRV_HEAD      00000066  0000000000000000  0000000000000000  0000004f  2**0  CONTENTS, READONLY
              2 NRV2E         000000ba  0000000000000000  0000000000000000  000000b5  2**0  CONTENTS, RELOC, READONLY
              3 NRV2D         000000a1  0000000000000000  0000000000000000  0000016f  2**0  CONTENTS, RELOC, READONLY
              4 NRV2B         00000093  0000000000000000  0000000000000000  00000210  2**0  CONTENTS, RELOC, READONLY
              5 LZMA_ELF00    00000064  0000000000000000  0000000000000000  000002a3  2**0  CONTENTS, RELOC, READONLY
              6 LZMA_DEC10    000009f7  0000000000000000  0000000000000000  00000307  2**0  CONTENTS, READONLY
              7 LZMA_DEC20    000009f7  0000000000000000  0000000000000000  00000cfe  2**0  CONTENTS, READONLY
              8 LZMA_DEC30    00000018  0000000000000000  0000000000000000  000016f5  2**0  CONTENTS, READONLY
              9 NRV_TAIL      00000000  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, READONLY
             10 ELFMAINY      0000003a  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, RELOC, READONLY
             11 ELFMAINZ      000000ef  0000000000000000  0000000000000000  00001747  2**0  CONTENTS, RELOC, READONLY
            SYMBOL TABLE:
            0000000000000000 l    d  NRV_HEAD   0000000000000000 NRV_HEAD
            0000000000000000 l    d  LZMA_DEC30 0000000000000000 LZMA_DEC30
            0000000000000000 l    d  ELFMAINY   0000000000000000 ELFMAINY
            0000000000000000 l    d  ELFMAINZ   0000000000000000 ELFMAINZ
            0000000000000000 l    d  ELFMAINX   0000000000000000 ELFMAINX
            0000000000000000 l    d  NRV2E  0000000000000000 NRV2E
            0000000000000000 l    d  NRV2D  0000000000000000 NRV2D
            0000000000000000 l    d  NRV2B  0000000000000000 NRV2B
            0000000000000000 l    d  LZMA_ELF00 0000000000000000 LZMA_ELF00
            0000000000000000 l    d  LZMA_DEC10 0000000000000000 LZMA_DEC10
            0000000000000000 l    d  LZMA_DEC20 0000000000000000 LZMA_DEC20
            0000000000000000 l    d  NRV_TAIL   0000000000000000 NRV_TAIL
            0000000000000000 g       ELFMAINX   0000000000000000 _start
            0000000000000000         *UND*  0000000000000000 O_BINFO
​
            RELOCATION RECORDS FOR [ELFMAINX]:
            OFFSET           TYPE              VALUE
            0000000000000003 R_X86_64_PC32     ELFMAINZ+0x00000000000000d2
​
            RELOCATION RECORDS FOR [NRV2E]:
            OFFSET           TYPE              VALUE
            00000000000000af R_X86_64_PC32     NRV_HEAD+0x0000000000000021
            000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
​
            RELOCATION RECORDS FOR [NRV2D]:
            OFFSET           TYPE              VALUE
            0000000000000096 R_X86_64_PC32     NRV_HEAD+0x0000000000000021
            000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
​
            RELOCATION RECORDS FOR [NRV2B]:
            OFFSET           TYPE              VALUE
            000000000000008b R_X86_64_PC32     NRV_HEAD+0x0000000000000021
            0000000000000053 R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
​
            RELOCATION RECORDS FOR [LZMA_ELF00]:
            OFFSET           TYPE              VALUE
            0000000000000006 R_X86_64_PC32     LZMA_DEC30+0x0000000000000012
​
            RELOCATION RECORDS FOR [ELFMAINY]:
            OFFSET           TYPE              VALUE
            0000000000000018 R_X86_64_PC32     ELFMAINZ+0x0000000000000003
​
            RELOCATION RECORDS FOR [ELFMAINZ]:
            OFFSET           TYPE              VALUE
            00000000000000eb R_X86_64_32       O_BINFO
  1. 原有二进制文件progarm header 内容,

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000e70 0x0000000000000e70  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x0000000000002cf5 0x0000000000002cf5  R E    0x1000
  LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                 0x0000000000000688 0x0000000000000688  R      0x1000
  LOAD           0x0000000000004c98 0x0000000000005c98 0x0000000000005c98
                 0x00000000000003c8 0x00000000000003e0  RW     0x1000
  DYNAMIC        0x0000000000004ca8 0x0000000000005ca8 0x0000000000005ca8
                 0x0000000000000210 0x0000000000000210  RW     0x8
  NOTE           0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  NOTE           0x0000000000000358 0x0000000000000358 0x0000000000000358
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_PROPERTY   0x0000000000000338 0x0000000000000338 0x0000000000000338
                 0x0000000000000020 0x0000000000000020  R      0x8
  GNU_EH_FRAME   0x0000000000004260 0x0000000000004260 0x0000000000004260
                 0x00000000000000d4 0x00000000000000d4  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000004c98 0x0000000000005c98 0x0000000000005c98
                 0x0000000000000368 0x0000000000000368  R      0x1
​

pack() 函数分析

pack1():

p_unix.cpp:277:

#0  PackLinuxElf64::pack1 (this=0x5555557952c0, fo=0x7fffffffd1e0) at p_lx_elf.cpp:3496
#1  0x00005555555c2154 in PackLinuxElf64amd::pack1 (this=0x5555557952c0, fo=0x7fffffffd1e0, ft=...) at p_lx_elf.cpp:3805
#2  0x00005555555f3d8a in PackUnix::pack (this=0x5555557952c0, fo=0x7fffffffd1e0) at p_unix.cpp:293
#3  0x000055555560e030 in Packer::doPack (this=0x5555557952c0, fo=0x7fffffffd1e0) at packer.cpp:100
#4  0x0000555555618315 in PackMaster::pack (this=0x7fffffffd2b0, fo=0x7fffffffd1e0) at packmast.cpp:262
#5  0x0000555555635f42 in do_one_file (iname=0x7fffffffe1c3 "a", oname=0x7fffffffd890 "a.upx") at work.cpp:158
#6  0x0000555555636377 in do_files (i=1, argc=2, argv=0x7fffffffdde8) at work.cpp:271
#7  0x00005555555a55a6 in main (argc=2, argv=0x7fffffffdde8) at main.cpp:1539

具体生成代码位于p_lx_elf.cpp:2943

先从stub/amd64-linux.elf-fold.h读取头部内容,并根据原有二进制文件内容进行赋值

    memcpy(h3, proto, sizeof(*h3));  // reads beyond, but OK //proto = stub_amd64_linux_elf_fold,读取244 长度内容, PackLinuxElf64::cprElfHdr2 * h3
    h3->ehdr.e_type = ehdri.e_type;  // ET_EXEC vs ET_DYN (gcc -pie -fPIC),ehdri 为原始二进制头部内容。长度64
    h3->ehdr.e_ident[Elf64_Ehdr::EI_OSABI] = ei_osabi;
 p/x *h3
$30 = {ehdr = {e_ident = {0x7f, 0x45, 0x4c, 0x46, 0x2, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, e_type = {d = {0x3, 0x0}}, e_machine = {d = {0x3e, 0x0}}, e_version = {d = {0x1, 0x0, 0x0, 0x0}}, e_entry = {d = {0xbc, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_phoff = { d = {0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_shoff = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
        0x0, 0x0}}, e_flags = {d = {0x0, 0x0, 0x0, 0x0}}, e_ehsize = {d = {0x40, 0x0}},  e_phentsize = {d = {0x38, 0x0}}, e_phnum = {d = {0x3, 0x0}}, e_shentsize = {d = {0x40, 0x0}},e_shnum = {d = {0x0, 0x0}}, e_shstrndx = {d = {0x0, 0x0}}},
 phdr = {{p_type = {d = {0x1, 0x0, 0x0, 0x0}}, p_flags = {d = {0x5, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},  p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0xbc, 0x0, 0x0,0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0xbc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, 
 {p_type = {d = {0x1, 0x0, 0x0, 0x0}}, p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0,   0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {  d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x78, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = { d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, 
 {p_type = {d = {0x51, 0xe5, 0x74, 0x64}},  p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,  0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}}, 
 linfo = {l_checksum = {d = {0x2c, 0xe8, 0x3c, 0x1}}, l_magic = {d = {0x77, 0xe4, 0x48, 0x39}}, l_lsize = {d = {0xce, 0x73}}, 
    l_version = 0x16, l_format = 0x56}}

生成header 部分, 1个elfheader+3个program header+l_info 大小为 244=64+56*3+sizeof(l_info)=64+168+12=244

(gdb) p/x hbuf
$3 = {p_progid = 0x0, p_filesize = 0x6aa8, p_blocksize = 0x6aa8}
00000000: 7F45 4C46 0201 0100 0000 0000 0000 0000  .ELF............
00000010: 0300 3E00 0100 0000 BC00 1000 0000 0000  ..>.............
00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
00000030: 0000 0000 4000 3800 0300 4000 0000 0000  ....@.8...@.....
00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: BC00 0000 0000 0000 BC00 0000 0000 0000  ................
00000070: 0010 0000 0000 0000 0100 0000 0600 0000  ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000a0: 7860 0000 0000 0000 0010 0000 0000 0000  x`..............
000000b0: 51E5 7464 0600 0000 0000 0000 0000 0000  Q.td............
000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000e0: 1000 0000 0000 0000 0000 0000 0000 0000  ................
000000f0: 0000 0000

然后结构p_info ,blocksize 为后续压缩时使用,p_filesize 为压缩前文件大小为12

p/x hbuf
$3 = {p_progid = 0x0, p_filesize = 0x6aa8, p_blocksize = 0x6aa8}
000000e0: 1000 0000 0000 0000 0000 0000 0000 0000  ................
000000f0: 0000 0000 0000 0000 A86A 0000 A86A 0000  .........j...j..

a.upx 大小为 244+12=256;

pack2():

  1. 对PT_LOAD 段进行压缩: 对原有二进制中PT_LOAD 段内容进行压缩,压缩后加壳文件大小为6480,代码位于p_lx_elf.cpp:int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft) ,该函数会调用p_unix.cpp:319 void PackUnix::packExtent( const Extent &x, unsigned &total_in, unsigned &total_out, Filter *ft, OutputFile fo, unsigned hdr_u_len)函数 , 该函数根据是否是最长可执行PT_LOAD 段,采取不同的压缩方法:

    a) 对最长可执行PT_LOAD 段采用 compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy, 0, 0, 0, hdr_ibuf, hdr_u_len); //pakcer.cpp:1603 进行压缩,并进行loader 初始化操作,loader 会在pack3()中用到

    b) 对于非可执行段采用,r = upx_compress(hdr_ibuf, hdr_u_len, hdr_obuf, &hdr_c_len, 0, ph.method, 10, NULL, NULL); 进行压缩。

    详细分析如下:

    1)

    a) 压缩前先进行检查,读取头部内容到hdr_ibuf中, 大小为 elfheader+program header 大小为64+56×13=792。

    对第一个段数据压缩时,去除头部elfheader 内容及 elfheader+program header 大小为64+56×13=792,从该地址开始读取PT_LOAD 内容,

    $ readelf -a a.out 
    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:               0x1460
      Start of program headers:          64 (bytes into file)
      Start of section headers:          25320 (bytes into file)
      Flags:                             0x0
      Size of this header:               64 (bytes)
      Size of program headers:           56 (bytes)
      Number of program headers:         13
      Size of section headers:           64 (bytes)
      Number of section headers:         31
      Section header string table index: 30
    Program Headers:
      Type           Offset             VirtAddr           PhysAddr
                     FileSiz            MemSiz              Flags  Align
      PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                     0x00000000000002d8 0x00000000000002d8  R      0x8
      INTERP         0x0000000000000318 0x0000000000000318 0x0000000000000318
                     0x000000000000001c 0x000000000000001c  R      0x1
          [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
      LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                     0x0000000000000e70 0x0000000000000e70  R      0x1000
      LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                     0x0000000000002cf5 0x0000000000002cf5  R E    0x1000
      LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                     0x0000000000000688 0x0000000000000688  R      0x1000
      LOAD           0x0000000000004c98 0x0000000000005c98 0x0000000000005c98
                     0x00000000000003c8 0x00000000000003e0  RW     0x1000
      DYNAMIC        0x0000000000004ca8 0x0000000000005ca8 0x0000000000005ca8
                     0x0000000000000210 0x0000000000000210  RW     0x8
      NOTE           0x0000000000000338 0x0000000000000338 0x0000000000000338
                     0x0000000000000020 0x0000000000000020  R      0x8
      NOTE           0x0000000000000358 0x0000000000000358 0x0000000000000358
                     0x0000000000000044 0x0000000000000044  R      0x4
      GNU_PROPERTY   0x0000000000000338 0x0000000000000338 0x0000000000000338
                     0x0000000000000020 0x0000000000000020  R      0x8
      GNU_EH_FRAME   0x0000000000004260 0x0000000000004260 0x0000000000004260
                     0x00000000000000d4 0x00000000000000d4  R      0x4
      GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                     0x0000000000000000 0x0000000000000000  RW     0x10
      GNU_RELRO      0x0000000000004c98 0x0000000000005c98 0x0000000000005c98
                     0x0000000000000368 0x0000000000000368  R      0x1

    读取大小为0xe70-0x318=0xB58 大小为2904,对读取的数据进行压缩,因为第一个PT_LOAD 段为只读段,非可执行段,因此采用 compress(ibuf, ph.u_len, obuf); 该函数进行压缩。压缩完的数据存储在obuf中。

    b) 由于首次压缩,对hdr_ibuf 内容进行压缩,r = upx_compress(hdr_ibuf, hdr_u_len, hdr_obuf, &hdr_c_len, 0, ph.method, 10, NULL, NULL); 压缩内容存储在hdr_obuf 中;压缩完头部后,使用binfo 存储压缩前后一些信息,

    (gdb) l
                ph.saved_u_adler = upx_adler32(hdr_ibuf, hdr_u_len, init_u_adler);// 进行校验和计算,
                ph.saved_c_adler = upx_adler32(hdr_obuf, hdr_c_len, init_c_adler);
                ph.u_adler = upx_adler32(ibuf, ph.u_len, ph.saved_u_adler);
                ph.c_adler = upx_adler32(obuf, ph.c_len, ph.saved_c_adler);
                end_u_adler = ph.u_adler;
                memset(&tmp, 0, sizeof(tmp));
                set_te32(&tmp.sz_unc, hdr_u_len);
                set_te32(&tmp.sz_cpr, hdr_c_len);
                tmp.b_method = (unsigned char) ph.method;//存储压缩使用的方法
    (gdb) p/x tmp
    $31 = {sz_unc = 0x318, sz_cpr = 0xde, b_method = 0x2, b_ftid = 0x0, b_cto8 = 0x0, b_unused = 0x0}

    写入binfo 信息,写入压缩后的header 内容。

    00000100: 1803 0000 DE00 0000 0200 0000 F6FB 21FF  ..............!.
    00000110: 7F45 4C46 0201 0100 0300 3E00 0D60 140F  .ELF......>..`..
    00000120: 77C9 0E76 4017 E862 2213 3800 0D2C 60DD  w..v@..b".8..,`.
    00000130: 7705 1F00 1E00 060F 0427 074B 7621 8FD8  w........'.Kv!..
    00000140: 0208 6737 C823 9B3D 1803 0F07 1C00 2BEC  ..g7.#.=......+.
    00000150: 805C 0104 0000 B0CB 5ED8 700E 0700 1037  .\......^.p....7
    00000160: 050F BD90 4716 07F5 2C00 1061 87B0 906F  ....G...,..a...o
    00000170: E088 0607 3DFB 0D6C 3712 984C 0F98 5C16  ....=..l7..L..\.
    00000180: E4E4 8507 C803 E037 EC20 831C 02A8 A85C  .......7. .....\
    00000190: 070E 6121 2F10 024F 041E 59B0 C103 384F  ..a!/..O..Y...8O
    000001a0: 0720 0082 1DD9 4237 5827 2017 F2C8 0744  . ....B7X' ....D
    000001b0: 0004 073B 20FB 53E5 7464 6F50 3760 4216  ...; .S.tdoP7`B.
    000001c0: F2C8 660F 07D4 0056 60BB C36F 5137 0600  ..f....V`..oQ7..
    000001d0: 0084 10EC 10DE 526F 8760 180B 7B68 0307  ......Ro.`..{h..
    000001e0: 6700 0000 0000 0090 00FF                 g.........

    然后写入binfo 结构tmp,写入压缩后的PT_LOAD 数据内容

    (gdb) p/x tmp
    $35 = {sz_unc = 0xb58, sz_cpr = 0x3d5, b_method = 0x2, b_ftid = 0x0, b_cto8 = 0x0, b_unused = 0x0}
    000001e0: 6700 0000 0000 0090 00FF 580B 0000 D503  g.........X.....
    000001f0: 0000 0200 0000 DB7F BBFD 2F6C 6962 3634  ........../lib64
    .....
    000005a0: 1F19 9001 19A8 20B0 0119 9001 21B8 9001  ...... .....!...
    000005b0: 1990 22C0 230D 8C01 19C8 24FF 0008 C880  ..".#.....$.....
    000005c0: 1725 0000 0000 0000 0024 FF              .%.......$.                                                             

    到此地一个PT_LOAD 段压缩完成,计算目前的加壳文件大小为 256+sizeof(b_info)+sizeof(hdr_obuf)+sizeof(b_info)+sizeof(obuf)=256+12+0xde+12+0x3d5=0x5cb.

    (gdb) n
    444         total_in += ph.u_len;
    (gdb) n
    445         total_out += ph.c_len;

    2) 压缩第二个段,为可执行段, 采用该函数进行压缩

      Type           Offset             VirtAddr           PhysAddr
                     FileSiz            MemSiz              Flags  Align
                     ....
     LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                     0x0000000000002cf5 0x0000000000002cf5  R E    0x1000
    ​
    compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
                                    0, 0, 0, hdr_ibuf, hdr_u_len); //pakcer.cpp:1603
    (gdb) p/x tmp
    $41 = {sz_unc = 0x2cf5, sz_cpr = 0xe7d, b_method = 0x2, b_ftid = 0x49, b_cto8 = 0x2, b_unused = 0x0}

    同样写入binfo结构,写入压缩后的数据

    000005c0: 1725 0000 0000 0000 0024 FFF5 2C00 007D  .%.......$..,..}
    000005d0: 0E00 0002 4902 00BE FDFF FFF3 0F1E FA48  ....I..........H
    .......
    00001440: 0689 9FC3 0700 80AB 78E7 D901 0000 0000  ........x.......
    00001450: 0000 20FF
    (gdb) n
    444         total_in += ph.u_len;
    (gdb) n
    445         total_out += ph.c_len;

    更新total_in,total_out. total_in ,为已经被压缩的长度总和, total_out 为目前压缩完成长度总和

    到此a.upx 长度为:0x5cb+12+0xe7d=0x1454:p_lx_elf.cpp:4026

    3) 压缩第3个段:

    Type           Offset             VirtAddr           PhysAddr
                   FileSiz            MemSiz              Flags  Align
                     ....
    LOAD           0x0000000000004000 0x0000000000004000 0x0000000000004000
                   0x0000000000000688 0x0000000000000688  R      0x1000
                   
     (gdb) p/x tmp
    $11 = {sz_unc = 0x688, sz_cpr = 0x3cd, b_method = 0x2, b_ftid = 0x0, b_cto8 = 0x0, b_unused = 0x0}

    同理该段为只读段,采用压缩方法(void) compress(ibuf, ph.u_len, obuf); 进行压缩,压缩后存储到obuf中,

    同上,还是先写入一个binfo结构,然后再写入压缩的数据。

        if (ph.c_len < ph.u_len) {
    (gdb) n
    436             fo->write(obuf, ph.c_len);
    (gdb) n
    438             verifyOverlappingDecompression(ft);
    (gdb) n
    444         total_in += ph.u_len;
    (gdb) n
    445         total_out += ph.c_len;
    (gdb) p total_in
    $12 = (unsigned int &) @0x7fffffffcf14: 16877
    (gdb) p total_out
    $13 = (unsigned int &) @0x7fffffffcf18: 4912
    (gdb) p ph.c_len
    $14 = 973
    (gdb) n
    338     for (off_t rest = x.size; 0 != rest; ) {
    (gdb) p total_out 
    $15 = (unsigned int &) @0x7fffffffcf18: 5885
    00001450: 0000 20FF 8806 0000 CD03 0000 0200 0000  .. .............
    00001460: BFFD FFF3 0100 0200 7262 0068 696E 666F  ........rb.hinfo
    ...
    000017f0: 2920 8D04 0428 8C05 440E 3086 0648 DAAD  ) ...(..D.0..H..
    00001800: 6DFF 0E38 8307 470E 406E 0741 0F02 2842  m..8..G.@n.A..(B
    00001810: 1FF8 6865 D902 1810 48D3 3C00 01A3 6B63  ..he....H.<...kc
    00001820: 6847 05DF 0000 0000 0000 8004 FF         hG...........

    a.upx 长度为0x1454+12+0x3cd=0x182D。

    4) 对第4个段进行压缩

     Type           Offset             VirtAddr           PhysAddr
                   FileSiz            MemSiz              Flags  Align
                     ....
     LOAD           0x0000000000004c98 0x0000000000005c98 0x0000000000005c98
                    0x00000000000003c8 0x00000000000003e0  RW     0x1000
    (gdb) n
    428         fo->write(&tmp, sizeof(tmp));
    (gdb) p/x tmp
    $20 = {sz_unc = 0x3c8, sz_cpr = 0x10e, b_method = 0x2, b_ftid = 0x0, b_cto8 = 0x0, b_unused = 0x0}
    (gdb) n
    429         b_len += sizeof(b_info);
    (gdb) n
    431         if (ft) {
    (gdb) n
    435         if (ph.c_len < ph.u_len) {
    (gdb) n
    436             fo->write(obuf, ph.c_len);
    (gdb) n
    438             verifyOverlappingDecompression(ft);
    (gdb) n
    444         total_in += ph.u_len;
    (gdb) n
    445         total_out += ph.c_len;
    (gdb) n
    338     for (off_t rest = x.size; 0 != rest; ) {
    (gdb) p total_in
    $21 = (unsigned int &) @0x7fffffffcf14: 17845
    (gdb) p total_out
    $22 = (unsigned int &) @0x7fffffffcf18: 6155
    00001820: 6847 05DF 0000 0000 0000 8004 FFC8 0300  hG..............
    00001830: 000E 0100 0002 0000 0002 39D8 E440 1500  ..........9..@..
    ...
    00001920: 9041 C0D0 E032 D841 06F0 0012 7F12 0509  .A...2.A........
    00001930: 830C 1212 4FA8 840B EC08 6017 80A7 0000  ....O.....`.....
    00001940: 0040 0020 0100 FF                        .@. ...
    ​

    a.upx 长度为:0x182D+12+0x10e=0x1947 ,

    total_in= 16877+0x3c8=17845

    total_out=5885+0x10e=6155

    到此PT_LOAD 段压缩完成。

    5) sz_pack2a = fpad4(fo); //p_lx_elf.cpp:93 ,该函数其实是为了对齐,目前长度为6471% 4=3,因此 对齐代码如下:

     off_t len = fo->st_size();
    (gdb) n
    95      unsigned d = 3u & (0 - len);
    (gdb) p len
    $1 = 6471
    (gdb) n
    96      unsigned zero = 0;
    (gdb) p d
    $2 = 1
    (gdb) n
    97      fo->write(&zero, d);
    (gdb) pd
    Undefined command: "pd".  Try "help".
    (gdb) p d
    $3 = 1
    (gdb) n
    98      return d + len;
    a.upx 内容如下:
    ​
    00001940: 0040 0020 0100 FF00                      .@. ....

    需要产长度+1 即可,sz_pack2a=0x1948

loader组成分析

参考 手脱定制版的android SO UPX壳_江西省遂川县杰出青年代表的博客-CSDN博客

loader 初始化位于pack2 comresswithfilter() 函数中,源码调用流程:p_lx_elf.cpp:3989:int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft) ,对最大的可执行段 调用:

if (k == nk_f || !is_shlib) {    // nk_f 记录的是最长的可执行的PT_LOAD 段,在此判断,并进行压缩。
                packExtent(x, total_in, total_out,
                    (k==nk_f ? &ft : 0 ), fo, hdr_u_len);// 传入参数不同,可执行段传入Filter地址,否则传入0,p_unix.cpp:327(gdb 调试 x86_64)
            }

p_unix.cpp:327 , void PackUnix::packExtent( const Extent &x, unsigned &total_in, unsigned &total_out, Filter *ft, OutputFile *fo, unsigned hdr_u_len)h函数调用compressWithFilters():

if (ft) { // 如果是最大的可执行pt_load 段,在该方法进行压缩。
            // compressWithFilters() updates u_adler _inside_ compress();
            // that is, AFTER filtering.  We want BEFORE filtering,
            // so that decompression checks the end-to-end checksum.
            end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
            ft->buf_len = l;
​
                // compressWithFilters() requirements?
            ph.filter = 0;
            ph.filter_cto = 0;
            ft->id = 0;
            ft->cto = 0;
​
            compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
                                0, 0, 0, hdr_ibuf, hdr_u_len); //pakcer.cpp:1603
        }
 Packer::compressWithFilters (this=0x5555557952c0, i_ptr=0x55555579c340 "\363\017\036\372H\203\354\bH\213\005\311O", i_len=11509, 
    o_ptr=0x5555557a2e10 "/lib64/ld-linux-x86-64.so.2", f_ptr=0x55555579c340 "\363\017\036\372H\203\354\bH\213\005\311O", f_len=11509, hdr_ptr=0x0, hdr_len=0, 
    parm_ft=0x7fffffffcfa0, overlap_range=2048, cconf=0x0, filter_strategy=2, inhibit_compression_check=false) at packer.cpp:1390
#1  0x0000555555612ea1 in Packer::compressWithFilters (this=0x5555557952c0, ft=0x7fffffffcfa0, overlap_range=2048, cconf=0x0, filter_strategy=2, filter_off=0, 
    ibuf_off=0, obuf_off=0, hdr_ptr=0x0, hdr_len=0, inhibit_compression_check=false) at packer.cpp:1614
#2  0x00005555555f424b in PackUnix::packExtent (this=0x5555557952c0, x=..., total_in=@0x7fffffffcf14: 3696, total_out=@0x7fffffffcf18: 1203, ft=0x7fffffffcfa0, 
    fo=0x7fffffffd1e0, hdr_u_len=0) at p_unix.cpp:366
#3  0x00005555555c2e5e in PackLinuxElf64::pack2 (this=0x5555557952c0, fo=0x7fffffffd1e0, ft=...) at p_lx_elf.cpp:4055
#4  0x00005555555f3e34 in PackUnix::pack (this=0x5555557952c0, fo=0x7fffffffd1e0) at p_unix.cpp:302
#5  0x000055555560e030 in Packer::doPack (this=0x5555557952c0, fo=0x7fffffffd1e0) at packer.cpp:100
#6  0x0000555555618315 in PackMaster::pack (this=0x7fffffffd2b0, fo=0x7fffffffd1e0) at packmast.cpp:262
#7  0x0000555555635f42 in do_one_file (iname=0x7fffffffe1c3 "a", oname=0x7fffffffd890 "a.upx") at work.cpp:158
#8  0x0000555555636377 in do_files (i=1, argc=2, argv=0x7fffffffdde8) at work.cpp:271
#9  0x00005555555a55a6 in main (argc=2, argv=0x7fffffffdde8) at main.cpp:1539
​

具体初始化流程如下:

  • 使用 stub_amd64_linux_elf_entry 初始化linker ,packer.cpp:1131,初始化流程位于linker.cpp:123,stub_amd64_linux_elf_entry:0x1850(6224)-----9547 文件尾部内容如下:

    Sections:
    Idx Name          Size      VMA               LMA               File off  Algn  Flags
      0 ELFMAINX      0000000f  0000000000000000  0000000000000000  00000040  2**0  CONTENTS, RELOC, READONLY
      1 NRV_HEAD      00000066  0000000000000000  0000000000000000  0000004f  2**0  CONTENTS, READONLY
      2 NRV2E         000000ba  0000000000000000  0000000000000000  000000b5  2**0  CONTENTS, RELOC, READONLY
      3 NRV2D         000000a1  0000000000000000  0000000000000000  0000016f  2**0  CONTENTS, RELOC, READONLY
      4 NRV2B         00000093  0000000000000000  0000000000000000  00000210  2**0  CONTENTS, RELOC, READONLY
      5 LZMA_ELF00    00000064  0000000000000000  0000000000000000  000002a3  2**0  CONTENTS, RELOC, READONLY
      6 LZMA_DEC10    000009f7  0000000000000000  0000000000000000  00000307  2**0  CONTENTS, READONLY
      7 LZMA_DEC20    000009f7  0000000000000000  0000000000000000  00000cfe  2**0  CONTENTS, READONLY
      8 LZMA_DEC30    00000018  0000000000000000  0000000000000000  000016f5  2**0  CONTENTS, READONLY
      9 NRV_TAIL      00000000  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, READONLY
     10 ELFMAINY      0000003a  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, RELOC, READONLY
     11 ELFMAINZ      000000ef  0000000000000000  0000000000000000  00001747  2**0  CONTENTS, RELOC, READONLY
    SYMBOL TABLE:
    0000000000000000 l    d  NRV_HEAD   0000000000000000 NRV_HEAD
    0000000000000000 l    d  LZMA_DEC30 0000000000000000 LZMA_DEC30
    0000000000000000 l    d  ELFMAINY   0000000000000000 ELFMAINY
    0000000000000000 l    d  ELFMAINZ   0000000000000000 ELFMAINZ
    0000000000000000 l    d  ELFMAINX   0000000000000000 ELFMAINX
    0000000000000000 l    d  NRV2E  0000000000000000 NRV2E
    0000000000000000 l    d  NRV2D  0000000000000000 NRV2D
    0000000000000000 l    d  NRV2B  0000000000000000 NRV2B
    0000000000000000 l    d  LZMA_ELF00 0000000000000000 LZMA_ELF00
    0000000000000000 l    d  LZMA_DEC10 0000000000000000 LZMA_DEC10
    0000000000000000 l    d  LZMA_DEC20 0000000000000000 LZMA_DEC20
    0000000000000000 l    d  NRV_TAIL   0000000000000000 NRV_TAIL
    0000000000000000 g       ELFMAINX   0000000000000000 _start
    0000000000000000         *UND*  0000000000000000 O_BINFO
    ​
    RELOCATION RECORDS FOR [ELFMAINX]:
    OFFSET           TYPE              VALUE
    0000000000000003 R_X86_64_PC32     ELFMAINZ+0x00000000000000d2
    ​
    RELOCATION RECORDS FOR [NRV2E]:
    OFFSET           TYPE              VALUE
    00000000000000af R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [NRV2D]:
    OFFSET           TYPE              VALUE
    0000000000000096 R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [NRV2B]:
    OFFSET           TYPE              VALUE
    000000000000008b R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    0000000000000053 R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [LZMA_ELF00]:
    OFFSET           TYPE              VALUE
    0000000000000006 R_X86_64_PC32     LZMA_DEC30+0x0000000000000012
    ​
    RELOCATION RECORDS FOR [ELFMAINY]:
    OFFSET           TYPE              VALUE
    0000000000000018 R_X86_64_PC32     ELFMAINZ+0x0000000000000003
    ​
    RELOCATION RECORDS FOR [ELFMAINZ]:
    OFFSET           TYPE              VALUE
    00000000000000eb R_X86_64_32       O_BINFO

loader 初始化

代码分析如下:由于pack3()返回的loader内容为linker->output内容,这里重点关注下output赋值操作。

void Packer::initLoader(const void *pdata, int plen, int small)
{
    delete linker;
    linker = newLinker(); 
gdb) s
PackLinuxElf64amd::newLinker (this=0x1e8500000e7d) at p_lx_elf.cpp:802
802 {
(gdb) s
803     return new ElfLinkerAMD64; 
​
    assert(bele == linker->bele);
    linker->init(pdata, plen);//linker.cpp:123 pdata=
​
    unsigned size;
    char const * const ident = getIdentstr(&size, small);
    linker->addSection("IDENTSTR", ident, size, 0);
}
(gdb) p pdata 
$15 = (const void *) 0x5555556a8c20 <stub_amd64_linux_elf_entry>
(gdb) p plen
$16 = 9547
(gdb) n
1136        linker->init(pdata, plen);//linker.cpp:123
  • linker.cpp:123, stub_amd64_linux_elf_entry 数组,二进制数据保存在linker input 中,并且初始化output 长度为0x4000=16384

        const upx_byte *pdata = (const upx_byte *) pdata_v; 
        ....
            inputlen = plen;
            input = new upx_byte[inputlen + 1];
            if (inputlen)
                memcpy(input, pdata, inputlen);
        output = new upx_byte[inputlen ? inputlen : 0x4000]; //output 初始化大小为0x4000 
        outputlen = 0;
            int pos = find(input, inputlen, "Sections:\n", 10); //pos=6624
            assert(pos != -1);
            char *psections = (char *) input + pos; //找到sections 信息开始位置
    ​
            char *psymbols = strstr(psections, "SYMBOL TABLE:\n");//找到symbols 开始位置
            assert(psymbols != NULL);
    ​
            char *prelocs = strstr(psymbols, "RELOCATION RECORDS FOR ");//找到RELOCATION 开始位置。
            assert(prelocs != NULL);
    ​
            preprocessSections(psections, psymbols); //linker.cpp:182 preprocessSections(),将位于amd64-linux.elf-entry.h,如上中11个section,添加到sections[]数组中
            preprocessSymbols(psymbols, prelocs);  //linker.cpp:204(去除注释部分内容),preprocessSymbols(),将symbol 添加到symbols[]数组中
            preprocessRelocations(prelocs, (char *) input + inputlen);//preprocessRelocations()同上,初始化relocations[]数组
            addLoader("*UND*");
  • void ElfLinker::preprocessSections(char *start, char *end) 代码位于linker.cpp:182, 基本思想为 从psections开始到psymbols结束,将获取到的section信息 添加到linker sections 数组中,并在末尾添加section ABS 及UND section。

    for (nsections = 0; start < end; start = 1 + nextl) {
    ....
     if (sscanf(start, "%*d %1023s %x %*d %*d %x 2**%d", name, &size, &offset, &align) == 4) {
                char *n = strstr(start, name);
                n[strlen(name)] = 0;
                addSection(n, input + offset, size, align);//linker.cpp:314
                ...
          }
       }
        addSection("*ABS*", NULL, 0, 0);
        addSection("*UND*", NULL, 0, 0);
    Sections:
      Idx Name          Size      VMA               LMA               File off  Algn  Flags
      0 ELFMAINX      0000000f  0000000000000000  0000000000000000  00000040  2**0  CONTENTS, RELOC, READONLY
      1 NRV_HEAD      00000066  0000000000000000  0000000000000000  0000004f  2**0  CONTENTS, READONLY
      2 NRV2E         000000ba  0000000000000000  0000000000000000  000000b5  2**0  CONTENTS, RELOC, READONLY
      3 NRV2D         000000a1  0000000000000000  0000000000000000  0000016f  2**0  CONTENTS, RELOC, READONLY
      4 NRV2B         00000093  0000000000000000  0000000000000000  00000210  2**0  CONTENTS, RELOC, READONLY
      5 LZMA_ELF00    00000064  0000000000000000  0000000000000000  000002a3  2**0  CONTENTS, RELOC, READONLY
      6 LZMA_DEC10    000009f7  0000000000000000  0000000000000000  00000307  2**0  CONTENTS, READONLY
      7 LZMA_DEC20    000009f7  0000000000000000  0000000000000000  00000cfe  2**0  CONTENTS, READONLY
      8 LZMA_DEC30    00000018  0000000000000000  0000000000000000  000016f5  2**0  CONTENTS, READONLY
      9 NRV_TAIL      00000000  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, READONLY
     10 ELFMAINY      0000003a  0000000000000000  0000000000000000  0000170d  2**0  CONTENTS, RELOC, READONLY
     11 ELFMAINZ      000000ef  0000000000000000  0000000000000000  00001747  2**0  CONTENTS, RELOC, READONLY

    sec 共初始化了14个section ,包含ABS ,UND section 信息。

  • 同理处理ElfLinker::Symbol *ElfLinker::addSymbol(const char *name, const char *section, upx_uint64_t offset) 代码位于linker.cpp:330 ,将获取到的symbols 信息添加到linker 数组symbols中

    SYMBOL TABLE:
    0000000000000000 l    d  NRV_HEAD   0000000000000000 NRV_HEAD
    0000000000000000 l    d  LZMA_DEC30 0000000000000000 LZMA_DEC30
    0000000000000000 l    d  ELFMAINY   0000000000000000 ELFMAINY
    0000000000000000 l    d  ELFMAINZ   0000000000000000 ELFMAINZ
    0000000000000000 l    d  ELFMAINX   0000000000000000 ELFMAINX
    0000000000000000 l    d  NRV2E  0000000000000000 NRV2E
    0000000000000000 l    d  NRV2D  0000000000000000 NRV2D
    0000000000000000 l    d  NRV2B  0000000000000000 NRV2B
    0000000000000000 l    d  LZMA_ELF00 0000000000000000 LZMA_ELF00
    0000000000000000 l    d  LZMA_DEC10 0000000000000000 LZMA_DEC10
    0000000000000000 l    d  LZMA_DEC20 0000000000000000 LZMA_DEC20
    0000000000000000 l    d  NRV_TAIL   0000000000000000 NRV_TAIL
    0000000000000000 g       ELFMAINX   0000000000000000 _start
    0000000000000000         *UND*  0000000000000000 O_BINFO

    共有14个symbol ,其中最后一列为 symbol 的名称,第4列为symbol对应的section 名称。

    for (nsymbols = 0; start < end; start = 1 + nextl) {
    ....
    else if (sscanf(start, "%x%*c%*c%*c%*c%*c%*c%*c%*c %1023s %*x %1023s",
    #endif
                            &offset, section, symbol) == 3)
            {
                                char *s = strstr(start, symbol);
                                s[strlen(symbol)] = 0;
                                if (strcmp(section, "*UND*") == 0)
                                    offset = 0xdeaddead;
                                assert(strcmp(section, "*ABS*") != 0);
                                addSymbol(s, section, offset);
                            }

    在 symbol 名称为O_BINFO 时,section 名称为" *UND* ", offset=0xdeaddead,其他symbol offset 为0

  • 对linker relocations 数组初始化,

    RELOCATION RECORDS FOR [ELFMAINX]:
    OFFSET           TYPE              VALUE
    0000000000000003 R_X86_64_PC32     ELFMAINZ+0x00000000000000d2
    ​
    RELOCATION RECORDS FOR [NRV2E]:
    OFFSET           TYPE              VALUE
    00000000000000af R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [NRV2D]:
    OFFSET           TYPE              VALUE
    0000000000000096 R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    000000000000005c R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [NRV2B]:
    OFFSET           TYPE              VALUE
    000000000000008b R_X86_64_PC32     NRV_HEAD+0x0000000000000021
    0000000000000053 R_X86_64_PC32     ELFMAINY+0xfffffffffffffffc
    ​
    RELOCATION RECORDS FOR [LZMA_ELF00]:
    OFFSET           TYPE              VALUE
    0000000000000006 R_X86_64_PC32     LZMA_DEC30+0x0000000000000012
    ​
    RELOCATION RECORDS FOR [ELFMAINY]:
    OFFSET           TYPE              VALUE
    0000000000000018 R_X86_64_PC32     ELFMAINZ+0x0000000000000003
    ​
    RELOCATION RECORDS FOR [ELFMAINZ]:
    OFFSET           TYPE              VALUE
    00000000000000eb R_X86_64_32       O_BINFO
            if (sscanf(start, "RELOCATION RECORDS FOR [%[^]]", sect) == 1)
                    section = findSection(sect);
              ....
            if (sscanf(start, "%x %99s %1023s", &offset, type, symbol) == 3) {
                char *t = strstr(start, type);
                t[strlen(type)] = 0;
    .....
    ​
                if (section) {
                    addRelocation(section->name, offset, t, symbol, add);
                    // printf("relocation %s %s %x %llu preprocessed\n", section->name, symbol, offset,
                    // (unsigned long long) add);
                }
               ...
               }

    以第一个reloc 为例: section->name="ELFMAINX" ,offset=3,t="R_X86_64_PC32",add=d2 ,symbol="ELFMAINZ"

    ElfLinker::Relocation *ElfLinker::addRelocation(const char *section, unsigned off, const char *type,
                                                    const char *symbol, upx_uint64_t add) {
        if (update_capacity(nrelocations, &nrelocations_capacity))
            relocations = static_cast<Relocation **>(
                realloc(relocations, (nrelocations_capacity) * sizeof(Relocation *)));
        assert(relocations != NULL);
        Relocation *rel = new Relocation(findSection(section), off, type, findSymbol(symbol), add);
        relocations[nrelocations++] = rel;
        return rel;
    }

    最后一个reloction ,add 为0

    RELOCATION RECORDS FOR [ELFMAINZ]:
    OFFSET           TYPE              VALUE
    00000000000000eb R_X86_64_32       O_BINFO
    symbol="O_BINFO",不包含+0x 也不包含-0x
    char *p = strstr(symbol, "+0x");
                if (p == NULL)
                    p = strstr(symbol, "-0x");
                if (p) {
                    char sign = *p;
                    *p = 0; // terminate the symbol name
                    p += 3;
                    assert(strlen(p) == 8 || strlen(p) == 16);
    #if (ACC_CC_MSC && (_MSC_VER < 1800))
                    unsigned a = 0, b = 0;
                    if (sscanf(p, "%08x%08x", &a, &b) == 2)
                        add = ((upx_uint64_t) a << 32) | b;
                    else
                        add = a;
    #else
                    char *endptr = NULL;
                    add = strtoull(p, &endptr, 16);
                    assert(endptr && *endptr == '\0');
    #endif
                    if (sign == '-')
                        add = 0 - add;
                }
               //

    共初始化10个relocation。到此loader 初始化完成。

lodar 组成内容

返回到linker.cpp 178

addLoader("*UND*");
// 该section 为upx 最后添加的size=0,该初始化只是初始化了linker->head=linker->tail 指向了该section,output内容没有改变 outputlen=0。

返回到packer.cpp:1139

 char const * const ident = getIdentstr(&size, small); //添加版权信息,作为IDENTSTR section。packer.cpp:1054
    linker->addSection("IDENTSTR", ident, size, 0); //长度129

p_lx_elf.cpp:1206:

struct b_info h; memset(&h, 0, sizeof(h));
    unsigned fold_hdrlen = 0;
    cprElfHdr1 const *const hf = (cprElfHdr1 const *)fold;
    fold_hdrlen = umax(0x80, sizeof(hf->ehdr) +
        get_te16(&hf->ehdr.e_phentsize) * get_te16(&hf->ehdr.e_phnum) +
            sizeof(l_info) );
    h.sz_unc = ((szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen));// fold_hdrlen=188,hf->ehdr.e_phentsize=56,hf->ehdr.e_phnum=2,sizeof(l_info)=12
    h.b_method = (unsigned char) ph.method;    // h  {sz_unc = 2063, sz_cpr = 2576, b_method = 2 '\002', b_ftid = 73 'I', 
     h.b_ftid = (unsigned char) ph.filter;     // b_cto8 = 2 '\002', b_unused = 0 '\000'}
    h.b_cto8 = (unsigned char) ph.filter_cto;//
    unsigned char const *const uncLoader = fold_hdrlen + fold;//
​
    h.sz_cpr = MemBuffer::getSizeForCompression(h.sz_unc + (0==h.sz_unc)); //h.sz_unc=2063 h.sz_cpr长度为2063+2063/8+256=2576
    unsigned char *const cprLoader = New(unsigned char, sizeof(h) + h.sz_cpr); //compress.cpp:76
    {
    unsigned h_sz_cpr = h.sz_cpr;
    int r = upx_compress(uncLoader, h.sz_unc, sizeof(h) + cprLoader, &h_sz_cpr,
        NULL, ph.method, 10, NULL, NULL );//compress:76,对uncLoader 进行压缩,压缩后长度为h_sz_cpr,1644.压缩后内容存储在sizeof(h) + cprLoader 位置。
    h.sz_cpr = h_sz_cpr;
    if (r != UPX_E_OK || h.sz_cpr >= h.sz_unc)
        throwInternalError("loader compression failed");
    }
#if 0  //{  debugging only
    if (M_IS_LZMA(ph.method)) {
        ucl_uint tmp_len = h.sz_unc;  // LZMA uses this as EOF
        unsigned char *tmp = New(unsigned char, tmp_len);
        memset(tmp, 0, tmp_len);
        int r = upx_decompress(sizeof(h) + cprLoader, h.sz_cpr, tmp, &tmp_len, h.b_method, NULL);
        if (r == UPX_E_OUT_OF_MEMORY)
            throwOutOfMemoryException();
        printf("\n%d %d: %d %d %d\n", h.b_method, r, h.sz_cpr, h.sz_unc, tmp_len);
        for (unsigned j=0; j < h.sz_unc; ++j) if (tmp[j]!=uncLoader[j]) {
            printf("%d: %x %x\n", j, tmp[j], uncLoader[j]);
        }
        delete[] tmp;
    }
#endif  //}
    unsigned const sz_cpr = h.sz_cpr;
    set_te32(&h.sz_cpr, h.sz_cpr);
    set_te32(&h.sz_unc, h.sz_unc);
    memcpy(cprLoader, &h, sizeof(h));//cprLoader 内容为 h 内容+uncLoader 压缩后内容。// h{sz_unc = 2063, sz_cpr = 1644, b_method = 2 '\002', b_ftid = 73 'I', 
                                                                                //b_cto8 = 2 '\002', b_unused = 0 '\000'}
    // This adds the definition to the "library", to be used later.
    linker->addSection("FOLDEXEC", cprLoader, sizeof(h) + sz_cpr, 0);//linker.cpp:314 ,长度为 1644+12=1656
    delete [] cprLoader;

以上代码大致意思为 uncloader 内容为 读取 stub_amd64_linux_elf_fold+188 以后内容,长度为2251-188=2063 。binfo+对uncloader 进行压缩,作为cprloader 内容,并且将 cprloader 内容作为 FOLDEXEC section

p_lx_elf.cpp:1257

 addStubEntrySections(ft);// p_lx_elf.cpp:625 
#0  ElfLinker::addLoader (this=0x7fffffffc050, sname=0x0) at linker.cpp:363
#1  0x00005555555a0267 in ElfLinker::addLoader (this=0x5555557945a0, s=0x55555565b94f "ELFMAINX", ap=0x7fffffffbfe0) at linker.cpp:424
#2  0x0000555555611215 in Packer::addLoaderVA (this=0x5555557952c0, s=0x55555565b94f "ELFMAINX") at packer.cpp:1173
#3  0x0000555555610e72 in Packer::addLoader (this=0x5555557952c0, a=0x55555565b94f "ELFMAINX", b=0x0) at packer.cpp:1149
#4  0x00005555555b4b2a in PackLinuxElf::addStubEntrySections (this=0x5555557952c0) at p_lx_elf.cpp:626

"ELFMAINX” ,将section->input 内容添加到output中长度为15.

     memcpy(output + outputlen, section->input, section->size);
    section->output = output + outputlen;

同理依次添加

NRV_HEAD,NRV2B,NRV_TAIL

outputlen=0xf+0x66+0x93+0=0x108

addLoader("ELFMAINY,IDENTSTR", NULL);
ELFMAINY,IDENTSTR

outputlen=0x108+0x3a+129=0x1c3

"+40,ELFMAINZ"
​
if (sect[0] == '+') // alignment
        {
            assert(tail);
            unsigned l = hex(sect[2]) - tail->offset - tail->size;//
            unsigned m = hex(sect[1]);
            if (m) {
                l %= hex(sect[1]); //+40 , m=4 ,l=1
            }
            if (l) {
                if (sect[3] == 'D')
                    alignData(l);
                else
                    alignCode(l);
                tail->size += l;
            }
        }
linker.h:101
        virtual void alignCode(unsigned len) { alignWithByte(len, 0); }
 linker.cpp:539:
 void ElfLinker::alignWithByte(unsigned len, unsigned char b) {
    memset(output + outputlen, b, len);
    outputlen += len;
}

"+40" 会对output 内容修改,并增加outplen长度。

outputlen=0x1c3+1+0xef=0x2b3

addLoader("FOLDEXEC", NULL);

outputlen=0x2b3+1656=2347 ,即loader大小。

loader组成部分分析完成。p_lx_elf.cpp:1259

pack3() :

源码位于p_unix.cpp:302,

   PackUnix::pack (this=0x5555557952c0, fo=0x7fffffffd1e0) at p_unix.cpp:302
   302      if (pack2(fo, ft)) {
   (gdb) n
   309      pack3(fo, ft);  // append loader
   (gdb) s
   PackLinuxElf64::pack3 (this=0xc0000000d, fo=0x7fffffffcee0, ft=...) at p_lx_elf.cpp:492
   492  {
   (gdb) n
   493      off_t flen = super::pack3(fo, ft);  // loader follows compressed PT_LOADs
   (gdb) s
   PackLinuxElf::pack3 (this=0x555555795b50, fo=0x10, ft=...) at p_lx_elf.cpp:324
   324  {
   (gdb) n
   326      unsigned const zero = 0;
   
       unsigned const t = (4 & len) ^ ((!!xct_off)<<2);  // 0 or 4
       fo->write(&zero, t); // t=0
       len += t;  // force sz_pack2 (0 mod 8)  [see below] len=0x1948
   
       set_te32(&disp, sz_elf_hdrs + sizeof(p_info) + sizeof(l_info) +
           (!!xct_off & !!opt->o_unix.android_shlib));  // |1 iff android shlib,sz_elf_hdrs=232,sizeof(p_info) =12,
       fo->write(&disp, sizeof(disp));  // offset(b_info) sizeof(l_info)=12 ,disp=256
       len += sizeof(disp); // len=len+4 ==len=0x1948+4=0x194C
       set_te32(&disp, len);  // distance back to beginning (detect dynamic reloc)elf文件头部到目前位置的长度
       fo->write(&disp, sizeof(disp)); //写入当前长度0x194C
       len += sizeof(disp); // len=0x194C+4=0x1950
   00001930: 830C 1212 4FA8 840B EC08 6017 80A7 0000  ....O.....`.....
   00001940: 0040 0020 0100 FF00 0001 0000 4C19 0000  .@. ........L...

到此,目前a.upx 长度为 0x1950=6480

  1. 添加loader: loader 内容为 为pack2()对可执行的pT_LOAD对进行压缩时 在函数comptesswithfilter(),根据stub/amd64_linux.elf-entry.h 及md64_linux.elf-fold.h 内容初始化的lincker及loader ,返回的linker->output大小。大小为2347

  2. 对PT_LOAD gap(相邻两个PT_LOAD 段直接的间隙,即 ptload2->offset -(ptload1->offset+ptload1->fsize)大小进行压缩,压缩时,写入一个binfo 结构,然后写入压缩数据 ; binfo 内容如下:{sz_unc = 400, sz_cpr = 14, b_method = 2 '\002', b_ftid = 0 '\000', b_cto8 = 0 '\000', b_unused = 0 '\000'} ,sz_unc 压缩前的长度,sz_cpr 压缩后的长度,method 压缩才采用的方法。

      00002270: 4A00 0040 8447 2001 0000 FF00 9001 0000  J..@.G .........
      00002280: 0E00 0000 0200 0000 0084 0292 0000 0000  ................
      00002290: 0000 0000 12FF 0B03 0000 0E00 0000 0200  ................
      000022a0: 0000 002B 0092 0000 0000 0000 0080 04FF  ...+............
      000022b0: 1006 0000 0E00 0000 0200 0000 4028 0092  ............@(..
      000022c0: 0000 0000 0000 0020 01FF 
      0000227C: 9001 0000  ....                 //前12位 0190 压缩前长度 400,压缩后长度000E 14 ,使用method: 02,
      00002280: 0E00 0000 0200 0000 0084 0292 0000 0000  ................
      00002290: 0000 0000 12FF          //后边14位为压缩后数据内容。
      00002296: 0B03 0000 0E00 0000 0200  ................  //分析同上,压缩前长度030B,大小为779,压缩后为000E 为14
      000022a0: 0000 002B 0092 0000 0000 0000 0080 04FF  ...+............
      000022b0: 1006 0000 0E00 0000 0200 0000 4028 0092  ............@(.. //同上,压缩前长度为0X0610,1552,压缩后为000E为14
      000022c0: 0000 0000 0000 0020 01FF 
      000022ca: 481A 0000 7F08  ....... ..H..... // 压缩前长度0x1a48=6728,压缩后长度为087F 为:2175,binfo之后为压缩数据内容。
      000022d0: 0000 0200 0000
  到此PT_LOAD gap压缩完成,总长度为0x22d5+0x087F=0x2B54 。
  1. 写入UPX_MAGIC_LE32 内容。

  2. 对elfout 即 两个programheader 内容的赋值操作,并返回a.upx ,output 文件大小。elfout 为当前写回的文件头部内容。

    {ehdr = {e_ident = {0x7f, 0x45, 0x4c, 0x46, 0x2, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, e_type = {d = {0x3, 0x0}}, e_machine = {d = {0x3e,0x0}}, e_version = {d = {0x1, 0x0, 0x0, 0x0}}, e_entry = {d = {0x50, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_phoff = {d = {0x40, 0x0, 0x0, 0x0, 0x0, 0x0,0x0, 0x0}}, e_shoff = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_flags = {d = {0x0, 0x0, 0x0, 0x0}}, e_ehsize = {d = {0x40, 0x0}}, e_phentsize = {d = {0x38, 0x0}}, e_phnum = {d = {0x3, 0x0}}, e_shentsize = {d = {0x40, 0x0}}, e_shnum = {d = {0x0, 0x0}}, e_shstrndx = {d = {0x0, 0x0}}}, phdr = {{ p_type = {d = {0x1, 0x0, 0x0, 0x0}}, p_flags = {d = {0x5, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x7b, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x7b, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, {p_type = {d = {0x1, 0x0, 0x0, 0x0}}, p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x30, 0x0, 0x0,0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = { d = {0x78, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, {p_type = {d = {0x51, 0xe5, 0x74, 0x64}}, 
          p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, 
          p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x0, 0x0, 0x0, 0x0, 
              0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, {p_type = {d = {0x0, 0x0, 0x0, 0x0}}, p_flags = {d = {0x0, 0x0, 0x0, 
              0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0, 
              0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, 
          p_align = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}}, linfo = {l_checksum = {d = {0x0, 0x0, 0x0, 0x0}}, l_magic = {d = {0x0, 0x0, 0x0, 0x0}}, 
        l_lsize = {d = {0x0, 0x0}}, l_version = 0x0, l_format = 0x0}}
    ​

    phdr[0] 长度为 6480+2347 大小==0x227B,对齐大小为4096=0x1000

    phdr[1] vaddr= (0x227B+0xfff) & (0xf000)=0x3000

    到此,a.upx 长度为11108=0x2B64,接下来分析 pack4 源码了。 p_unix.cpp:311

pack4():

  ph = {version = 13, format = 22, method = 2, level = 8, u_len = 6728, c_len = 2175, u_adler = 3755430340, c_adler = 1167461060, u_file_size = 27304, filter = 73, 
    filter_cto = 2, n_mru = 0, header_checksum = 0, saved_u_adler = 2139826101, saved_c_adler = 2878392669, buf_offset = 0, compress_result = {method = 2, 
      level = 8, u_len = 6728, c_len = 2175, result_lzma = {pos_bits = 0, lit_pos_bits = 0, lit_context_bits = 0, dict_size = 0, fast_mode = 0, num_fast_bytes = 0, 
        match_finder_cycles = 0, num_probs = 0}, result_ucl = {result = {4294967295, 5064, 4294967295, 69, 4294967295, 21, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, 
      result_zlib = {dummy = 0}}, max_offset_found = 5064, max_match_found = 69, max_run_found = 21, first_offset_found = 1, overlap_overhead = 2048}

​ ​ ### ​ ​ ​ 根据ph 内容生成 buf 内容,即packheader 内容,具体生成算法见packhead.cpp:92 ​ ​ ​ size = 32; ​ old_chksum = get_packheader_checksum(p, size - 1); //自定义计算方法,去除前4位,后续各位相加总和 % 251。 ​ set_le32(p + 16, u_len);//0x1a68 ​ set_le32(p + 20, c_len); //0x78f ​ set_le32(p + 24, u_file_size); //0x6aa8 ​ p[28] = (unsigned char) filter; //73=0x49 ​ p[29] = (unsigned char) filter_cto;//2=0x2 ​ assert(n_mru == 0 || (n_mru >= 2 && n_mru <= 256)); ​ p[30] = (unsigned char) (n_mru ? n_mru - 1 : 0);//0 ​ } ​ set_le32(p + 8, u_adler);//0xdfd751c4 ​ set_le32(p + 12, c_adler);//0x45960ac4 ​ .......... ​ p[4] = (unsigned char) version; //{version = 13, format = 22, method = 2,level = 8} ​ p[5] = (unsigned char) format; ​ p[6] = (unsigned char) method; ​ p[7] = (unsigned char) level; ​ p[size - 1] = get_packheader_checksum(p, size - 1);//自定义计算方法,去除前4位,后续各位相加总和 % 251。 ​ ​ ​ buf 内容如下: ​ ​ ​ {0x4d, 0x50, 0x50, 0x43, 0xd, 0x16, 0x2, 0x8, 0xc4, 0x51, 0xd7, 0xdf, ​ 0xc4, 0xa, 0x96, 0x45, 0x48, 0x1a, 0x0, 0x0, 0x7f, 0x8, 0x0, 0x0, 0xa8, 0x6a, ​ 0x0, 0x0, 0x49, 0x2, 0x0, 0xa} ​ ​ p_lx_elf.cpp:4285: 定位到文件头部,对elfheader进行处理,根据elfout内容对a.upx

  ```
   p/x elfout
  {ehdr = {e_ident = {0x7f, 0x45, 0x4c, 0x46, 0x2, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, e_type = {d = {0x3, 0x0}}, e_machine = {d = {0x3e,0x0}}, e_version = {d = {0x1, 0x0, 0x0, 0x0}}, e_entry = {d = {0x50, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_phoff = {d = {0x40, 0x0, 0x0, 0x0, 0x0, 0x0,0x0, 0x0}}, e_shoff = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, e_flags = {d = {0x0, 0x0, 0x0, 0x0}}, e_ehsize = {d = {0x40, 0x0}}, e_phentsize = {d = {0x38, 0x0}}, e_phnum = {d = {0x3, 0x0}}, e_shentsize = {d = {0x40, 0x0}}, e_shnum = {d = {0x0, 0x0}}, e_shstrndx = {d = {0x0, 0x0}}}, phdr = {{
        p_type = {d = {0x1, 0x0, 0x0, 0x0}}, p_flags = {d = {0x5, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x7b, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0,0x0}}, p_memsz = {d = {0x7b, 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}},
        {p_type = {d = {0x1,0x0, 0x0, 0x0}}, p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x30, 0x0, 0x0,0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x78, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, 
        {p_type = {d = {0x51, 0xe5, 0x74, 0x64}},p_flags = {d = {0x6, 0x0, 0x0, 0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x0, 0x0, 0x0, 0x0,0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}, 
        {p_type = {d = {0x0, 0x0, 0x0, 0x0}}, p_flags = {d = {0x0, 0x0, 0x0,0x0}}, p_offset = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_vaddr = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_paddr = {d = {0x0, 0x0,0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_filesz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_memsz = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, p_align = {d = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}}}, linfo = {l_checksum = {d = {0x0, 0x0, 0x0, 0x0}}, l_magic = {d = {0x0, 0x0, 0x0, 0x0}}, l_lsize = {d = {0x0, 0x0}}, l_version = 0x0, l_format = 0x0}}
  ```
  
  同时写入linfo : 赋值在p_lx_elf.cpp:323  PackLinuxElf::pack3: linfo
  
  ```
  {l_checksum = {d = {0x88, 0x31, 0x4a, 0x68}}, l_magic = {d = {0x4d, 0x50, 0x50, 0x43}}, l_lsize = {d = {0x34, 0x9}}, l_version = 0xd,  l_format = 0x16}
  ```
  
  修改前a.upx 内容
  
  ```
  00000000: 7F45 4C46 0201 0100 0000 0000 0000 0000  .ELF............
  00000010: 0300 3E00 0100 0000 BC00 1000 0000 0000  ..>.............
  00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
  00000030: 0000 0000 4000 3800 0300 4000 0000 0000  ....@.8...@.....
  00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................
  00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  00000060: BC00 0000 0000 0000 BC00 0000 0000 0000  ................
  00000070: 0010 0000 0000 0000 0100 0000 0600 0000  ................
  00000080: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  000000a0: 7860 0000 0000 0000 0010 0000 0000 0000  x`..............
  000000b0: 51E5 7464 0600 0000 0000 0000 0000 0000  Q.td............
  000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  000000e0: 1000 0000 0000 0000 0000 0000 0000 0000  ................
  000000f0: 0000 0000 0000 0000
  ```
  
  修改后,a.upx 内容如下:
  
  ```
  00000000: 7F45 4C46 0201 0100 0000 0000 0000 0000  .ELF............
  00000010: 0300 3E00 0100 0000 5019 0000 0000 0000  ..>.....P.......
  00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
  00000030: 0000 0000 4000 3800 0300 4000 0000 0000  ....@.8...@.....
  00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................
  00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  00000060: 7B22 0000 0000 0000 7B22 0000 0000 0000  {"......{"......
  00000070: 0010 0000 0000 0000 0100 0000 0600 0000  ................
  00000080: 0000 0000 0000 0000 0030 0000 0000 0000  .........0......
  00000090: 0030 0000 0000 0000 0000 0000 0000 0000  .0..............
  000000a0: 7830 0000 0000 0000 0010 0000 0000 0000  x0..............
  000000b0: 51E5 7464 0600 0000 0000 0000 0000 0000  Q.td............
  000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  000000d0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  000000e0: 1000 0000 0000 0000 8831 4A68 4D50 5043  .........1JhMPPC
  000000f0: 3409 0D16 
  ```

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值