我正在尝试在32位ELF可执行文件中注入一段shellcode。我正在运行64位的Ubuntu 14.04。因此,我运行的所有命令都需要显式开关才能生成32位代码。我正在使用elf-infector注入我的shellcode。主机二进制文件的C源代码如下:

/* simple_if.c */

#include <stdio.h>
#include "s2e.h"

int main()
{
  int var_cond;
  printf("Enter 0/1: ");
  scanf("%d", &var_cond);
  if(!var_cond)
    printf("Entered value: 0\n");
  else
    printf("Entered value: 1\n");

  return 0;
}


首先我尝试了一个“ Hello World” ASM有效负载:

; hello.asm
global _start
section .text

_start:
    jmp MESSAGE      ; 1) lets jump to MESSAGE

GOBACK:
    mov eax, 0x4
    mov ebx, 0x1
    pop ecx          ; 3) we are poping into `ecx`, now we have the
                     ; address of "Hello, World!\r\n" 
    mov edx, 0xF
    int 0x80
    jmp end          ; Injector will insert a jump to original entry point

    ;mov eax, 0x1    ; Intentionally not returning the control
    ;mov ebx, 0x0
    ;int 0x80

MESSAGE:
    call GOBACK       ; 2) we are going back, since we used `call`, that means
                      ; the return address, which is in this case the address 
                      ; of "Hello, World!\r\n", is pushed into the stack.
    db "Hello, World!", 0dh, 0ah    
end:


编译宿主和寄生虫,并在末尾注入shellcode。

gcc -m32 simple_if.c -o simple_if
nasm -f elf hello.asm -o hello.o
ld -m elf_i386 hello.o -o hello

# Test the assembled code
./hello
Hello, World!
Segmentation fault (core dumped)
# Segfault is natural, we are not gracefully returning to OS

# Now extract the shellcode
for i in `objdump -d ./hello | tr '\t' ' ' | tr ' ' '\n' | egrep '^[0-9a-f]{2}$' `; do echo -n "\\x$i" ; done | paste -d '' -s | sed 's/^/"/' | sed 's/$/"/g'
"\xeb\x14\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\x59\xba\x0f\x00\x00\x00\xcd\x80\xeb\x14\xe8\xe7\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a"

# Update parasite.h
make
./infector simple_if

Run the infected file
./simple_if
Hello, World!
Enter 0/1: 8
Entered value: 1
Segmentation fault (core dumped)


但是,我希望程序可以正常退出。因为,感染者在shellcode的末尾插入了一个到OEP的跳转。我尝试了不同的有效载荷。但是,在这种情况下,程序将在无限循环中运行,永远不会退出。

global     _start    
section    .text

_start:
    mov    ecx,0x23f0
    mov    edx,0x804869c
    jmp    prog_name

stub:
    pop    eax
    push   ebx
    mov    ebx,edx
    ;db     0x0f,0x3f,0x00,0xaa,0x00,0x00,0x00,0x00,0x00,0x00
    pop    ebx
    xor    eax,eax
    jmp    jump_start

prog_name:
    call   stub
    db "simple_if",0x00,0x90

jump_start:


这就是受感染的文件所产生的结果。

./simple_if
Enter 0/1: 9
Entered value: 1
Enter 0/1: 7
Entered value: 1
Enter 0/1: 6
Entered value: 1
Enter 0/1: 5
Entered value: 1
Enter 0/1: ^C


使用GDB,我可以看到先执行了shellcode,然后程序跳至OEP。此后发生崩溃。有人可以给我任何线索是怎么回事吗?

评论

无限循环版本还会无限运行shellcode吗?看起来好像重复到达了shellcode,并且每次都将控制权返回到程序的开始。

用-O0 -g编译程序,然后gdb编译它。运行;当它收到信号时,检查eip(信息寄存器)和堆栈回溯(bt)。如果仍然无法解决问题,请在main的返回处设置一个断点(break simple_if.c:16,仔细检查行号),运行,一步一步地检查之后的情况(stepi以及nexti等退出函数)处理程序)。

寄存器和/或标志可能已从先前的值更改。分别在shellcode的开头和结尾处尝试pushad / popad和pushfd / popfd。这将恢复原始寄存器和EFlags。如果没有其他问题,那么我们就可以排除问题。

#1 楼

正如@goodies在评论中所说,这是在破坏一些寄存器值,从而导致崩溃。

pusha / popa扩展有效负载,就像这样

_start:
  pusha
  jmp MESSAGE


和此处

int 0x80
popa
jmp end     


如果现在执行所有步骤,则将获得所请求的结果:

./simple_if 
Hello, World!
Enter 0/1: 9
Entered value: 1


除非您特别希望通过修改regs发生某些行为,否则这通常是处理有效负载以维持寄存器状态的最佳方法。