[CTF] Dragon CTF 2020

RetroZeit(Reverse)

レ(゚∀゚;)ヘ=З=З=З 2023. 12. 21. 09:31
728x90

주어진 코드

#include <stdio.h>
#include <string.h>
char enc_chx[] = { 0x8B , 0x84 , 0x9A , 0x9B , 0x9A , 0xB1 , 0xD6 , 0xAF , 0x93 , 0xB2 , 0x81 , 0x8C , 0x84 , 0xAB , 0x9D , 0x9C , 0x8E , 0xB9 , 0xB0 , 0xD9 , 0xA8 , 0xA4 , 0x9C , 0x81 , 0x85 , 0xA0 , 0xA6 , 0xB4 , 0x87 , 0x9A , 0xBB , 0x92 , 0x96 , 0xAD , 0x8C , 0xD7 , 0xB0 , 0x8D , 0x97 };
char enc_idx[] = { 0x16 , 0xC , 0x24 , 0x17 , 0x13 , 0x19 , 0x7 , 0x9 , 0xE , 0x23 , 0x5 , 0x1 , 0x18 , 0x21 , 0xD , 0x10 , 0x12 , 0x1F , 0x1A , 0x1E , 0x22 , 0x0 , 0xF , 0xB , 0x8 , 0x15 , 0x11 , 0x2 , 0x1D , 0x1C , 0x26 , 0x3 , 0x4 , 0x25 , 0x14 , 0x20 , 0x6 , 0x1B , 0xA };
void retry_flag() { 
	int var_1, var_2; 
	int var_7, var_8; 
	for (int i=0; i < 31; i++) { 
		var_7 = rand() % 26; // called some func I didn't understand, but it was about modulo 
		var_8 = rand() % 26; // dunno... :/ 
		var_1 = enc_idx[var_7]; 
		var_2 = enc_chx[var_7]; 
		enc_idx[var_7] = enc_idx[var_8]; 
		enc_chx[var_7] = enc_chx[var_8]; 
		enc_idx[var_8] = var_1; 
		enc_chx[var_8] = var_2; 
	} }
int check_flag() {
	char var_1; 
	var_1 = enc_idx[0]; 
	if (var_1 & 1 != 0) 
		return 0; 
	for (int i=2; i < 39; i += 2) { 
		if (enc_idx[i] < var_1) 
			return 0; 
		var_1 = enc_idx[i]; 
		if (var_1 & 1 != 0) 
			return 0; 
	} 
	var_1 = enc_idx[1]; 
	if (var_1 & 1 == 0) 
		return 0; 
	for (int i=3; i < 39; i += 2) { 
		if (enc_idx[i] > var_1) 
			return 0; 
		var_1 = enc_idx[i]; 
		if (var_1 & 1 == 0) 
			return 0; 
	} 
	return 1; 
}
void decrypt_flag(char* dest) { 
	char flag[0x64] = {0}; // uses bzero to do it
	for (int i=0; i < 39; i++) { 
		flag[i] = (~enc_chx[i]) ^ i; } 
	strcpy(dest, flag); 
}

 

위 코드에 메인 함수는 나와있지 않지만, GUI, time driver를 설치하고, 버튼이 호출 된 다음에 check_flag을 반복 호출한다. 여기서 버튼은 gui 텍스트를 flag를 계산할 수 있도록 업데이트 하기 위해 호출이 된다. 만약 return값이 1이면 decrypt_flag을 호출하고 결과를 보여주지만, 그렇지 않으면 retry_flag만 호출하고 loop만 호출한다.

먼저 check_flag()부터 코드를 보았다. 먼저 홀수 인덱스인지, 짝수 인덱스인지 확인한다. 홀수와 짝수를 각각 for문을 돌리면서 for문 안에서 다음 루프를 돌기 전에 i-2인덱스에 해당되는 값과 현재 값을 비교한다. 짝수에서는 현재 값보다 i-2 인덱스 해당 값이 더 커야하고, 홀수에서는 현재 값이 i-2 인덱스 해당 값보다 작아야 한다. 그리고 for문 안에서 홀수 인덱스가 홀수를 가지고 있고 짝수 인덱스가 짝수를 가지고 있는지 확인을 한다. 즉, check_flag()을 돌면 짝수는 내림차순, 홀수는 오름차순으로 정렬이 된다.

그 다음 retry_flag()를 보았다. 임의 인덱스인 var_7와 var_8에 랜덤 값을 생성한 후에 enc_idx[var_7]와 enc_ch[var_7]을 enc_idx[var_8]와 enc_ch[var_8]로 바꿔준다. check_flag()을 따라 enc_idx와 enc_ch은 재정렬된다. 근데 enc_idx를 보면 16진수를 10진수로 바꿔서 보면 숫자 중복이 없으며 0에서부터 38까지의 숫자이다. 그렇기 때문에 인덱스를 반전시키려면 그냥 짞수인 경우 38 - enc_idx[i]를 해주면 된다. 정리해보면, enc_flag[(enc_idx[i]&1)? enc_idx[i]] = enc_ch[i] 이라는 코드를 만들 수 있다.

 

공격코드

 

코드 실행 시 flag 값 얻을 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'[CTF] Dragon CTF 2020' 카테고리의 다른 글

Harmony Chat(Webhacking)  (0) 2023.12.21
Bit Flip3(Cryptography)  (1) 2023.12.21
Bit Flip2(Cryptography)  (1) 2023.12.21
Bit Flip1(Cryptography)  (0) 2023.12.21