늘모자란, 개발 :: [wargame.kr] Challenge 29 - DLL with notepad

늘모자란, 개발

난 리버싱은 하나도 모른다. 아니 띄엄띄엄... 겉핥기도 아니고 그냥 정말 맛만 본 느낌인데, 문제를 보니까 참 아득하다.

문제에는 notepad.exe 와 blueh4g13.dll 이 있었는데 우선 notepad 파일부터 비교해보기로 했다. 이름은 notepad 고 변조된 프로그램일수도 있으니까.. 근데 이건 그냥 정말 notepad 인것 같고, dll만 보면될 것 같았다.

나는 ida hex-ray decompiler를 사용했다.

int __cdecl start(LPVOID lpParameter)
{
  wchar_t *v1; // eax@2
  WCHAR Filename; // [sp+4h] [bp-204h]@1

  if ( GetModuleFileNameW(0, &Filename, 0x200u) )
  {
    v1 = wcsrchr(&Filename, 0x5Cu);
    if ( v1 )
    {
      if ( !wcsicmp(v1 + 1, L"notepad.exe") )
      {
        dword_100033A8 = (int)CreateThread(0, 0, (LPTHREAD_START_ROUTINE)StartAddress, lpParameter, 0, 0);
        CloseHandle((HANDLE)dword_100033A8);
      }
    }
  }
  return 1;
}


start는 이렇다. 좀 보니 notepad.exe가 실행되어야 됨을 알 수 있다.
그리고 다음소스를 보면

void __stdcall __noreturn StartAddress(LPVOID lpThreadParameter)
{
  HWND v1; // esi@1
  HWND v2; // ebx@1
  DWORD v3; // edi@1
  DWORD dwProcessId; // [sp+14h] [bp-28h]@1
  CHAR String; // [sp+18h] [bp-24h]@3

  sub_100010C0();
  Sleep(0x2BCu);
  v1 = FindWindowW(0, L"blueh4g.txt - \uba54\ubaa8\uc7a5");
  v2 = FindWindowExW(v1, 0, L"edit", 0);
  v3 = GetCurrentProcessId();
  GetWindowThreadProcessId(v1, &dwProcessId);
  if ( v3 != dwProcessId )
    FreeLibraryAndExitThread((HMODULE)lpThreadParameter, 0);
  do
  {
    Sleep(0x32u);
    GetWindowTextA(v2, &String, 32);
  }
  while ( strcmp(&String, (const char *)&dword_10003388) );
  SetWindowTextA(v2, &::String);
  FreeLibraryAndExitThread((HMODULE)lpThreadParameter, 0);
}


blueh4g.txt - 메모장 이름을 찾고 있다. 저건 blueh4g.txt에 정답을 적어야된다는거 같다.
생각하길, blueh4g.txt 를 열어놓고 거따가 답을 적으면 SetWindowTextA(v2, &::String); 에 의해 WindowTexA로 - 여기선 아마 메모장 윈도우 - 답이 기재되는 구조인거 같다.

dword_10003388 이 정답일게 뻔하니까, 이 친구를 따라가보자



특정 로직에서 처리하고 있다.

unsigned int sub_100010C0()
{
  char *v0; // eax@1
  unsigned int v1; // esi@1
  char v2; // cl@2
  int v3; // ebx@4
  int v4; // edi@4
  int v5; // ecx@5
  unsigned int v6; // ecx@5
  unsigned int v7; // esi@8
  unsigned int result; // eax@8
  int v9; // ebx@9
  int v10; // edi@9
  int v11; // ecx@10
  unsigned int v12; // ecx@10
  __time64_t Time; // [sp+10h] [bp-90h]@1
  struct tm Tm; // [sp+18h] [bp-88h]@1
  char v15[32]; // [sp+3Ch] [bp-64h]@1
  char v16[64]; // [sp+5Ch] [bp-44h]@8

  Time = time64(0);
  localtime64_s(&Tm, &Time);
  dword_10003388 = 0;
  dword_1000338C = 0;
  dword_10003390 = 0;
  dword_10003394 = 0;
  dword_10003398 = 0;
  dword_1000339C = 0;
  dword_100033A0 = 0;
  dword_100033A4 = 0;
  memset((void *)&String, 0, 0x40u);
  sub_10001320("oh! handsome guy!");
  v0 = v15;
  v1 = 0;
  do
    v2 = *v0++;
  while ( v2 );
  if ( v0 != &v15[1] )
  {
    v3 = Tm.tm_mon;
    v4 = Tm.tm_mday * Tm.tm_mon;
    do
    {
      v5 = v4 + v15[v1];
      v6 = 126
         * (((signed int)(((unsigned __int64)(2113396605i64 * v5) >> 32) - v5) >> 6)
          + ((unsigned int)(((unsigned __int64)(2113396605i64 * v5) >> 32) - v5) >> 31))
         + v5;
      if ( (signed int)v6 < 33 )
        v6 += v3 + 33;
      *((_BYTE *)&dword_10003388 + v1++) = v6;
      v4 += v3;
    }
    while ( v1 < strlen(v15) );
  }
  sub_10001340("Air fares to NY don't come cheap.");
  v7 = 0;
  result = strlen(v16);
  if ( result )
  {
    v9 = Tm.tm_mday;
    v10 = Tm.tm_mday * Tm.tm_mon;
    do
    {
      v11 = v10 + v16[v7];
      v12 = 126
          * (((signed int)(((unsigned __int64)(2113396605i64 * v11) >> 32) - v11) >> 6)
           + ((unsigned int)(((unsigned __int64)(2113396605i64 * v11) >> 32) - v11) >> 31))
          + v11;
      if ( (signed int)v12 < 33 )
        v12 += v9 + 33;
      *((_BYTE *)&String + v7++) = v12;
      v10 += v9;
      result = strlen(v16);
    }
    while ( v7 < result );
  }
  return result;
}


대강 읽어보니 시간 관련해서 리턴이 될 것 같다.
근데 이걸 직접 돌려볼 순 없고 디버거를 붙여서 다시 들여다보자라고.. .썼는데 ollydbg를 내가 사용하는 법을 잘 몰라서 한참 헤맸다
나중엔 dll이 제대로 메모장에 붙어있나를 의심하는 수준에까지 처하게 되었는데

그래서 프로세스 익스플로러를 실행해 dll을 확인해보니 잘 붙어있다 (당연)
여기서 아이디어가 스친게, 어차피 dll은 계산된값을 메모리에 들고 있을거고, setTextA 해주는 스트링도 이미 만들어져 있을것이라는 생각이 들어서 memory에 올라간 텍스트를 하나씩 훑기 시작했다. 그 결과...



key를 발견할 수 있었다. 홈페이지에 넣으면 auth key가 나온다... 내 생각엔... 절대 이렇게 푸는게 아닐거 같은데.............. 문제 자체에 허점이 있는 것 같다..
2016/06/22 03:27 2016/06/22 03:27