注入段后分段故障

问题描述 投票:0回答:1

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

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

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

#include <iostream>

using namespace std;

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

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

    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

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

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

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

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

您可以看到入口点是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:               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

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

所以现在问题开始了:

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

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

#0  0x0000000000001080 in ?? ()
(gdb) info f
Stack level 0, frame at 0x7fffb20db438:
 rip = 0x1080; saved rip = 0x1
 called by frame at 0x7fffb20db440
 Arglist at 0x7fffb20db428, args: 
 Locals at 0x7fffb20db428, Previous frame's sp is 0x7fffb20db438
 Saved registers:
  rip at 0x7fffb20db430

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

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

assembly gdb code-injection sections readelf
1个回答
0
投票

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

[_start位于0x1080(至少在Linux上不是)。>>如果readelf告诉您那是_start的地址,则您具有与位置无关的可执行文件。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.