x86_64执行Shellcode失败: [英] x86_64 Executing Shellcode fails:
问题描述
我在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 text
label. 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屋!