문제를 풀기에 앞서 mfc100u.dll을 확보해줘야 한다.
문제 설명은 다음과 같다.
ReversingKr KeygenMe
Find the Name when the Serial is 76876-77776
This problem has several answers.
Password is ***p
실행하면 name과 serial을 입력하라고 나온다.
먼저 Wrong 이라는 문자열을 검색해주자.
ida에서 shift+f12를 누르면 나오지 않을 수 있다.
이는 유니코드 문자열을 검색하지 않기 때문이다.
화면에서 우클릭하면 setup 메뉴가 나오는데 거기서 유니코드도 체크해줘야 한다.
이제 x로 어디서 쓰이는지 추적하면 된다.
void __thiscall sub_401CD0(char *this)
{
int v2; // eax
CWnd *v3; // ecx
v2 = sub_401740(this);
v3 = (CWnd *)(this + 0xBC);
if ( v2 )
CWnd::SetWindowTextW(v3, L"Correct!");
else
CWnd::SetWindowTextW(v3, L"Wrong");
}
검증 함수를 거쳐서 결과를 출력해주는 것 같다.
검증 함수는 다음과 같다.
(대충 리네이밍을 수행했음)
int __stdcall sub_CE1740(int a1)
{
int idx2; // edi
int idx0; // esi
int idx1; // esi
__int16 wchar; // bx
char input_0; // al
char input_1; // al
unsigned __int8 _1_4; // bl
wchar_t *serial_array_4_addr1; // eax
__int16 serial_array_4_1; // di
wchar_t *serial_array_4_addr2; // eax
__int16 serial_array_2; // di
wchar_t *Buffer; // eax
__int16 v14; // di
wchar_t *v15; // eax
__int16 v16; // di
wchar_t *v17; // eax
__int16 v18; // di
char input_2; // al
char input_3; // al
unsigned __int8 _3_4; // bl
wchar_t *v22; // eax
__int16 v23; // di
wchar_t *v24; // eax
__int16 v25; // di
wchar_t *v26; // eax
__int16 v27; // di
wchar_t *v28; // eax
__int16 v29; // di
wchar_t *v30; // eax
__int16 v31; // si
unsigned __int8 _1_1; // [esp+10h] [ebp-28h]
unsigned __int8 _3_1; // [esp+10h] [ebp-28h]
unsigned __int8 _1_2; // [esp+11h] [ebp-27h]
unsigned __int8 _3_2; // [esp+11h] [ebp-27h]
unsigned __int8 _1_8; // [esp+13h] [ebp-25h]
unsigned __int8 _3_8; // [esp+13h] [ebp-25h]
unsigned __int8 _1_10; // [esp+14h] [ebp-24h]
unsigned __int8 _3_10; // [esp+14h] [ebp-24h]
unsigned __int8 _0_1; // [esp+18h] [ebp-20h]
unsigned __int8 _2_1; // [esp+18h] [ebp-20h]
unsigned __int8 _0_2; // [esp+19h] [ebp-1Fh]
unsigned __int8 _2_2; // [esp+19h] [ebp-1Fh]
unsigned __int8 _0_4; // [esp+1Ah] [ebp-1Eh]
unsigned __int8 _2_4; // [esp+1Ah] [ebp-1Eh]
unsigned __int8 _0_8; // [esp+1Bh] [ebp-1Dh]
unsigned __int8 _2_8; // [esp+1Bh] [ebp-1Dh]
unsigned __int8 _0_10; // [esp+1Ch] [ebp-1Ch]
unsigned __int8 _2_10; // [esp+1Ch] [ebp-1Ch]
wchar_t serial_array[12]; // [esp+20h] [ebp-18h] BYREF
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(serial_array);
idx2 = 0;
*(_DWORD *)&serial_array[10] = 0;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[2]);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[4]);
LOBYTE(serial_array[10]) = 2;
CWnd::GetWindowTextW(a1 + 304, serial_array);
if ( *(_DWORD *)(*(_DWORD *)serial_array - 12) == 4 )
{
idx0 = 0;
while ( (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx0) >= 'a'
&& (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx0) <= 'z' )
{
if ( ++idx0 >= 4 )
{
LABEL_7:
idx1 = 0;
while ( 1 )
{
if ( idx2 != idx1 )
{
wchar = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx1);
if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx2) == wchar )
goto LABEL_2;
}
if ( ++idx1 >= 4 )
{
if ( ++idx2 < 4 )
goto LABEL_7;
CWnd::GetWindowTextW(a1 + 0x1A4, &serial_array[2]);
if ( *(_DWORD *)(*(_DWORD *)&serial_array[2] - 0xC) == 0xB
&& (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 5) == '-' )
{
input_0 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 0);
_0_1 = (input_0 & 1) + 5;
_0_10 = ((input_0 & 0x10) != 0) + 5;
_0_2 = ((input_0 & 2) != 0) + 5;
_0_4 = ((input_0 & 4) != 0) + 5;
_0_8 = ((input_0 & 8) != 0) + 5;
input_1 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 1);
_1_1 = (input_1 & 1) + 1;
_1_10 = ((input_1 & 0x10) != 0) + 1;
_1_2 = ((input_1 & 2) != 0) + 1;
_1_4 = ((input_1 & 4) != 0) + 1;
_1_8 = ((input_1 & 8) != 0) + 1;
serial_array_4_addr1 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_1 + _1_4, serial_array_4_addr1, 0xAu, 10);
serial_array_4_1 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0);
if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 0) == serial_array_4_1 )// 7
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
serial_array_4_addr2 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_8 + _1_8, serial_array_4_addr2, 0xAu, 10);
serial_array_2 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 1);
if ( serial_array_2 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 6
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
Buffer = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_2 + _1_10, Buffer, 0xAu, 10);
v14 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 2);
if ( v14 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 8
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v15 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_4 + _1_1, v15, 0xAu, 10);
v16 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 3);
if ( v16 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 7
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v17 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_10 + _1_2, v17, 0xAu, 10);
v18 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 4);
if ( v18 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 6
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
input_2 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 2);
_2_1 = (input_2 & 1) + 5;
_2_10 = ((input_2 & 0x10) != 0) + 5;
_2_2 = ((input_2 & 2) != 0) + 5;
_2_4 = ((input_2 & 4) != 0) + 5;
_2_8 = ((input_2 & 8) != 0) + 5;
input_3 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 3);
_3_1 = (input_3 & 1) + 1;
_3_10 = ((input_3 & 0x10) != 0) + 1;
_3_2 = ((input_3 & 2) != 0) + 1;
_3_4 = ((input_3 & 4) != 0) + 1;
_3_8 = ((input_3 & 8) != 0) + 1;
v22 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_2_1 + _3_4, v22, 0xAu, 10);
v23 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 6);
if ( v23 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v24 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_2_8 + _3_8, v24, 0xAu, 10);
v25 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 7);
if ( v25 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v26 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_2_2 + _3_10, v26, 0xAu, 10);
v27 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 8);
if ( v27 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v28 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_2_4 + _3_1, v28, 0xAu, 10);
v29 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 9);
if ( v29 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v30 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_2_10 + _3_2, v30, 0xAu, 10);
v31 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 10);
if ( v31 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[4]);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[2]);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(serial_array);
return 1;
}
}
}
}
}
}
}
}
}
}
}
goto LABEL_2;
}
}
}
}
}
LABEL_2:
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[4]);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&serial_array[2]);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(serial_array);
return 0;
}
return이 0과 1로 나뉜다.
1이 되어야 Correct가 출력되기 때문에 if 문을 중점적으로 분석해야 한다.
입력 값은 알파벳 소문자이다.
while ( (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx0) >= 'a'
&& (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, idx0) <= 'z' )
입력한 input 값은 비트 마스크를 통해 분석된다.
input_0 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 0);
_0_1 = (input_0 & 1) + 5;
_0_10 = ((input_0 & 0x10) != 0) + 5;
_0_2 = ((input_0 & 2) != 0) + 5;
_0_4 = ((input_0 & 4) != 0) + 5;
_0_8 = ((input_0 & 8) != 0) + 5;
input_1 = ATL::CSimpleStringT<wchar_t,1>::GetAt(serial_array, 1);
_1_1 = (input_1 & 1) + 1;
_1_10 = ((input_1 & 0x10) != 0) + 1;
_1_2 = ((input_1 & 2) != 0) + 1;
_1_4 = ((input_1 & 4) != 0) + 1;
_1_8 = ((input_1 & 8) != 0) + 1;
그런 뒤 if문으로 입력된 시리얼 값과 비교한다.
0번째 문자와 1번째 문자의 마스크 한 값들이 더해지는 구조다.
serial_array_4_addr1 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_1 + _1_4, serial_array_4_addr1, 0xAu, 10);
serial_array_4_1 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0);
if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 0) == serial_array_4_1 )// 7
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
serial_array_4_addr2 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_8 + _1_8, serial_array_4_addr2, 0xAu, 10);
serial_array_2 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 1);
if ( serial_array_2 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 6
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
Buffer = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_2 + _1_10, Buffer, 0xAu, 10);
v14 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 2);
if ( v14 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 8
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v15 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_4 + _1_1, v15, 0xAu, 10);
v16 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 3);
if ( v16 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 7
{
ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(&serial_array[4], -1);
v17 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(&serial_array[4]);
itow_s(_0_10 + _1_2, v17, 0xAu, 10);
v18 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[2], 4);
if ( v18 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&serial_array[4], 0) )// 6
입력된 시리얼 값은 76876-77776이다.
0,1번째 문자는 76876을 만족해야 하고
2,3번째 문자는 77776을 만족해야 한다.
아래와 같이 표를 만들어서 해결할 수 있다.
(p이므로 2,3 문자는 고정)
bit mask \ input | 0 | 1 | 2 | 3 |
0x1 | T/F | F/T | T | F |
0x2 | T | F | F | F |
0x4 | T/F | F/T | T | F |
0x8 | F | F | T | F |
0x10 | F | T | F | T |
result | 0x62 (b) | 0x75 (u) | 0x67 (m) | 0x70 (p) |
다른 답도 있다는데 못찾겠다.
'write-up(rev) > reversing.kr' 카테고리의 다른 글
[reversing.kr] ImagePrc write-up (2) | 2024.06.06 |
---|---|
[reversing.kr] Replace write-up (0) | 2024.06.01 |
[reversing.kr] Music Player write-up (0) | 2024.05.31 |
[reversing.kr] Easy ELF write-up (0) | 2023.08.30 |
[reversing.kr] Easy Unpack write-up (0) | 2023.08.30 |