[Reversing.kr] CSHARP

#REVERSING

Reversing.kr의 CSHARP 문제풀이


Reversing.krCSHARP 문제이다. 제목에서 알 수 있듯이 C# 관련 문제인데. 이전에 나왔던 C#보다는 어렵다.

gui

프로그램을 실행하면 Input창과 Button이 보인다. 우선 C# 으로 만든 .NET 프로그램이므로 바로 디컴파일을 시도했다.

btn_click

디컴파일 완료된 소스코드인데 버튼을 클릭하면 MetMetMet 함수를 호출한다.

metmetmet

어렵다.. MetMetMet 함수가 CorrectWrong을 다룬 다는 것은 알겠지만 내용이 나한테는 너무 어렵다.

근데 위에 MetMett함수가 있는데 디컴파일실패한 모습이다. 이 문제의 핵심이다. C# 프로그램임에도 함수의 소스코드를 디컴파일 어렵게 해놨다. ctor

좀 더 살펴보면 위와 같은 ctor를 만나는데 ctor이 생성자의 약어라고 한다.

생성자라면 프로그램의 시작에서 위 코드가 가장 먼저 실행된다는 것이다. 그리고 저 코드들을 보면 MetMett함수를 복원하는 기능이라는 것도 금세 알 수 있다.

그래서 원래는 저 생성자의 종료부분에 중단점을 걸고 복원된 MetMett 함수를 보는 것이 계획이었지만... 세그먼트 오류로 코드가 실행이 안됐다.

그래서 시도한 방법은 HxD에서 MetMett 함수의 시작과 끝을 찾은 다음 위 코드 복원 연산을 직접하는 것이였다.

MetMett 함수의 시작과 끝을 찾는 방법에서 시간을 좀 많이 소비했는데 내가 찾은 방법은 CFF_Explorer 프로그램이다.

위 프로그램의 도움으로 MetMett 함수의 시작은 0x538이고 크기는 0xEA 라는 것을 찾았다.

그리고 바로 복원 작업을 하는 C++ 코드를 작성했다.

#include <iostream>
#include <iomanip>
 
int main() {
	int arr[] = { 0x02, 0x8D, 0x68, 0x1E, 0x0B, 0x3F, 0xDE, 0xFF, 0xFF, 0xFF, 0x01, 0x15, 0x17, 0x9B, 0x02, 0x15, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x49, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x18, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x45, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x16, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x56, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x17, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x4C, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1E, 0x0A, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x2B, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1D, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x19, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x1C, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1A, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x30, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1E, 0x08, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1F, 0xE1, 0xFF, 0xFF, 0xFF, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1C, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1F, 0xED, 0xFF, 0xFF, 0xFF, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1E, 0x09, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1F, 0xA2, 0xFF, 0xFF, 0xFF, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x02, 0x1B, 0x90, 0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0x60, 0x1E, 0x74, 0x2D, 0x03, 0x01, 0x15, 0x16, 0x9B, 0x29};
	int num = 0;
	for (int i = 0; i < 0xEA; i++) {
		arr[i] += 1;
		num += arr[i];
	}
 
    arr[0x12] = num - 0x26;
    arr[0x23] = num - 3;
    arr[0x34] = num ^ 0x27;
    arr[0x45] = num - 0x15;
    arr[0x57] = 0x47 - num;
    arr[0x7c] = num ^ 0x72;
    arr[0x8d] = num ^ 80;
    arr[0x9f] = 0xeb - num;
    arr[0xb3] = 0x6a + num;
    arr[200] = 0x24 - num;
    arr[220] = num - 3;
 
    for (int i = 0; i < 0xEA; i++) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (arr[i] & 0xFF) << " ";
    }
	return 0;
}

위 코드 실행 결과로 나오는 HEX 값들을 모두 복사한 후에 아래와 같이 기존 MetMett 영역에 붙여넣기 해준다. hxd2

저장하고 다시 디컴파일을 시도하면 복원된 MetMett함수를 만날 수 있었다. metmett2

위 코드를 토대로 역연산 해주면 문자가 나오는데 이 문자가 Flag는 아니다.

이 Flag를 base64 디코딩 해줘야 실제 Flag인데

그 이유는 MetMetMet함수에서 문자열을 base64 인코딩한 후 비교하기 때문이다.

마지막으로 Flag를 넣으면 성공 correct