내가 실행하려는 어셈블리 코드는 단지 시스템 호출 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
최종 코드를 얻으려면 assemble, 와 연결하세요.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)에서 최종 실행 파일을 실행하려고 하면 segfault가 발생합니다.
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)();
}
또는 쉘코드가 포함된 페이지에서 페이지 보호를 변경할 수 있습니다.
#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)();
}
}
전반적인 변경 사항은 다음과 같습니다.당신이 찾은 것전체 취약점 클래스를 수정합니다. 위의 접근 방식을 사용하더라도 실행 중인 프로세스에 코드를 삽입하고 실행 가능한 스택을 요청하여 프로세스가 어느 정도 "협력"하지 않고는 이를 실행할 수 없습니다.