안 쓰던 블로그

dreamhack rev-basic-3 풀이 본문

CTF/Reversing

dreamhack rev-basic-3 풀이

proqk 2020. 9. 17. 19:58
반응형

이 문제에서도 rev1처럼 입력을 받고 뭔가 함수 호출 후에 corret wrong에 따라 분기한다

분기문에서 bp걸고 f7로 내부로 들어갔다

 

 

문자열을 한 글자씩 가져온 후에 어떤 연산을 거치고 input과 비교한다

 

한 글자씩 비교하는 함수를 총 0x18(23)번 반복하기 때문에 Flag가 총 0x18(23)글자인것을 먼저 확인해야 한다

(마지막은 \00)

 

첫 번째 글자를 구할 때는 카운트가 0부터 시작되기 때문에 Flag 첫 글자와 연산에 사용되는 비교 문자의 글자가 동일하다. 일단 규칙을 찾아야 한다. 첫 번째 글자는 그랬는데 두번째 글자부터는 카운트가 1로 증가하며 뭔가 연산이 시작되는 것을 볼 수 있음


첫 번째로 본인이 입력한 글자 ^ 카운트 연산을 한다
두 번째로 첫 번째 연산 과정에서 구한 결과 값 - (카운트 * 2) 연산을 한다
세 번째로 두 번째 연산 과정에서 구한 결과 값 비교문자와 비교 한다
 0x18(23) 글자가 모두 맞을 경우 Correct! 를 출력하며 종료

 

비교 문자열은 비교하는 부분인 LEA RCX, QWORD PTR DS:[7FF~]에 가서 덤프를 보면 아스키 코드 값으로 문자열이 있다

49 60 67 74 63 67 42 66 80 78 69 69 7B 99 6D 88 68 94 9F 8D 4D A5 9D

이 hex를 i^(hex[i] -2*i) 의 규칙으로 변환하면 정답이 나온다

#include <iostream>
using namespace std;

int main()
{
	int arr[] = { 0x49,0x60,0x67,0x74,0x63,0x67,0x42,0x66,0x80,0x78,0x69,0x69,0x7B,0x99,0x6D,0x88,0x68,0x94,0x9F,0x8D,0x4D,0xA5,0x9D,0x45 };
	for (char i = 0; i < 24; i++) {
		for (char j = 0; j < 127; j++) {
			int tmp1 = ((j ^ i) + i * 2);
			if (arr[i] == tmp1) {
				cout << j;
			}
		}
	}
}

 

파이썬

# 연산 후 비교하는 값을 저장한 리스트
compare = [0x49,0x60,0x67,0x74,0x63,0x67,0x42,0x66,0x80,0x78,0x69,0x69,0x7B,0x99,0x6D,0x88,0x68,0x94,0x9F,0x8D,0x4D,0xA5,0x9D,0x45]

# Flag를 저장하는 리스트
Flag = []

for idx,item in enumerate(compare):
    Flag.append(chr((item - idx * 2)^idx))

print("Flag : {}".format("".join(Flag)))

 

코드를 실행시키면 플래그를 얻을 수 있다.

 

반응형

'CTF > Reversing' 카테고리의 다른 글

wow64 file system redirection  (0) 2020.09.18
어셈블리 C코드 변환하기  (0) 2020.09.17
dreamhack rev-basic-0 풀이  (0) 2020.09.14
어셈블리 코드 C코드로 변환하기  (0) 2020.09.14
Register  (0) 2020.09.01
Comments