문제에는 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가 나온다... 내 생각엔... 절대 이렇게 푸는게 아닐거 같은데.............. 문제 자체에 허점이 있는 것 같다..