注入段后分段错误

时间:2019-10-02 12:09:04

标签: assembly gdb code-injection sections readelf

我目前正在关注Dennis Andriesse撰写的关于二进制分解和检测的书。

在下一章中,我们为ELF类型文件编写了注射器。 注入程序将代码段放置在位置0x80000 [+ offset%16]处,覆盖.note.ABI-tag部分(该段仅包含与执行无关的信息,因此可以安全地覆盖它)。

我要修改的程序是一个简单的hello_username程序,如下所示:

list comprehension

我在此处放置的代码如下:

#include <iostream>

using namespace std;

main()
{
    cout << "hello Lucky" << endl;
    return 0;
}

尽管我相信我们不需要推送rcx和r11,但是代码很简单明了, 我用

编译
    BITS 64

section .text
global main

main:

    push    rax
    push    rcx
    push    rdx
    push    rsi
    push    rdi
    push    r11


    mov rax,    0x1                 ;syscall to print (sys_write)
    mov rdi,    0x1                 ;stdout
    lea rsi,    [rel $+rankle-$]    ;offset to prank
    mov rdx,    [rel $+size-$]      ;length of prank
    syscall

    pop     r11
    pop     rdi
    pop     rsi
    pop     rdx
    pop     rcx
    pop     rax

    push    0x1080              ;find "entry_point" using readelf program
    ret

rankle  : db "Yikes! U got pranked!", 0
size    : dd 22

在那之后,我将其与我们编写的程序一起注入,除了注入该部分之外,我还覆盖了入口点。这是操作前的readelf输出:

nasm -f bin -o pranked.bin hi_there.asm

您可以看到入口点是0x1080,这是.text部分的起点。 (_start函数位于此位置,已使用objdump将其检出)

现在,进行注射后,输出相同:

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:               0x1080
  Start of program headers:          64 (bytes into file)
  Start of section headers:          15344 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

  Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         00000000000002a8  000002a8
        000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.build-i NOTE             00000000000002c4  000002c4
        0000000000000024  0000000000000000   A       0     0     4
  [ 3] .note.ABI-tag     NOTE             00000000000002e8  000002e8
        0000000000000020  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000308  00000308
        0000000000000028  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000000330  00000330
        0000000000000138  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000000468  00000468
        0000000000000163  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           00000000000005cc  000005cc
        000000000000001a  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          00000000000005e8  000005e8
       0000000000000040  0000000000000000   A       6     2     8
  [ 9] .rela.dyn         RELA             0000000000000628  00000628
       0000000000000120  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000000748  00000748
       0000000000000060  0000000000000018  AI       5    23     8
  [11] .init             PROGBITS         0000000000001000  00001000
       0000000000000017  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000001020  00001020
       0000000000000050  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         0000000000001070  00001070
       0000000000000008  0000000000000008  AX       0     0     8
  [14] .text             PROGBITS         0000000000001080  00001080
       00000000000001e1  0000000000000000  AX       0     0     16
  [ .... ]

您可以看到从0x80370开始的新部分在那里,并且ELF标头中的新入口点指向该部分(使用十六进制编辑器对其进行了仔细检查)。

现在,问题开始了:

如果我尝试执行该程序,它将正确打印出来 “ Yikes!您被恶作剧!\”紧接着是SEGMENTATION FAULT。

这让我发疯了,因为我现在已经纠缠了一个多星期! 不幸的是,gdb在这里没有太大帮助,但至少我可以在SIGSEV之前抢到堆栈框架:

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:               0x80370
  Start of program headers:          64 (bytes into file)
  Start of section headers:          15344 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         00000000000002a8  000002a8
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.build-i NOTE             00000000000002c4  000002c4
       0000000000000024  0000000000000000   A       0     0     4
  [ 3] .init             PROGBITS         0000000000001000  00001000
       0000000000000017  0000000000000000  AX       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000308  00000308
       0000000000000028  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000000330  00000330
       0000000000000138  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000000468  00000468
       0000000000000163  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           00000000000005cc  000005cc
       000000000000001a  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          00000000000005e8  000005e8
       0000000000000040  0000000000000000   A       6     2     8
  [ 9] .rela.dyn         RELA             0000000000000628  00000628
       0000000000000120  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000000748  00000748
       0000000000000060  0000000000000018  AI       5    23     8
  [11] .plt              PROGBITS         0000000000001020  00001020
       0000000000000050  0000000000000010  AX       0     0     16
  [12] .plt.got          PROGBITS         0000000000001070  00001070
       0000000000000008  0000000000000008  AX       0     0     8
  [13] .text             PROGBITS         0000000000001080  00001080
       00000000000001e1  0000000000000000  AX       0     0     16

       [...]

  [25] .bss              NOBITS           0000000000004060  00003048
       0000000000000118  0000000000000000  WA       0     0     32
  [26] .pranked          PROGBITS         0000000000080370  00004370
       000000000000004a  0000000000000000  AX       0     0     16
  [27] .symtab           SYMTAB           0000000000000000  00003070
       00000000000006f0  0000000000000018          28    49     8
  [28] .strtab           STRTAB           0000000000000000  00003760
       0000000000000382  0000000000000000           0     0     1
  [29] .shstrtab         STRTAB           0000000000000000  00003ae2
       0000000000000107  0000000000000000           0     0     1

那就是我被困的地方。为什么说1080英寸? ()。 我猜我对入口点的计算也应该是正确的。 裂痕也指向_start函数。...

我如何才能再次跳转到正确的入口点? 我只想为世界打招呼程序编写一个mod,这不应该太多黑魔法...

1 个答案:

答案 0 :(得分:3)

  

我猜我对入口点的计算也应该是正确的。关键是指向_start函数,

不可能_start位于0x1080(至少在Linux上不是)。

如果readelf告诉您那是_start的地址,则您有一个与位置无关的可执行文件。

PIE可执行文件直到几年前才出现,因此本书可能没有提到您需要一个非PIE的文件(因为在编写非PIE二进制文件时,您就可以构建/运行所有二进制文件)。

要构建非PIE二进制文件,请使用g++ -fno-pie -no-pie hello.cc。完成此操作后,其余的代码注入应该像本书中那样工作。