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