플래그를 이미지로 출력해주지만 일부가 가려져있어 플래그를 읽을 수 없는 상태의 프로그램.
- 파일 실행
- 정적 분석
- 동적 분석
- 파일 바이너리 수정
다운 받은 파일을 실행해보면 플래그가 가려져있는 것을 볼 수 있음.
IDA로 Patch.exe 파일을 실행함.
이 문제는 WinAPI를 이용해 만들어진 GUI 프로그램이기 때문에 WinMain 함수를 찾아야 함.
이 함수는 보편적으로 윈도우를 생성하고 관련된 초기화 작업을 진행함.
이와 고나련된 API를 상호참조하는 방식으로 찾을 수 있음.
프로그램이 DLL로부터 임포트해 사용하는 함수의 목록은 Imports 탭에 존재함. 윈도우 생성 시 사용되는 CreateWindowExW 함수를 더블클릭해서 함수가 임포트되는 곳으로 갈 수 있음.
x키를 눌러서 함수가 사용되는 곳을 보면 WinMain 함수에서 사용하고 있음을 확인 가능.
MSDN에서 RegisterClassExW 함수에 대해서 알아봤음.
CreateWindow나 CreateWindowEx 함수에 대한 호출에 차후 사용할 수 있도록 윈도우 클래스를 등록하는 함수임.
저 디컴파일된 곳에서 인자로 v11 변수가 들어감을 확인할 수 있음.
가장 중요한 부분. 윈도우의 메시지 콜백을 설정하는 부분임.
보편적으로 메시지 콜백함수에서 윈도우의 동작이 정의되어 있기 때문에 sub_1400032F0 함수를 분석해 어떤 동작을 수행하는지 알아야 함.
MSDN에서 찾은 창 클래스 관련 문서임. 지금 Patch.exe 파일은 아래처럼 WNDCLASSEXW로 구조체를 만들어 놓은 것 같음. 구조체의 태그는 이제 v11로.
lpfnWndProc 창 프로시저 혹은 "window proc" 라는 애플리케이션 정의 함수에 대한 포인터임.
창 프로시저는 창의 동작 대부분을 정의함. 여기서 구조체의 멤버로 할용되고 있는 것 같음.
RegisterClass(&wc); -> 구조체의 주소를 RegisterClass 함수에 전달함.
이 파일에서는 구조체의 주소가 v11인 것으로 보임.
*CallBack 함수
함수는 일반적으로 프로그래머에 의해 작성되고 호출됨.
일반적인 함수와 비슷하지만, 호출되는 시점이 시스템에 의해 결정됨.
콜백함수(프로시저) WinMain에서 WndClass.lpfnWndProc = WndProc; 로 WNDCLASS 구조체에 등록된 뒤에 RegisterCladd(&WndClass); 되어진 이후 따로 호출하지 않음.
하지만 구조체의 정보가 등록된 이후는 WinMain 내부의 메시지 루프 부분을 통해
while(GetMessage(&Message, NULL, 0, 0))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
윈도우 메시지 큐에서 GetMessage로 가져옴.
TranslateMessage -> 가상 키 메시지를 문자 메시지로 변환함.
DispatchMessage -> 연결된 콜백 함수(프로시저)에 전달함.
일단 sub_1400032F0 함수를 디컴파일해보면 switch_case 구문의 세 개의 case 중 0xFu case에서 Paint와 관련된 역할을 하는 것을 볼 수 있음.
BeginPaint와 EndPaint 함수 사이에서 플래그를 출력해줄 것이기 때문에 플래그를 그리는 것으로 보이는 sub_140002C40 함수를 분석해봐야함.
sub_140002C40을 디컴파일한 화면임.
51라인 부터 75라인까지는 동일한 sub_140002B80 함수를 사용하고 있음. 같은 함수가 연속적으로 출력되는 형태로 보아 이게 플래그를 지운 검은 게 아닐까 하는 합리적 의심이 들게 됨.
이후 함수들은 다 다르니까 얘들은 반복적인 형태가 아닌 각각 특정한 그림을 그리고 있는 것으로 생각할 수 있음.
먼저 sub_140002B80 함수를 분석해보겠음.
지금 라인 13, 16, 20, 23 에서 펜 생성하고, 선 그리고 스무스하게 만들고 다시 펜 지우고 하는 식의 그리는 행위가 이뤄지는 것을 볼 수 있음. 근데 sub_1400017A0은 펜 생성하고 선을 여러개 그림. 이를 통해 이 부분이 글자를 하나씩 그리는 부분이라고 추측할 수 있음.
그럼 이제 동적 분석을 해보자.
sub_1400032F0에서 sub_140002B80을 호출하는 첫 부분에 F2로 브레이크 포인트 걸어두고 F9키로 프로그램을 실행시킴. F8 단축키로 함수를 실행한 후 프로그램에 어떤 변화가 생기는지 확인함.
60라인 갈 때까지 F8을 눌렀더니 아래 화면처럼 점점 검은 색으로 채워지는 것을 볼 수 있었음.
그럼 이제 이 선이 안그려지도록 바이너리를 패치해야함.
g를 눌러서 선을 그리는 함수인 sub_140002B80으로 이동한다는데 난 좀 이상해서 그냥 프로그램을 다시 시작하고 Function name에서 해당 함수를 찾아서 이동했음.
Edit -> Patch Program -> Assemble 을 클릭해서 나오는 창에 Instruction에 함수를 바로 리턴하도록 ret 인스트럭션을 입력하고 ok를 눌러줌.
패치한 내용을 실제 바이너리에 적용하기 위해
Edit -> Patch -> Program -> Apply patches to input file 메뉴를 클릭해줌. 바로 ok를 누르면 바이너리 패치가 실제 파일에 적용됨.
'Dreamhack' 카테고리의 다른 글
시스템 해킹 Stage 1 (0) | 2022.07.18 |
---|---|
리버싱 09 - 혼자 실습 (0) | 2022.07.12 |
리버싱 07 - rev-basic-1 (0) | 2022.07.12 |
리버싱 06 - rev-basic-0 (0) | 2022.07.12 |
리버싱 05 - x86 Assembly (0) | 2022.07.12 |