주어진 코드
#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 |