본글은 드림핵 자료를 참고삼아 좀더 빠르게 이해하고자 작성한 글로 틀린 내용이 존재할 수 있습니다.
댓글로 틀린 부분에 대한 지적은 환영합니다.
개요
이전까지 ROP기법을 통해 보호기법이 걸려있는 파일에서 함수를 호출하는 방식을 사용했었습니다.
하지만 코드에 따라 방법이 달라지는 방식이므로 기존보다 더 나은 기법들이 계속 생겨나고 있습니다.
SROP는 그중에서 시그널을 활용하는 ROP기법입니다.
시그널
먼저 운영체제는 크게 유저모드와 커널 모드로 나뉘어 있습니다.
실제로 파일을 생성하고 실행하는 모든 작업은 이 두개의 모드가 서로 상호 작용하며 이루어지는데
시그널은 두 모드 사이에서 프로세스에 특정 정보를 전달하는 매개체의 역할을 합니다.
rt_sigreturn
프로세스가 바뀌는 것을 컨텍스트 스위칭이라고 하는데
커널 모드에서 실행되고 다시 유저 모드로 복귀할때 스위칭이 일어나며, 커널이 가지고 있던 정보를 되돌려 줘야
유저 프로세스가 다시 흐름대로 진행이 가능합니다.
이 과정으로 유저의 스택에 레지스터의 정보를 저장하게 됩니다.
만약 이부분에서 공격자가 rt_sigreturn을 호출할 수 있고,
스택도 조작이 가능하다면 모든 레지스터와 세그먼트의 조작이 가능해집니다.
이때 쓰이는 구조체가 sigcontext이며 이러한 기법을 바로 SROP(Sig Return Oriented Programming) 라고 부릅니다.
Sigcontext
sigcontext는 레지스터 정보인 만큼 32bit와 64bit에 따라 나뉘게 됩니다.
32bit

64bit

Exploit 공격법
구조체에 맞게 순서대로 값을 넣어주는 것도 가능하지만 하나하나 매번 공격시마다
구조체의 위치를 계산하고 값을 덮는 것은 상당한 반복작업이어서
pwntools 에서는 이를 위한 클래스 SigreturnFrame를 제공합니다.
SigreturnFrame
SigreturnFrame클래스는 sigcontext 구조체에 맞게 코드를 작성해야 하는 부담을 덜어줍니다.
다음코드는 SigreturnFrame클래스를 활용한 예시 코드입니다.
>>> from pwn import *
>>> context.clear(arch='amd64')
>>> frame = SigreturnFrame()
>>> frame.rdi = 0x41414141
>>> frame.rax = 59
>>> frame.rsi = 12341234
>>> print(frame)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00AAAA\x00\x00\x00\x00\xf2O\xbc\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
코드를 보면 현재 rdi와 rax, rsi에 값을 넣어야 하는 상황인데 frame.rdi= 값 이라는 편리한 방식으로
구조체에 맞게 값을 삽입할 수 있게 됩니다.
단, 아키텍처마다 구조체가 다른 점때문에 이를 명시해줘야 하는 점을 잊지 말아야 합니다.
더 자세한 Exploit Code는 관련 워게임을 진행하면서 작성하도록 하겠습니다.
Reference
'Reference > Pwnable_Study' 카테고리의 다른 글
[Pwn] _IO_FILE Arbitrary Read (0) | 2023.07.03 |
---|---|
[Pwn] _IO_FILE_Plus & _IO_FILE vtable Overwrite (0) | 2023.07.01 |
[Pwn] gdb offset Tip (0) | 2023.04.01 |
[Pwn] Overwrite _rtld_global (0) | 2023.04.01 |
tcache double free bypass (0) | 2023.02.12 |