我尝试运行的汇编代码只是一个系统调用 60。
# exit.s
.intel_syntax noprefix
.section .text
.globl _start
_start:
xor rax, rax
mov al, 0x3c
xor rdi, rdi
xor rdi, 1
syscall
将其与 组装,与和as exit.s -o exit.o
链接以获得最终代码。ld exit.o -o exit
objdump -d exit
// ret.c
const char shellcode[] = "\x48\x31\xc0\xb0\x3c\x48\x31\xff\x48\x83\xf7\x01\x0f\x05";
int main() {
(*(void(*)())shellcode)();
}
我编译使用gcc -fno-stack-protector -z execstack -no-pie -o ret ret.c
在 Manjaro Linux(内核 5.10)和 Ubuntu(内核 5.8)上,我在尝试运行最终的可执行文件时遇到段错误。
我在 Ubuntu 16.04(内核 4.4)上尝试了同样的操作,并且运行完美。
我做了一些研究,看起来像这次提交可能改变了行为,但我不确定。
我的问题:如何让上述代码在最新的内核版本上运行?
答案1
由于您需要一个可执行堆栈,因此将代码放在那里将使其可执行:
int main() {
const char shellcode[] = "\x48\x31\xc0\xb0\x3c\x48\x31\xff\x48\x83\xf7\x01\x0f\x05";
(*(void(*)())shellcode)();
}
或者,您可以更改包含 shellcode 的页面上的页面保护:
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
const char shellcode[] = "\x48\x31\xc0\xb0\x3c\x48\x31\xff\x48\x83\xf7\x01\x0f\x05";
int main() {
long page_size = sysconf(_SC_PAGESIZE);
void *page_start = (void *) ((long) shellcode & -page_size);
if (mprotect(page_start, page_size * 2, PROT_READ | PROT_EXEC)) {
perror("mprotect");
} else {
(*(void(*)())shellcode)();
}
}
整体变化点如你找到的那个是修复整类漏洞。即使使用上述方法,如果进程没有在某种程度上“合作”(通过请求可执行堆栈),您也无法将代码注入到正在运行的进程中并执行它。