<보안 study>/리버싱

MFC 프레임워크 기반 앱 시작지점

gosoeungduk 2023. 1. 6. 23:16
반응형

#MFC #리버싱 #Reversing


MFC 프레임 워크 기반 앱의 경우, MFC 에서 선언 해놓은 클래스들을 상속 받아서 사용자 클래스를 정의하는 식의 개발이 이루어진다.

 

그만큼 MFC 프레임 워크에서 기본적으로 제공해주는 기반이 상당한데, 최근 MFC 관련 앱을 리버싱해본 결과 리버싱 과정에서도 그러한 기반 클래스들이 어떻게 동작하고, Dialog 까지 생성하는지 등등 알아야할 것이 많아보였다.

 

흔히 금방 찾을 수 있는 main 함수의 경우에도 함수 vtable 어딘가에 심볼이 깨진채로 들어가있어서 정적분석으로는 금방 가늠하기 어렵고, 동적분석으로 해당 함수를 찾아야한다고 판단하였다.

 

수 많은 문서를 탐색하면서 main 포인트를 찾는 과정을 간략히 정리해보겠다.

int start()
{
  _security_init_cookie();
  return _tmainCRTStartup();
}

우선 _tmainCRTStartup 함수 부터 시작된다. 최초 EntryPoint 함수는 싱글 다이얼로그냐 멀티 다이얼로그 방식이냐에 따라 _tmainCRTStartup 이 아닌 함수일 수도 있다고는 한다.

 

int _tmainCRTStartup()
{
    /* ... 생략 ... */
    wShowWindow = 0xA;                            
      if ( (StartupInfo.dwFlags & 1) != 0 )         
        wShowWindow = StartupInfo.wShowWindow;      
      result = AfxWinMain(0x7FF6B5A70000i64, 0i64, _wcmdln, wShowWindow);
}

이처럼 _tmainCRTStartup 함수에서 일정 조건을 무사히 통과하면 AfxWinMain 함수를 통해 진짜 main 로직을 호출하게 된다.

 

// mfc90u.dll:AfxWinMain
mfc90u.dll:000000005A8E51E4 mov     rax, rsp
mfc90u.dll:000000005A8E51E7 mov     [rax+8], rbx
mfc90u.dll:000000005A8E51EB mov     [rax+10h], rbp
mfc90u.dll:000000005A8E51EF mov     [rax+18h], rsi
mfc90u.dll:000000005A8E51F3 mov     [rax+20h], rdi
mfc90u.dll:000000005A8E51F7 push    r12
mfc90u.dll:000000005A8E51F9 push    r13
mfc90u.dll:000000005A8E51FB push    r14
mfc90u.dll:000000005A8E51FD sub     rsp, 20h
mfc90u.dll:000000005A8E5201 mov     ebx, r9d
mfc90u.dll:000000005A8E5204 mov     rdi, r8
mfc90u.dll:000000005A8E5207 mov     rsi, rdx
mfc90u.dll:000000005A8E520A mov     rbp, rcx
mfc90u.dll:000000005A8E520D or      r13d, 0FFFFFFFFh
mfc90u.dll:000000005A8E5211 call    mfc90u_1104
mfc90u.dll:000000005A8E5216 mov     r12, [rax+8]
mfc90u.dll:000000005A8E521A call    mfc90u_1103
mfc90u.dll:000000005A8E521F mov     r9d, ebx
mfc90u.dll:000000005A8E5222 mov     r14, [rax+8] ; 함수 vtable 포인터 r14 에 저장
mfc90u.dll:000000005A8E5226 mov     r8, rdi
mfc90u.dll:000000005A8E5229 mov     rdx, rsi
mfc90u.dll:000000005A8E522C mov     rcx, rbp
mfc90u.dll:000000005A8E522F call    near ptr mfc90u_1232
mfc90u.dll:000000005A8E5234 test    eax, eax
mfc90u.dll:000000005A8E5236 jz      short loc_5A8E5293
mfc90u.dll:000000005A8E5238 test    r14, r14
mfc90u.dll:000000005A8E523B jz      short loc_5A8E524D
mfc90u.dll:000000005A8E523D mov     rax, [r14]
mfc90u.dll:000000005A8E5240 mov     rcx, r14
mfc90u.dll:000000005A8E5243 call    qword ptr [rax+130h] ; vtable_base + 0x130 => CWinApp::InitApplication

위 부분은 AfxWinMain 함수의 코드이다. 가만 보면 맨 아래에 $rax 기반으로 오프셋을 옮기며 함수호출을 하는 구문을 볼 수 있을텐데, MFC 앱이 사용하는 모든 함수가 담겨있는 vtable 베이스를 $rax 에 담아서 그 것을 기준으로 함수호출이 이루어진다.

 

// vtable 시작점
.rdata:00007FF6B5FE7AD0 dq offset sub_7FF6B5A857F0
.rdata:00007FF6B5FE7AD8 dq offset unknown_libname_9             ; Microsoft VisualC v7/14 64bit runtime
.rdata:00007FF6B5FE7AE0 dq offset sub_7FF6B5BC92C0
.rdata:00007FF6B5FE7AE8 dq offset unknown_libname_9             ; Microsoft VisualC v7/14 64bit runtime
.rdata:00007FF6B5FE7AF0 dq offset ?OnCmdMsg@CCmdTarget@@UEAAHIHPEAXPEAUAFX_CMDHANDLERINFO@@@Z ; CCmdTarget
/* ... 쭈욱 이어진다 ... */
.rdata:00007FF6B5FE7BF8 dq offset ?InitApplication@CWinApp@@UEAAHXZ ; CWinApp::InitApplication(void)

vtable 은 이런 식이다.

 

mfc90u.dll:000000005A8E524D mov     rax, [r12]
mfc90u.dll:000000005A8E5251 mov     rcx, r12
mfc90u.dll:000000005A8E5254 call    qword ptr [rax+0B0h]            ; real main function

아무튼 CWinApp::InitApplication 함수가 잘 끝나면 아래로 내려와서 또 함수 하나를 호출하는데 [rax+0xB0] 부분이 우리가 원하는 앱의 진짜 시작 로직이다.

 

해당 부분을 실행시켜보면, 다이얼로그 창이 있는 앱의 경우 다이얼로그가 초기화 되는 모습을 볼 수 있을 것이다.

 

해당 함수를 찾았다면, 깨진 심볼을 직접 복구 시켜주고 이제부터는 정적분석이 가능해지는 타이밍이 되는 것이다.

 

동적 디버깅을 진득하게 해보면 어려운 부분은 아니지만, MFC 앱이 생각보다 마주칠일이 거의 없어서 나중에 바로바로 꺼내보기 위해 여기까지 정리해본다.

반응형

'<보안 study> > 리버싱' 카테고리의 다른 글

Galaxy S20(SM-G981N) 루팅  (5) 2023.09.02
[UE4] FNamePool 위치 식별  (3) 2023.05.23
공유메모리 매핑  (0) 2023.01.04
Cracking Example  (1) 2022.11.21
자바 1.8.0 다운  (0) 2022.09.07