HackCTF reversing 분야의 마지막 문제다. 언제 다 푸나 했는데 결국 다 풀어버렸다.
기드라로 파일을 분석했다. main 함수부터 살펴봤다.
undefined4 main(void)
{
char cVar1;
size_t sVar2;
int local_38;
char cStack49;
int local_30;
uint local_2c;
undefined4 local_28;
char local_24 [28];
memset(local_24,0,0x1a);
printf((char *)0xdf0);
__isoc99_scanf(0xdfc,local_24);
sVar2 = strlen(local_24);
if (sVar2 == 0x19) {
local_38 = 0;
while (local_38 < 6) {
local_30 = 0x18;
while (cVar1 = local_24[24], -1 < local_30) {
if (local_30 == 0) {
local_24[0] = cStack49;
}
else {
if (local_30 == 0x18) {
local_24[24] = local_24[23];
cStack49 = cVar1;
}
else {
local_24[local_30] = local_24[local_30 + -1];
}
}
local_30 = local_30 + -1;
}
local_38 = local_38 + 1;
}
local_2c = 0;
while ((int)local_2c < 0x19) {
if ((*(uint *)(data + local_2c * 4) ^ local_2c ^ (int)local_24[local_2c]) !=
*(uint *)(comp + local_2c * 4)) {
puts((char *)0xe10);
return 0;
}
local_2c = local_2c + 1;
}
local_28 = 0;
while (local_28 < 0x19) {
_IO_putc((int)(char)*(undefined4 *)(comp + local_28 * 4),stdout);
local_28 = local_28 + 1;
}
puts((char *)0xe1c);
}
else {
puts((char *)0xe00);
}
return 0;
}
변수명이 유사하게 설정되어 있고, 구조 정리가 잘 안되어서 부분 부분 나눠서 정리를 했다.
if (sVar2 == 0x19) {
local_38 = 0;
while (local_38 < 6) {
local_30 = 0x18;
while (cVar1 = local_24[24], -1 < local_30) {
if (local_30 == 0) {
local_24[0] = cStack49;
}
else {
if (local_30 == 0x18) {
local_24[24] = local_24[23];
cStack49 = cVar1;
}
else {
local_24[local_30] = local_24[local_30 + -1];
}
}
local_30 = local_30 + -1;
}
local_38 = local_38 + 1;
}
평문의 위치를 바꿔주는 기능을 하는 것 같다. 암호화의 Logic이라고 하면 할 수는 있겠지만, 직접 평문을 암호화하는 Logic은 아닌 것 같아서 밑의 부분을 이어서 살펴봤다.
while ((int)local_2c < 0x19) {
if ((*(uint *)(data + local_2c * 4) ^ local_2c ^ (int)local_24[local_2c]) != *(uint *)(comp + local_2c * 4)) {
puts((char *)0xe10);
return 0;
}
XOR 연산을 이용해 암호화하는 것 같다. XOR 연산은 배타적인 특성을 지니므로 이를 통해 우리가 알아내야 할 입력값을 알 수 있다. 즉, 이를 이용해 복호화하면 플래그 값을 얻을 수 있는 것이다.
data[i * 4] ^ i ^ input[i] == comp[i * 4];
변수명을 수정해서 암호화 방식을 정리하면 위와 같다. 입력 받아야 하는 값을 구해야 하므로 다시 정리해보자.
input[i] = data[i * 4] ^ i ^ comp[i * 4];
data와 comp에 있는 값들을 확인할 수 있다. 존재하는 데이터, 복호화 방식을 알았으니 코드를 짜면 된다.
#include <stdio.h>
void main() {
char data[25] = { 0x72, 0x09, 0x04, 0x10, 0x49, 0x19, 0x3a, 0x1c, 0x34, 0x3b, 0x26, 0x2a, 0x15, 0x30, 0x52, 0x1b, 0x0d, 0x0c, 0x12, 0x38, 0x49, 0x04, 0x02, 0x69, 0x4b };
char comp[25] = { 0x43, 0x6f, 0x6e, 0x67, 0x72, 0x61, 0x74, 0x7a, 0x5f, 0x59, 0x6f, 0x75, 0x5f, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x46, 0x6c, 0x61, 0x67, 0x21, 0x21 };
char input[25] = { 0, };
for (int i = 0; i < 25; i++)
printf("%c", data[i] ^ i ^ comp[i]);
}
위의 코드를 실행하면 플래그 값이 나오는데 위치만 살짝 바꾸면 정상적인 플래그 값을 볼 수 있다. (앞의 일부 문자열을 "HackCTF{ ~~" 문자열 뒤로 붙이면 된다.)
드디어 리버싱 분야의 문제를 다 풀었다. 나머지 분야도 마저 풀어야겠다.
[HackCTF-Reversing#6] static - 250 points (0) | 2021.01.06 |
---|---|
[HackCTF-Reversing#5] keygen - 200 points (0) | 2021.01.06 |
[HackCTF-Reversing#4] Strncmp - 150 points (0) | 2021.01.05 |
[HackCTF-Reversing#3] Handray - 100 points (0) | 2021.01.03 |
[HackCTF-Reversing#2] Reversing Me - 100 points (0) | 2021.01.02 |
댓글 영역