본문 바로가기

4-7. 2021-2 심화 스터디/CTF

[2021.09.18] Dreamhack rev-basic 외 풀이

3주차는 리버싱의 기본 개념 학습 후,

Dreamhack과 HackCTF 사이트에서 실제 리버싱 문제를 풀고 풀이방법을 서로 공유함

 

1. rev-basic-0 (Dreamhack)

 

문제 파일 압축 해제 후 실행

무작위 문자열을 입력하니 자동으로 파일이 종료됨

 

이에 분석을 위해 x64dbg 디버거에서 파일을 열고, ‘다음을 찾기 – 모든 모듈 – 문자열 참조’를 통해 파일에서 참조되는 문자열을 모두 탐색함

 

 

아래와 같이 맨 처음 파일 실행 시 출력되었던 “Input” 문자열 외에, “Correct”, “Wrong” 문자열도 발견함, 이에 Input 문자열이 있는 위치로 이동함

 

무작위 문자열을 대입하니 아까는 확인하지 못한 Wrong 문자열을 확인할 수 있었음

 

비교되는 문자열을 알아내기 위해 strcmp 함수가 실행되는 위치에 BP를 걸고 확인함

 

흐름을 확인하니 rdx에 저장되어 있던 “Compar3_the_str1ng” 문자열과 비교되는 것을 확인함

이에 확인을 위해 해당 문자열을 Input 값으로 입력해 봄, 그 결과 정답임을 확인할 수 있었음

 

flag: DH{Compar3_the_str1ng}



2. rev-basic-1 (Dreamhack)

 

문제파일 다운로드 후 실행

Input 을 입력하는 내용 확인

 

다음을 찾기 > 모든 모듈 > 문자열 참조 > Input 검색

 

input 문자열이 존재하는 곳 더블클릭





call 하나씩 눌러보고 마지막 call 부분 더블클릭

 

 

플래그 Compar3_the_ch4ract3r 값 확인

 

flag: DH{Compar3_the_ch4ract3r}

 

3. rev-basic-2 (Dreamhack)

문제 파일 다운로드 

chall2.exe

 

IDA F9로 실행, input에서 입력받기 위해 실행이 멈춘 것을 확인

멈춘 부분의 실행 전개도

바깥쪽의 파란 실행도를 보아, 반복문 루프를 도는 것을 알 수 있다.

input을 하고 무언가를 비교해야 되기 때문에 cmp가 있는 부분을 찾았다.

[rcx+rax*4], edx 값을 비교한다.

이때, 4배수의 값을 증가시키면서 반복문 루프가 비교되는 것을 알 수 있으며, rcx는 lea rcx, aC에 있던 값이라는 것을 알 수 있다.

이때 aC의 값을 보면 주소값이 4단위 마다 다른 값이 들어있는 것을 볼 수 있다.

 

flag: DH{Comp4re_the_arr4y}



4. rev-basic-3 (Dreamhack)

문제 파일 실행(cmd)

임의의 값을 입력 했을때 입력한 문자열이 검증을 통과하지 못해 Wrong이 출력됨 

flag를 통해 Correct가 출력되도록 해야함

 

IDA를 통해 확인(Hex-Rays SA에서 개발하여 판매중인 상용 디스어셈블러. 주로 리버스 엔지니어링을 위한 디버거로 이용된다.)

 

IDA실행 후 f5를 통해 프로그램 코드 확인

조건문에 correct / wrong이 나눠지므로 해당 조건문이 있는 sub_14001000 함수를 본다

함수 내용을 보면 0부터 23까지 도는 반복문이고 (0x18은 24번) byte_140003000 배열과 입력받고 가공시킨 a1 값과 같으면 True return한다는 것이다.

 

여기서 if 문을 보면 byte_140003000[i] != (i ^ *(unsigend __int8 *)(a1 + 1)) + 2 * i)라는 식을 볼 수 있는데 ^은 xor이다. xor은 a^b=c 일 때 c^b =a를 만족한다는 성질이 있다.

즉 byte_140003000[i]=(i xor 사용자 입력값) + 2 * i로 보았을 때 (참일때 식)

byte_140003000[i] - 2 *i=(i xor 사용자 입력값 )

-byte_140003000[i] - 2 *i=c

-사용자 입력값 = a 일 때

- c = a ^ i 이므로 a = c ^ i를 만족한다

따라서 사용자 입력값(a1+i) = ( byte_140003000[i] - 2 * i ) ^ I을 만족하면 True를 반환한다.

byte_140003000[i] 은 byte_140003000[32]의 배열에서 24바이트만 찾으면된다(24번 반복)

 

0x49 0x60 0x67 0x74 0x63 0x67 0x42 0x66 0x80 0x78 0x69 0x69 (2 dup(69h)는 69h가 2개가 중복 )

0x7B 0x99 0x6D 0x88 0x68 0x94 0x9F 0x8D 0x4D 0xA5 0x9D 0x45

(10진수도 사용가능)

 

이제 식과 값을 이용하여 플래그를 구하자(c언어 사용)

(a1+i) = ( byte_140003000[i] - 2 * i ) ^ i

→  byte_140003000[i] - 2 * i ) ^ i 값을 구하자

 

결과: I_am_X0_xo_Xor_eXcit1ng





flag: DH{I_am_X0_xo_Xor_eXcit1ng}