본문 바로가기

SWUFORCE 워게임👊🏻

[Dreamhack] LEVEL1 ; reversing ; Happy New Year!

 

 

1. 문제 파일을 받았다. chall 이름의 파일 한 개가 있다.

 

2. IDA로 열어 main 부분을 살펴봤다. 

 

3. F5 눌러서 Hex-Rays 의사코드로 변환한 후 살펴봤다.

값을 넣어서 어떤 조건을 만족하면 Flag를 출력하는 방식이다.

 

입력값 s가 정답이 되는 조건은 다음과 같다.

1) 문자열 길이가 정확히 59바이트여야 함

__isoc99_scanf("%59s", s);
if ( strlen(s) == 59 )

 

2) 입력값이 그대로 dest에 복사됨

  • 입력한 문자열 s가 그대로 dest 버퍼로 복사됨
  • 이후 연산은 모두 dest 기준으로 수행됨
strcpy(dest, s);

 

3) dest[i] ^ key[i] 결과가 정해진 문자열과 일치해야 함

for ( i = 0; i <= 58; ++i )
    dest[i] ^= *((_BYTE *)v5 + i);

if ( !strcmp(dest,
"Please_input_the_correct_new_year_greetings_at_this_problem") )

 

즉, 미리 준비된 59바이트 XOR 키(v5)가 존재하고

XOR 키와 입력값 s를 연산했을 때

"Please_input_the_correct_new_year_greetings_at_this_problem"이 정확히 나와야 한다.

 

입력값은 target 문자열과 XOR 키를 역연산하여 계산할 수 있다.

 

3. XOR 키를 찾아보겠다.

 

for ( i = 0; i <= 58; ++i )
    dest[i] ^= *((_BYTE *)v5 + i);

 

XOR 연산에 사용되는 v5는 디컴파일 코드상 포인터 변수로 나타나지만,
어셈블리 분석 결과 v5는 스택 영역의 var_120 주소를 가리키고 있음을 확인할 수 있다.
실제 XOR 연산은 [rbp + var_120 + i] 형태로 수행되며,
이는 var_120부터 연속적으로 저장된 59바이트 데이터를
XOR 키로 사용하고 있음을 의미한다.
따라서 v5는 var_120의 시작 주소와 동일하다.

 

 

4. v5(= var_120)의 초기화 지점 코드이다. 여기서 XOR 키가 세팅되고 있는 것을 볼 수 있다.

 

1) 단순 QWORD 저장 구간 (모두 리틀엔디안 변환이 필요함)

변수
var_120 0C313A0A11150D18
var_118 2C37426D44472F19
var_110 1B1A3A1704000F00
var_108 1301263B1904312A
var_100 361F06041A0A3E17

 

2) 겹쳐서 쓰는 구간

mov qword [var_F8], rdx
mov qword [var_F8+3], rax
mov [var_ED], rdx

 

주소 덮어쓰기 구조
var_F8[0~7] rdx
var_F8[3~10] rax (겹침 발생)
var_ED (F8+11) rdx

 

 

5. 역연산의 원리는 다음과 같다.

A ^ B ^ B = A

따라서 s = target_string ^ key 즉, s[i] = target[i] ^ key[i]

6. 복원을 해보면

타겟 문자열 : Please_input_the_correct_new_year_greetings_at_this_problem

XOR 키 : IDA에서 var_120~var_ED 영역의 바이트들을 리틀엔디안으로 추출

 

복구 스크립트를 짜서 계산해보면 최종 플래그를 얻을 수 있다.

 

해결 완~👊🏻