x86_64执行Shellcode失败: [英] x86_64 Executing Shellcode fails:

查看:153
本文介绍了x86_64执行Shellcode失败:的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在64位Linux上使用Python 2.7.我有以下Python脚本,应该执行简单的Hello World shellcode.

I'm using Python 2.7 on 64-bit Linux. I have the following Python script witch should execute a simple Hello World shellcode.

import urllib2
import ctypes

shellcode = "\xb8\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x48\xbe\xd8\x00\x60\x00\x00\x00\x00\xba\x0e\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\xbf\x00\x00\x00\x00\x0f\x05"


#Create buffer in memory
shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))

#Funktionszeiger
shellcode_func  = ctypes.cast(shellcode_buffer, ctypes.CFUNCTYPE(ctypes.c_void_p))

#Shellcode execute
shellcode_func()

如果我运行python Scriptname.py,则会收到内存访问错误.这里有人知道为什么我的脚本不起作用吗?

If i run python Scriptname.py I get a memory access error. Anybody here have an idea why my script isn't working?

原始ASM代码:

section .data
    text db "Hello",10

section .text
    global _start

_start:
    ;syscall sys_write(1, text, 14)
    mov rax, 1
    mov rdi, 1
    mov rsi, text
    mov rdx, 14
    syscall

    ;syscall sys_exit(0)
    mov rax, 60
    mov rdi, 0
    syscall

推荐答案

您将需要使您的shellcode在具有读取/写入/执行特权的内存位置中运行的python代码.因为它是运行您的shell代码的内存,所以它不在可执行内存中.您可以创建一个为您执行此操作的函数(testshellcode.py):

You are going to need python code that makes your shellcode run in a memory location that has Read/Write/Execute privileges. As it is the memory your shell code is running from is not in executable memory. You can create a function that does this for you (testshellcode.py):

import ctypes, mmap, sys

# Convert string to bytes object. Differs between Python2 and Python3
if sys.version_info >= (3, 0):
    def b(string, charset='latin-1'):
        if isinstance(string, bytes) and not isinstance(string, str):
            return (string)
        else:
            return bytes(string, charset)
else:
    def b(string):
        return bytes(string)

def create_shellcode_function (shellcode_str):
    shellcode_bytes = b(shellcode_str)

    # Allocate memory with a RWX private anonymous mmap
    exec_mem = mmap.mmap(-1, len(shellcode_bytes),
                         prot = mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC,
                         flags = mmap.MAP_ANONYMOUS | mmap.MAP_PRIVATE)

    # Copy shellcode from bytes object to executable memory
    exec_mem.write(shellcode_bytes)

    # Cast the memory to a C function object
    ctypes_buffer = ctypes.c_int.from_buffer(exec_mem)
    function = ctypes.CFUNCTYPE( ctypes.c_int64 )(ctypes.addressof(ctypes_buffer))
    function._avoid_gc_for_mmap = exec_mem

    # Return pointer to shell code function in executable memory
    return function

# linux machine code
shellcode = "shell code string here"

# Create a pointer to our shell code and execute it with no parameters
create_shellcode_function(shellcode)()

该代码应与Python2.7 +和Python3兼容

The code should work with Python2.7+ and Python3

即使您将外壳代码字符串插入上方测试程序中的字节对象中,它也会失败.您的外壳程序代码字符串似乎缺少字符串本身(hello);似乎没有正确编码,并且您依赖text标签的静态内存位置.您将需要一个与职位无关的地址.

Even if you insert your shell code string into the byte object in the test program above it will fail. Your shell code strings seem to be lacking the string itself (hello); doesn't seem to be encoded properly and you rely on a static memory location for the textlabel. You will need an address that is position independent.

要修复代码,使其独立于位置,可以使用RIP相对寻址.将字符串放在代码部分之后的.text中,然后完全忘记.data.此版本足以满足要求(shellcode.asm):

To fix the code so it is position independent you can use RIP relative addressing. Place the string inside the .text after the code section and forget about .data altogether. This version should suffice (shellcode.asm):

section .text
    global _start

_start:
    ;syscall sys_write(1, text, text_len)
    mov rax, 1
    mov rdi, 1
    lea rsi, [rel text]     ; RIP Relative addressing for Position independent code
    mov rdx, text_len       ; text length computed by assembler
    syscall

    ;syscall sys_exit(0)
    mov rax, 60
    mov rdi, 0
    syscall

    text db "Hello",10
text_len EQU $-text         ; Rather than hard coding length compute text length

使用OBJDUMP将Shell代码程序转换为Shell代码字符串可能会出现问题.我写了一个 Stackoverflow答案,讨论了OBJDUMP方法的一些陷阱.如果要创建可执行文件来独立测试外壳程序代码,则最好将其汇编并链接到可执行文件.使用OBJCOPY将可执行文件转换为二进制文件,然后使用某些东西(例如HEXDUMP)将二进制文件转换为shell代码字符串.以下命令应该起作用:

Using OBJDUMP to convert a shell code program to a shell code string can be problematic. I wrote a Stackoverflow Answer discussing some of the pitfalls of the OBJDUMP method. If you are creating an executable to test your shell code standalone then it is preferable to assemble and link it to an executable; use OBJCOPY to convert the executable to binary and then use something (like HEXDUMP) to convert the binary to a shell code string. The following commands should work:

nasm -f elf64 shellcode.asm -o shellcode.o 
ld shellcode.o -o shellcode
objcopy -O binary shellcode shellcode.bin

如果运行独立的二进制文件shellcode,则应输出:

If you run the standalone binary shellcode it should output:

你好

然后可以使用以下命令将shellcode.bin转换为外壳代码字符串:

You can then convert shellcode.bin to a shell code string with:

hexdump -v -e '"\\""x" 1/1 "%02x" ""' shellcode.bin

输出看起来像:

\ xb8 \ x01 \ x00 \ x00 \ x00 \ xbf \ x01 \ x00 \ x00 \ x00 \ x48 \ x8d \ x35 \ x13 \ x00 \ x00 \ x00 \ x00 \ xba \ x06 \ x00 \ x00 \ x00 \ x00 \ x0f \ x05 \ xb8 \ x3c \ x00 \ x00 \ x00 \ xbf \ x00 \ x00 \ x00 \ x00 \ x0f \ x05 \ x48 \ x65 \ x6c \ x6c \ x6f \ x0a

\xb8\x01\x00\x00\x00\xbf\x01\x00\x00\x00\x48\x8d\x35\x13\x00\x00\x00\xba\x06\x00\x00\x00\x0f\x05\xb8\x3c\x00\x00\x00\xbf\x00\x00\x00\x00\x0f\x05\x48\x65\x6c\x6c\x6f\x0a

然后您可以将此外壳代码字符串插入上面的python程序(testshellcode.py)中,并用上面的字符串替换此处的外壳代码字符串.您可以使用以下命令运行上面的脚本:

You can then insert this shell code string in the python program above (testshellcode.py) replacing shell code string here with the string above. You can run the script above with:

python testshellcode.py

输出应为:

你好


这是更高级的方法,并且有一些shell代码教程,它们解释了避免字符串中\x00个字节的许多技巧.


This is more advanced, and there are shell code tutorials that explain many of the tricks to avoid \x00 bytes in a string.

通常,对于外壳代码,您要消除NUL(\x00)个字节以进行真正的字符串利用. shellcode.asm的版本可以执行以下操作:

Usually with shell code you want to eliminate NUL (\x00) bytes for real string exploits. A version of shellcode.asm that does this could look something like:

section .text
    global _start

_start:
    jmp afterdata
    text db "Hello",10
text_len EQU $-text

afterdata:
    ;syscall sys_write(1, text, text_len)
    xor eax, eax
    inc eax
    mov edi, eax
    lea rsi, [rel text]
    xor edx, edx
    mov dl, text_len
    syscall

    ;syscall sys_exit(0)
    xor eax, eax
    mov al, 60
    xor edi, edi
    syscall

如果使用前面提到的命令创建shell代码字符串,则HEXDUMP应该生成类似以下内容的

If you create shell code string with the commands mentioned previously, HEXDUMP should produce something like:

\ xeb \ x06 \ x48 \ x65 \ x6c \ x6c \ x6f \ x0a \ x31 \ xc0 \ xff \ xc0 \ x89 \ xc7 \ x48 \ x8d \ x35 \ xed \ xff \ xff \ xff \ x31 \ xd2 \ xb2 \ x06 \ x0f \ x05 \ x31 \ xc0 \ xb0 \ x3c \ x31 \ xff \ x0f \ x05

\xeb\x06\x48\x65\x6c\x6c\x6f\x0a\x31\xc0\xff\xc0\x89\xc7\x48\x8d\x35\xed\xff\xff\xff\x31\xd2\xb2\x06\x0f\x05\x31\xc0\xb0\x3c\x31\xff\x0f\x05

此版本与您的代码具有相同的作用,但请注意,字符串中没有\x00个字节.运行时,它也应该打印:

This version does the same thing as your code but notice there are no \x00 bytes in the string. When run, it too should print:

你好

这篇关于x86_64执行Shellcode失败:的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆