
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 영역의 바이트들을 리틀엔디안으로 추출
복구 스크립트를 짜서 계산해보면 최종 플래그를 얻을 수 있다.


해결 완~👊🏻
'SWUFORCE 워게임👊🏻' 카테고리의 다른 글
| [Webhacking] old - 25 (0) | 2026.03.31 |
|---|---|
| [워게임 실습] reversing ; Happy New Year! (0) | 2026.01.13 |
| [워게임 실습] Simple-ssti ; web (0) | 2025.11.04 |
| [Dreamhack] LEVEL1 ; web ; Simple-ssti (0) | 2025.11.04 |
| [Dreamhack] TOP secret! ; crypto (0) | 2025.10.28 |