[DreamHack.io] rev-basic-3 풀이
[DreamHack.io] rev-basic-3 풀이
오랜만에 rev-basic-3를 다시 풀어보았다.
Environments
| Name | Config |
|---|---|
| CPU | Apple M1 |
| Architecture | ARM64 |
| OS | Microsoft Windows 11 on ARM |
| Tools | - Hex-Rays IDA 7.5 |
문제
URL: dreamhack.io/wargame/challenges/17/
Get Input
Print Wrong 또는 Correct
요약: MSVC++ 2019 AMD64 어플리케이션 chall3.exe 로부터 correct 를 출력 할 수 있는 문자열을 찾기
File Format
Upx not packed MSVC++ Windows 64 bit executable
checksec
| Name | Status |
|---|---|
| NX | Yes |
| Canary | Yes |
| ASLR | Yes |
| Dynamic Base | Yes |
| High Entropy VA | Yes |
| SEH | Yes |
| SafeSEH | / |
| Force Integrity | Yes |
| Control Flow Guard | No |
| Isolation | Yes |
| Auth | No |
풀이

IDA를 통한 분석 시 sub_7FF7A0FF1000 으로부터 결과 값을 전달 받아 jz를 통해 분기하는 것을 확인 가능. 즉 앞서 언급한 메서드에서 EAX가 0으로 설정 될 경우 Worng을 출력하며 종료된다. 따라서 jnz 등으로 patch 시 Correct를 받을 수 있지만 목표가 이것이 아니므로 생략한다.

빠른 진행을 위해 disassemble 된 코드를 분석하자면 특정 배열과 매개변수로 받은 int 타입을 기준으로 계산식을 통해 0 또는 1을 반환한다. 한자리라도 일치하지 않으면 0을 반환하는 형식이다. 우선 특정 배열 (byte_7FF7A0FF3000)을 한번 봐보자.

우선 hex 값이므로 dec 혹은 ascii 값으로 보면 다음과 같다.
.data:00007FF7A0FF3000 byte_7FF7A0FF3000 db 'I', '`', 'g', 't', 'c', 'g', 'B', 'f', '€', 'x', 2 dup('i')
.data:00007FF7A0FF3000 db '{', '™', 'm', 'ˆ', 'h', '”', 'Ÿ', 8Dh, 'M', '¥', 9Dh
.data:00007FF7A0FF3000 db 'E', 8 dup(0)
.data:00007FF7A0FF3000 byte_7FF7A0FF3000 db 73, 96, 103, 116, 99, 103, 66, 102, 128, 120, 2 dup(105)
.data:00007FF7A0FF3000 db 123, 153, 109, 136, 104, 148, 159, 141, 77, 165, 157
.data:00007FF7A0FF3000 db 69, 8 dup(0)
I`gtcgBf€x...

정상적이지 않은 문자열과 코드를 보았을 때 계산식을 통해 통과 가능한 문자열을 계산 할 수 있음을 알 수 있다. 사용작 입력 값을 input, 도출 해야할 원래의 문자열을 str 이라 보고 계산식을 정리한다. 이러면 어떠한 input을 넣었을 때 str에 만족하는 값이 나오는지 알 수 있다.
import java.util.*;
public class Main {
public static void main(String[] args) {
int arr[] = { 73, 96, 103, 116, 99, 103, 66, 102, 128, 120, 105, 105, 123, 153, 109, 136, 104, 148, 159, 141, 77, 165, 157, 69 };
ArrayList <String> list = new ArrayList<>();
for (int i = 0; i < 24; i++) { list.add(Character.toString((arr[i] - ( 2 * i)) ^ i)); }
for (int i = 0; i < 24; i++) { System.out.print(list.get(i)); }
}
}
머리와 펜으로 계산 할 수도 있지만 간단하게 컴퓨터에게 맡기기로 했다. 그러면 우리가 입력해야할 문자열 str을 알 수 있다.