HackCTF strncmp Write-Up

juuun0·2022년 1월 26일
1
post-thumbnail

Analyze Target

먼저 문제 파일을 확인해보면 64bit ELF 파일임을 확인할 수 있었습니다. 프로그램을 실행할 경우 입력값을 요구하였고 이후 어떤 내용을 출력해주며 실행은 종료되었습니다.

root@e60a28c09eb6:~/hackctf/strncmp# ./strncmp
Enter your input:
TestHaHaHa
Always dig deeper

Always dig deeper 라는 문자가 계속 출력되는 것을 보아 이를 일치하지 않는 값에 대한 출력으로 판단하였으며 gdb를 사용하여 입력값을 비교하는 routine을 분석하였습니다.

기본적으로 main() 함수 외에 strcmp_(), check() 함수가 존재하였으며 입력값을 비교하는 부분은 strcmp_()에서 진행되었습니다.

해당 함수의 마지막 부분에서 sstrncmp() 함수를 호출하는 것을 확인할 수 있었고 아래와 같이 사용되는 argument를 통해 요구되는 입력값을 찾을 수 있었습니다.

[-------------------------------------code-------------------------------------]
   0x40075c <strcmp_+134>:	mov    edx,0x1c
   0x400761 <strcmp_+139>:	mov    rsi,rcx
   0x400764 <strcmp_+142>:	mov    rdi,rax
=> 0x400767 <strcmp_+145>:	call   0x400560 <strncmp@plt>
   0x40076c <strcmp_+150>:	add    rsp,0x28
   0x400770 <strcmp_+154>:	pop    rbx
   0x400771 <strcmp_+155>:	pop    rbp
   0x400772 <strcmp_+156>:	ret
Guessed arguments:
arg[0]: 0x7fffffffebf0 --> 0x74736554 ('Test')
arg[1]: 0x7fffffffec10 ("OfdlDSA|3tXb32~X3tX@sX`4tXtz")
arg[2]: 0x1c
arg[3]: 0x7fffffffec10 ("OfdlDSA|3tXb32~X3tX@sX`4tXtz")
[------------------------------------stack-------------------------------------]

위에서 찾은 값을 입력할 경우 다른 결과를 보여주는 것을 확인할 수 있었습니다.

root@e60a28c09eb6:~/hackctf/strncmp# ./strncmp
Enter your input:
OfdlDSA|3tXb32~X3tX@sX`4tXtz
Good game

Exploit

flag로 추정되는 혹은 flag를 얻는데 도움이되는 값을 획득하였지만 이를 encoding 한 방법을 찾는데 다소 어려움이 있었습니다. 먼저 ghidra를 통해 decompile 결과를 확인하던 중 아래와 같이 xor 연산을 통해 encoding 하는 점을 확인할 수 있었습니다.

param_1[local_1c] = (byte)key ^ param_1[local_1c];

위 연산을 진행할 때 'key' 라는 변수에 지정된 값을 이용하였는데 gdb를 통해 아무리 확인하여도 0의 값을 가질 뿐 달라지는 점을 알 수 없었습니다.

무엇보다 check() 함수의 동작을 보면 더욱이 0의 값을 가질 수 밖에 없어보였습니다.

  key = atoi(*(char **)(param_2 + 8));
  if ((key + -0xe) * key != -0x31) {
    key = 0;
  }

key가 특정 공식을 만족하지 못할 경우 key 값을 0으로 지정하는 점을 확인할 수 있었습니다. 처음 문제를 풀 당시에는 저 공식을 이해하지 못하여 답에 접근하지 못하였는데 아래와 같이 치환할 경우 이해하기 쉬웠습니다.

(key - 14) * key = -49

위 공식을 만족하는 값은 '7'로 이를 key 값으로 설정하여 decoding을 진행할 경우 flag를 획득할 수 있었습니다.

#!/usr/bin/python3
 
 enc_flag = "OfdlDSA|3tXb32~X3tX@sX`4tXtz"
 key = 7 
 dec_flag = [0] * len(enc_flag)
 
 for i in range(len(enc_flag)):
     dec_flag[i] = chr(ord(enc_flag[i]) ^ key)
 
 print("".join(dec_flag))
profile
To be

0개의 댓글