简体   繁体   English

x86_64执行Shellcode失败:

[英]x86_64 Executing Shellcode fails:

I'm using Python 2.7 on 64-bit Linux. 我在64位Linux上使用Python 2.7。 I have the following Python script witch should execute a simple Hello World shellcode. 我有以下Python脚本,女巫应该执行一个简单的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()

If i run python Scriptname.py I get a memory access error. 如果我运行python Scriptname.py收到内存访问错误。 Anybody here have an idea why my script isn't working? 这里有人知道为什么我的脚本不起作用吗?

EDIT: Original ASM Code: 编辑:原始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

You are going to need python code that makes your shellcode run in a memory location that has Read/Write/Execute privileges. 您将需要使您的Shellcode在具有读取/写入/执行特权的内存位置中运行的python代码。 As it is the memory your shell code is running from is not in executable memory. 因为它是运行您的Shell代码的内存,所以它不在可执行内存中。 You can create a function that does this for you ( testshellcode.py ): 您可以创建一个为您执行此操作的函数( 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)()

The code should work with Python2.7+ and Python3 该代码应与Python2.7 +和Python3一起使用


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 ); 您的shell代码字符串似乎缺少字符串本身( hello ); doesn't seem to be encoded properly and you rely on a static memory location for the text label. 似乎编码不正确,并且text标签依赖静态存储位置。 You will need an address that is position independent. 您将需要一个与位置无关的地址。

To fix the code so it is position independent you can use RIP relative addressing. 要修复代码,使其与位置无关,可以使用RIP相对寻址。 Place the string inside the .text after the code section and forget about .data altogether. 将字符串放在.text内的代码部分之后,然后完全.data This version should suffice ( shellcode.asm ): 此版本应足够( 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

Using OBJDUMP to convert a shell code program to a shell code string can be problematic. 使用OBJDUMP将Shell代码程序转换为Shell代码字符串可能会出现问题。 I wrote a Stackoverflow Answer discussing some of the pitfalls of the OBJDUMP method. 我写了一个Stackoverflow答案,讨论了OBJDUMP方法的一些陷阱。 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. 使用OBJCOPY将可执行文件转换为二进制文件,然后使用某些东西(例如HEXDUMP)将二进制文件转换为Shell代码字符串。 The following commands should work: 以下命令应该起作用:

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

If you run the standalone binary shellcode it should output: 如果运行独立的二进制shellcode ,则应输出:

Hello 你好

You can then convert shellcode.bin to a shell code string with: 然后,您可以使用以下命令将shellcode.bin转换为shell代码字符串:

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

The output would look something like: 输出如下所示:

\\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 \\ 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

You can then insert this shell code string in the python program above ( testshellcode.py ) replacing shell code string here with the string above. 然后,您可以将此外壳程序代码字符串插入上面的python程序( testshellcode.py )中,用上面的字符串替换此处的外壳程序代码字符串 You can run the script above with: 您可以使用以下命令运行上面的脚本:

python testshellcode.py

The output should be: 输出应为:

Hello 你好


This is more advanced, and there are shell code tutorials that explain many of the tricks to avoid \\x00 bytes in a string. 这是更高级的方法,并且有一些shell代码教程,它们解释了避免字符串中\\x00字节的许多技巧。

Usually with shell code you want to eliminate NUL ( \\x00 ) bytes for real string exploits. 通常,对于外壳程序代码,您要消除NUL( \\x00 )字节以进行真正的字符串利用。 A version of shellcode.asm that does this could look something like: 执行此操作的shellcode.asm版本可能类似于:

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

If you create shell code string with the commands mentioned previously, HEXDUMP should produce something like: 如果使用前面提到的命令创建shell代码字符串,则HEXDUMP应该生成类似以下内容的代码:

\\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 \\固定的\\ XFF \\ XFF \\ XFF \\ X31 \\ XD2 \\ XB2 \\ X06 \\ X0F \\ X05 \\ X31 \\ XC0 \\ XB0 \\ X3C \\ X31 \\ XFF \\ X0F \\ X05

This version does the same thing as your code but notice there are no \\x00 bytes in the string. 此版本与您的代码具有相同的功能,但请注意,字符串中没有\\x00字节。 When run, it too should print: 运行时,它也应该打印:

Hello 你好

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM