카테고리 없음

리버싱 입문 Day 13 - XOR + index 구조의 CTF 문제 분석

baa1983 2026. 4. 24. 14:43

 

 

 

어제에 이어서 오늘도 CTF 스타일의 간단한 Crackme 문제를 하나 더 풀어봤다.

어제 문제에서 느꼈던 핵심은
“단순한 구조를 끝까지 밀고 가는 것” 이었고,
오늘은 그 연장선에서 XOR과 index 연산이 섞인 형태를 직접 확인해보는 과정이었다.

   

    1. 문제 구조

 

이번 문제 역시 기본적인 구조는 동일했다.

  • main에서 입력을 받는다
  • check 함수로 전달된다
  • 조건을 만족하면 Correct 출력

문제를 c로 나타내면 다음과 같은 구조

 

 

 

 

기드라로 분석해보니 전체 흐름은 익숙한 형태였다.

CALL strlen
CMP RAX, 0x9
 

즉, 이번에도 입력 길이는 9자리로 고정되어 있었다.

이 부분은 이제 거의 자동으로 보이는 수준이다.

 

 

   2. 키값 확인

이번 문제에서도 key는 코드 내부에 고정된 값으로 존재했다.

MOV RAX, 0x7067746675716775
MOV byte ptr [RBP + local_e], 0x63
 

이를 바이트 단위로 풀어보면 다음과 같다.

75 67 71 75 66 74 67 70 63
 

즉 총 9개의 key 값이 존재한다는 것을 확인할 수 있었다.

 

 

  3. 핵심 연산

이번 문제에서 중요한 부분은 이 연산이었다.

XOR EAX, 0x20
ADD EAX, EDX
CMP byte ptr [RBP + local_d], AL
 

처음 구조를 보면 다음과 같이 해석할 수 있다.

 
(input[i] ^ 0x20) + i == key[i]
 

여기까지는 비교적 빠르게 파악이 가능했다.

 

 

  4. 헷갈린 부분

 

이번 문제에서 잠깐 헷갈렸던 부분은 아래 코드였다.

ADD RAX, RDX
 

처음에는 이게 수식에 포함되는 연산인지 고민했지만,
결론적으로는 배열 주소 계산이었다.

즉,

 
key[i]
 

를 가져오기 위해

key 주소 + i
 

를 계산하는 부분이었다.

이걸 수식으로 착각하면 전체 흐름이 꼬이기 시작한다.

정리하면:

ADD EAX, EDX → 실제 값 연산 (+ i)
ADD RAX, RDX → 주소 이동 (배열 접근)
 

이 구분이 중요하다.

 

 

  5. 역산 과정

전체 수식이 정리되면 역산은 간단해진다.

(input[i] ^ 0x20) + i = key[i]
 

input[i] = (key[i] - i) ^ 0x20
 

이 식을 기준으로 값을 하나씩 계산하면 된다.

 

 

  6. 최종 결과

계산 결과 다음 문자열이 도출됐다.

UFORBOAI{
 

실행해보면 정상적으로 Correct가 출력된다.

 

 

   오늘 느낀 점

이번 문제는 어제보다 구조가 조금 더 추가됐지만,
결국 핵심은 동일했다.

  • 길이 체크
  • 반복문
  • 간단한 연산
  • key 비교

여기서 중요한 건
“복잡하게 보이는 부분을 제거하고 핵심만 남기는 것” 이었다.

특히 오늘은 이걸 확실히 느꼈다.

“모든 ADD가 의미 있는 연산은 아니다”

주소 계산과 실제 연산을 구분하지 못하면
문제를 틀릴 수밖에 없다.

 

  • strlen 기반 길이 체크 파악 가능
  • 반복문 구조 인식 가능
  • XOR / ADD / index 연산 해석 가능
  • 역산식 도출 가능

속도는 아직 빠르지 않지만
이제는 “어디를 봐야 하는지”는 확실히 보인다.