HateIntel

The binary is for a non-Intel architecture and will not run, so the whole solve is static analysis in IDA.

2026.08.18 Reversing original post

실행을 시도해보았더니, CPU 아키텍처가 안 맞아서 실행 자체가 불가능한 상태입니다. 대신 아이다를 사용한 정적 분석을 해보려고 합니다.

문자열 찾기를 통해 메인 함수를 찾아냅니다. 디컴파일링을 아이다에서 시도해보면 현재 파일에 맞는 디컴파일러가 없다고 이야기합니다. 아이다는 ARM64 (Apple Silicon) 디컴파일러를 지원하지 않는 거 같습니다. 기드라 디컴파일러로 해봅시다.

Figure 1

여기는 디컴파일된 코드다:

int FUN_00002224(void) {
    char input[80];
    unsigned int key_len;
    int i;
    int offset;

    offset = 4;
    printf("Input key : ");
    scanf("%s", input);
    key_len = strlen(input);

    // 입력 문자열을 변형하는 함수
    FUN_0000232c(input, offset);

    i = 0;
    while (1) {
        if (key_len <= i) {
            puts("Correct Key!");
            return 0;
        }
        if (input[i] != ((char *)&DAT_00003004)[i])
            break;
        i++;
    }
    puts("Wrong Key!");
    return 0;
}

전체 흐름은 이렇다.

  1. 문자열 입력 받음
  2. strlen 으로 길이 계산
  3. FUN_0000232c(input, 4) 호출 → 입력값 변형
  4. 변형된 입력값을 정답 테이블과 한 글자씩 비교
  5. 전부 같으면 “Correct Key!”

이제 진짜 필요한 건 두 가지로 나뉜다. FUN_0000232c() (입력값을 어떻게 바꾸는지) 와 DAT_00003004 (변형된 input 과 비교되는 값). 그럼 FUN_0000232c() 를 디컴파일해보자. 두 번 클릭해 따라가면 된다.

void FUN_0000232c(char *param_1, int param_2) {
    char cVar1;
    size_t sVar2;
    int local_14;
    int local_10;

    for (local_14 = 0; local_14 < param_2; local_14 = local_14 + 1) {
        for (local_10 = 0; sVar2 = strlen(param_1), local_10 < (int)sVar2; local_10 = local_10 + 1) {
            cVar1 = FUN_00002494(param_1[local_10], 1);
            param_1[local_10] = cVar1;
        }
    }
    return;
}

중요 포인트:

  • 문자열 전체를 round = 4번
  • 각 문자마다 FUN_00002494(char, 1) 적용

즉, 한 글자당 FUN_00002494(…, 1) 을 4번 적용한 결과가 DAT_00003004 와 같아야 함. 여기서 정확한 연산 방법을 알려면 FUN_00002494() 도 디컴파일해야 함:

uint FUN_00002494(byte param_1, int param_2) {
    undefined4 local_10;
    undefined4 local_c;

    local_10 = (uint)param_1;
    for (local_c = 0; local_c < param_2; local_c = local_c + 1) {
        local_10 = local_10 << 1;
        if ((local_10 & 0x100) != 0) {
            local_10 = local_10 | 1;
        }
    }
    return local_10 & 0xff;
}

이건 8비트 기준 왼쪽 회전 (Rotate Left, ROL) 입니다. 호출 구조는 FUN_0000232c(input, 4) 이고 내부에서 c = FUN_00002494(c, 1) 이므로, 한 문자에 대해 ROL 1 을 4번 반복하는 것이다. 결과적으로:

최종 변형 = ROL(input_char, 4)   (8비트 기준으로 왼쪽 4비트 회전)

검증 로직을 요약하면 ROL4(input[i]) == DAT_00003004[i] 이다. 그러므로 원래 입력 키는 input[i] = ROR4(DAT_00003004[i]) (오른쪽으로 4비트 회전) 이다.

그 후 정보를 바탕으로 코드를 만들기 위해, DAT_00003004 도 따라가면 값을 알 수 있습니다.

Figure 2

이것을 바탕으로 만든 파이썬 코드입니다.

data = [
    0x44, 0xf6, 0xf5, 0x57, 0xf5, 0xc6, 0x96, 0xb6, 0x56, 0xf5,
    0x14, 0x25, 0xd4, 0xf5, 0x96, 0xe6, 0x37, 0x47, 0x27, 0x57,
    0x36, 0x47, 0x96, 0x03, 0xe6, 0xf3, 0xa3, 0x92
]


def ror4(x):
    return ((x >> 4) | (x << 4)) & 0xff


key = ''.join(chr(ror4(b)) for b in data)
print(key)

출력하면 키 값은:

Do_u_like_ARM_instructi0n?:)