문제에서 주어진 파일을 IDA로 분석하면 main 함수는 아래와 같습니다. 프로그램에는 2가지 기능이 있습니다. encode와 decode 기능입니다.
__int64 __fastcall encode(const char *a1)
{
int j; // [rsp+Ch] [rbp-24h]
int i; // [rsp+10h] [rbp-20h]
int v4; // [rsp+14h] [rbp-1Ch]
const char *v5; // [rsp+18h] [rbp-18h]
int v6; // [rsp+24h] [rbp-Ch]
v6 = strlen(a1);
v5 = (const char *)malloc(9 * v6);
for ( i = 0; i < v6; ++i )
{
a1[i] ^= 35u;
v4 = a1[i];
for ( j = 0; j < 8; ++j )
{
v5[8 * i + j] = v4 % 2 + 48;
v4 /= 2;
}
}
printf("%s\n", v5);
return 0LL;
}
int __cdecl main(int argc, const char **argv, const char **envp)
{
if ( argc != 3 )
{
printf("%s [mod] [text]\n", *argv);
exit(1);
}
if ( !strcmp(argv[1], (const char *)(unsigned int)"encode") )
{
encode(argv[2]);
}
else if ( !strcmp(argv[1], (const char *)(unsigned int)"decode") )
{
decode();
}
return 0;
}
문제는 decode 부분을 우리가 구현하면 됩니다. 아래와 같이 encode는 잘 작동하지만 decode 부분은 Your turn이라는 문구가 출력됩니다. 따라서 encode 함수의 알고리즘을 분석하여 복호화하는 함수를 구현하면 플래그를 획득할 수 있습니다.
저는 알고리즘을 분석하기에 앞서 각 문자가 똑같은 숫자만 출력한다는 것을 발견하여 마치 고전암호를 풀듯이 하나씩 끼워맞췄습니다. 아래와 같이 문자마다 8비트의 어떠한 고정값을 가지므로 8비트에 대응하는 알파벳을 하나씩 찾아 사전을 만들었습니다.
01000010=a 10000010=b 00000010=c 11100010=d 01100010=e 10100010=f 00100010=g
11010010=h 01010010=i 10010010=j 00010010=k 11110010=l 01110010=m 10110010=n
00110010=o 11001010=p 01001010=q 10001010=r 00001010=s 11101010=t 01101010=u
10101010=v 00101010=w 11011010=x 01011010=y 10011010=z
01000110=A 10000110=B 00000110=C 11100110=D 01100110=E 10100110=F 00100110=G
11010110=H 01010110=I 10010110=J 00010110=K 11110110=L 01110110=M 10110110=N
00110110=O 11001110=P 01001110=Q 10001110=R 00001110=S 11101110=T 01101110=U
10101110=V 00101110=W 11011110=X 01011110=Y 10011110=Z
11001000=0 01001000=1 10001000=2 00001000=3 11101000=4 01101000=5 10101000=6
00101000=7 11011000=8 01011000=9
위는 하나씩 알아낸 사전이고 아래는 사전을 이용해 문제에서 주어진 암호를 해석했습니다.
11100110=D
01010110=I
01110110=M
01010110=I
00011010={
10000110=B
01001000=1
10110010=n
00111110=_
11101010=t
11001000=0
00111110=_
01101000=5
11101010=t
10001110=Q
01001000=1
10110110=N
00100010=g
00111110=_
11100010=d
01001000=1
10110010=n
00100110=G
00111110=_
11100110=D
11001000=0
10110010=n
00100010=g
01111010=}
DIMI{B1n_t0_5tQ1Ng_d1ng_D0ng}
플래그를 알아냈습니다. 가끔식은 이러한 노가다 방식도 확실할 경우에는 괜찮을 것 같습니다.
'Misc' 카테고리의 다른 글
[Square CTF] Stegasaurus (0) | 2021.08.18 |
---|---|
[Square CTF] 🍎🍌🍍🤔😱😭 (0) | 2021.08.13 |
[DIMI CTF] dimi-contract (0) | 2021.08.05 |
[DIMI CTF] CTFind (0) | 2021.08.05 |
[Dreamhack] broken-png (0) | 2021.03.30 |
댓글