我正在通过此处的示例学习使用 C 语言进行 shellcode 开发。我可以编译汇编代码并获取操作码,也可以成功运行使用 NASM 编译的 ELF,但是当我运行带有嵌入式 shellcode 的 C 测试应用程序时会出现分段错误。我有 Ubuntu 20.04 64 位。
这是汇编代码,我可以运行./shellcode
并获得一个没有错误的 shell。
; https://mcsi-library.readthedocs.io/articles/2022/06/linux-exploitation-x64-shellcode/linux-exploitation-x64-shellcode.html
; shellcode.asm
; nasm -f elf64 -o shellcode.o shellcode.asm
; ld -m elf_x86_64 -s -o shellcode shellcode.o
section .text
global _start ; we inform the system where the program begins
_start:
xor rdx, rdx ; zero out rdx
push rdx ; push it onto the stack
mov rax, 0x68732f2f6e69622f ; we can push 'hs//nib/' as one value, after all it is 64-bit
push rax ; we push it onto the stack, so it lands at some address on the stack
mov rdi, rsp ; that address is where esp points to, so we store it in rdi => pointer to '/bin/sh'
push rdx ; we push 0, as it will be the null termination of the array
push rdi ; the address of '/bin/sh' is pushed onto the stack, it lands under another stack address
mov rsi, rsp ; we store that address into rsi. So rsi contains a pointer to a pointer to '/bin/sh'
xor rax, rax ; zero out eax to keep it clean
mov al, 0x3b ; 59 DEC, we move it to the lowest eax part to avoid nulls.
syscall ; all arguments are set up, syscall time
我使用此脚本获取操作码,并且获取了与原始帖子相同的操作码。
#!/bin/bash
# extract elf opcodes
if [ -z "$1" ]
then
echo "Usage: $0 <path to executable>"
exit
fi
objdump -d $1|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
这是嵌入了 shellcode 的 tester.c,它会引发段错误。
// tester.c
// shellcode tester program
// gcc -m64 -z execstack -fno-stack-protector -o tester tester.c
// https://mcsi-library.readthedocs.io/articles/2022/06/linux-exploitation-x64-shellcode/linux-exploitation-x64-shellcode.html
#include <stdio.h>
#include <string.h>
unsigned char code[] = "\x48\x31\xd2\x52\x48\xb8\x2f\x62\x69\x6e\x2f\x73\x68\x50\x48\x89\xe7\x52\x57\x48\x89\xe6\x48\x31\xc0\xb0\x3b\x0f\x05";
int main() {
printf("shellcode length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
我已经测试过-no-pie、-fno-pie,运行以setarch `uname -m` -R ./tester
禁用内存布局随机化,但没有任何效果。
提取 shellcode 的 shell 脚本中存在一个 bug。
在目标文件上运行
objdump -d
将会产生以下反汇编:此输出通过管道传输,管道剪切出标题行和字节数前缀,结果如下:
然后管道中的下一个命令是这样的:
这将抓取每行的前 6 个字(代表字节值)。问题是第三行有 7 个字节值,所以最后一行被截断了。
这会导致生成的操作码中缺少一个字节,这意味着您没有运行您认为正在运行的代码。
将管道命令更改为:
您将获得预期的机器代码字节。
下面是一个更简单且不容易出错的管道,用于生成 C 的 shellcode 数组:
shellcode.asm
:这里唯一的变化是添加
BITS 64
明确指定使用 64 位模式。然后,运行这两个命令:
然后你的 C 代码就可以简单了
注意使用
mmap
创建 RWX 段来存储 shellcode - 这意味着您不需要添加-z execstack -fno-stack-protector
。