[dreamhack] patch

Monitor In Secure☃️·2024년 5월 9일

wargame_rev

목록 보기
8/11

우선 파일을 ida로 열어서 디컴파일 시켰다. (WinMain 위치에서 디컴파일 진행)

꽤나 복잡한 코드들이 나왔다.

우선 분석 전 프로그램을 실행할 수 있어서 실행해보았다.

실행해본 결과, 플래그 값 부분이 가려져서 보이지 않는다는 것을 확인할 수 있다. 분석을 통해 어떤 조건을 만족해야 플래그 값을 볼 수 있을 것 같다.

[main을 디컴파일한 결과]

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  HCURSOR CursorW; // rax
  HWND Window; // rax
  HWND v8; // rbx
  HACCEL AcceleratorsW; // rbx
  WNDCLASSEXW v11; // [rsp+60h] [rbp-A8h] BYREF
  struct tagMSG Msg; // [rsp+B0h] [rbp-58h] BYREF

  LoadStringW(hInstance, 0x67u, &WindowName, 100);
  LoadStringW(hInstance, 0x6Du, &ClassName, 100);
  v11.cbSize = 80;
  v11.style = 3;
  v11.lpfnWndProc = (WNDPROC)sub_7FF63D2D32F0;
  *(_QWORD *)&v11.cbClsExtra = 0LL;
  v11.hInstance = hInstance;
  v11.hIcon = LoadIconW(hInstance, (LPCWSTR)0x6B);
  CursorW = LoadCursorW(0LL, (LPCWSTR)0x7F00);
  *(__m128i *)&v11.hbrBackground = _mm_load_si128((const __m128i *)&xmmword_7FF63D2D53F0);
  v11.hCursor = CursorW;
  v11.lpszClassName = &ClassName;
  v11.hIconSm = LoadIconW(hInstance, (LPCWSTR)0x6C);
  RegisterClassExW(&v11);
  qword_7FF63D2D7880 = (__int64)&unk_7FF63D2D78A0;
  Window = CreateWindowExW(0, &ClassName, &WindowName, 0xC80000u, 0x80000000, 0, 600, 200, 0LL, 0LL, hInstance, 0LL);
  v8 = Window;
  if ( Window )
  {
    hWnd = Window;
    dword_7FF63D2D7920 = 600;
    dword_7FF63D2D7924 = 200;
    GdiplusStartup(&unk_7FF63D2D78A0, &dword_7FF63D2D78A8, 0LL);
    ShowWindow(v8, nShowCmd);
    UpdateWindow(v8);
    AcceleratorsW = LoadAcceleratorsW(hInstance, (LPCWSTR)0x6D);
    while ( GetMessageW(&Msg, 0LL, 0, 0) )
    {
      if ( !TranslateAcceleratorW(Msg.hwnd, AcceleratorsW, &Msg) )
      {
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
      }
    }
    LODWORD(Window) = Msg.wParam;
  }
  return (int)Window;
}

처음 존재하는 함수인 sub_7FF63D2D32F0 안을 살펴본다.


beginpaint, gdipCreateFromHDC 함수의 이름을 통해 그래픽과 관련된 함수라는 것을 확인하였다.

밑에쪽에 의문의 함수 하나가 또 있다.(sub_7FF63D2D2C40) 이 역시 함수 안으로 들어가봐서 확인한다.

[sub_7FF63D2D2C40 디컴파일 결과]

char __fastcall sub_7FF63D2D2C40(__int64 a1, int a2)
{
  int v2; // ebx
  int v3; // edx
  int v4; // edx
  int v5; // edx
  int v6; // edx
  int v7; // edx
  int v8; // edx
  int v9; // edx
  int v10; // edx
  int v11; // edx
  int v12; // edx
  int v13; // edx
  int v14; // edx
  int v15; // edx
  int v16; // edx
  int v17; // edx
  int v18; // edx
  int v19; // edx
  int v20; // edx
  int v21; // edx
  int v22; // edx
  int v23; // edx
  int v24; // edx
  int v25; // edx
  int v26; // edx
  __int64 v27; // rbx
  __int64 v28; // r8
  __int64 v29; // r8
  __int64 v30; // rdx
  __int64 v31; // r8
  __int64 v32; // rdx
  __int64 v33; // r8
  __int64 v34; // rdx
  __int64 v35; // r8
  __int64 v36; // rdx
  __int64 v37; // r8
  __int64 v38; // rdx
  __int64 v39; // r8
  __int64 v40; // rdx
  __int64 v41; // r8
  __int64 v42; // r8
  __int64 v43; // rdx
  __int64 v44; // r8
  __int64 v45; // r8
  __int64 v46; // rdx
  __int64 v47; // r8

  v2 = qword_7FF63D2D7880;
  sub_7FF63D2D2B80(qword_7FF63D2D7880, a2, 30, 470, 80, -16777216);
  sub_7FF63D2D2B80(v2, v3, 35, 470, 75, -16777216);
  sub_7FF63D2D2B80(v2, v4, 40, 470, 70, -16777216);
  sub_7FF63D2D2B80(v2, v5, 45, 470, 65, -16777216);
  sub_7FF63D2D2B80(v2, v6, 50, 470, 60, -16777216);
  sub_7FF63D2D2B80(v2, v7, 55, 470, 55, -16777216);
  sub_7FF63D2D2B80(v2, v8, 60, 470, 50, -16777216);
  sub_7FF63D2D2B80(v2, v9, 65, 470, 45, -16777216);
  sub_7FF63D2D2B80(v2, v10, 70, 470, 40, -16777216);
  sub_7FF63D2D2B80(v2, v11, 75, 470, 75, -16777216);
  sub_7FF63D2D2B80(v2, v12, 80, 400, 60, -16777216);
  sub_7FF63D2D2B80(v2, v13, 30, 470, 90, -16777216);
  sub_7FF63D2D2B80(v2, v14, 35, 470, 30, -16777216);
  sub_7FF63D2D2B80(v2, v15, 40, 470, 35, -16777216);
  sub_7FF63D2D2B80(v2, v16, 45, 470, 50, -16777216);
  sub_7FF63D2D2B80(v2, v17, 50, 470, 40, -16777216);
  sub_7FF63D2D2B80(v2, v18, 55, 400, 90, -16777216);
  sub_7FF63D2D2B80(v2, v19, 60, 470, 60, -16777216);
  sub_7FF63D2D2B80(v2, v20, 65, 470, 30, -16777216);
  sub_7FF63D2D2B80(v2, v21, 70, 470, 80, -16777216);
  sub_7FF63D2D2B80(v2, v22, 75, 470, 70, -16777216);
  sub_7FF63D2D2B80(v2, v23, 80, 470, 60, -16777216);
  sub_7FF63D2D2B80(v2, v24, 80, 470, 80, -16777216);
  sub_7FF63D2D2B80(v2, v25, 80, 470, 70, -16777216);
  sub_7FF63D2D2B80(v2, v26, 90, 470, 90, -16777216);
  v27 = qword_7FF63D2D7880;
  sub_7FF63D2D17A0(qword_7FF63D2D7880, 40LL, v28, 4278190080LL);
  sub_7FF63D2D1C80(v27, 80LL, v29, 4278190080LL);
  sub_7FF63D2D2640(v27, v30, v31, 4278190080LL);
  sub_7FF63D2D20F0(v27, v32, v33, 4278190080LL);
  sub_7FF63D2D2390(v27, v34, v35, 4278190080LL);
  sub_7FF63D2D1240(v27, v36, v37, 4278190080LL);
  sub_7FF63D2D1F20(v27, v38, v39, 4278190080LL);
  sub_7FF63D2D1560(v27, v40, v41, 4278190080LL);
  sub_7FF63D2D1C80(v27, 360LL, v42, 4278190080LL);
  sub_7FF63D2D19D0(v27, v43, v44, 4278190080LL);
  sub_7FF63D2D17A0(v27, 440LL, v45, 4278190080LL);
  sub_7FF63D2D2870(v27, v46, v47, 4278190080LL);
  return 0;
}

많은 변수들이 할당되어 있고, 절반 이상이 함수 sub_7FF63D2D2880 이라는 함수를 지나고 있다는 것을 파악할 수 있다.

이 수상한 함수를 살펴보자.

GdipCreatePen1, GdipDrawLineI 등을 통해 이 함수가 바로 선을 그린다는 것을 알 수 있다. 따라서 많은 변수에 관련 함수를 호출하여 선을 촘촘하게 그려 값이 안보인다는 것을 파악할 수 있다.

플래그값이 보이도록하기 위해 첫번째로 생각한 단순한 방법은 '관련 함수를 실행시키지 않으면 되는 거 아닌가?' 하는 생각이었다.
그래서 sub_7FF63D2D2880이 시작하는 부분에 break를 걸어서 실행해보았다.


stepover(F8)해가며 확인해보았는데, 이러한 결과값이 출력되고 있었다..!

정확히 파악하기 위해 sub_7FF63D2D2880함수를 호출하지 않은 시점에도 break를 걸어서 실행시켜보았다. (실행->F9->F8)
확인해보니 선으로 먼저 가려지고, 앞에 DH가 출력되는 구조였다..!

그래서 이 방법은 통하지 않을 것 같다.. 다른 방법을 생각해보자.


생각해낸 방법은 바로..! 해당 함수를 진행시키지 않고, 실행하는 방법이다! 관련 함수 처음 부분에 return함수로 패치를 해주면 함수가 실행되지 않고 빠져나와 플래그 값이 출력 가능할 것이다.

어셈블리어로 패치를 할 것이기 때문에, tab을 누르면 해당 함수 위치의 어셈블리어를 확인할 수 있다.

그럼 패치를 진행해보자. (edit → Patch program → Assemble)

patch로 코드를 수정한 다음, 이를 저장해서 실행해보도록 하자. (edit → Patch Program → Apply patches to input file)

이 후 실행파일을 실행시켜보면 플래그값이 잘 출력되는 것을 확인할 수 있다.

0개의 댓글