728x90
1. 문제
Key 값이 BEDA-2F56-BC4F4368-8A71-870B 일때 Name은 무엇인가
힌트 : Name은 한자리인데.. 알파벳일수도 있고 숫자일수도 있고..
정답인증은 Name의 MD5 해쉬값(대문자)
이번엔 반대로 키에 해당하는 Name을 구해야한다
패킹은 따로 안돼있고 델파이로 만들어진 바이너리이다
int __usercall TForm1_Button1Click@<eax>(int a1@<eax>, int a2@<ebx>)
{
...
Controls::TControl::GetText(*(Controls::TControl **)(a1 + 872));
v15 = v16; // v16=&Name
v3 = v16;
if ( v16 ) // Name 값이 참이면
v3 = *(_DWORD *)(v16 - 4);
if ( v3 >= 3 ) // Name 사이즈가 3보다 크거나 같으면
{
Controls::TControl::GetText(*(Controls::TControl **)(a1 + 872));
v15 = v14;
v4 = v14;
if ( v14 )
v4 = *(_DWORD *)(v14 - 4);
if ( v4 <= 0x1E ) // len(Name) <= 0x1E
{
Controls::TControl::GetText(*(Controls::TControl **)(a1 + 0x374));
v7 = v13; // v13=serial
Controls::TControl::GetText(*(Controls::TControl **)(a1 + 0x368));
sub_45B850(v11, (int)&v12); // v11=Name
System::__linkproc__ LStrCmp(v7, v12);
if ( v5 )
Forms::TApplication::MessageBox(*(Forms::TApplication **)off_45E9C0[0], "Well done!", "Good Boy!!!", 0x40u);
else
Sleep_0(0x14Du);
....
}
Name에 입력한 사이즈를 검사한다. 문제에서는 한글자라고 했지만 여기서는 3바이트보다 크거나 같아야지만 된다. 저기는 1로 패치해서 디버깅하면 될듯
그리고 0x1E보다는 작아야한다. 힌트에서 한글자라고 했으니 여기는 걍 통과될 것이다.
키젠을 어디서 하는지를 찾는게 관건이다
2. 접근방법
디버깅 결과
sub_45B850(v11, (int)&v12); // v11=Name
여기서 키젠을 하는것을 확인할 수 있다. v11에는 입력한 Name이 들어가고 v12에는 생서된 키 값이 들어간다
// bad sp value at call has been detected, the output may be wrong!
int __fastcall sub_45B850(void *a1, int a2)
{
...
v34 = a2;
v36 = a1;
System::__linkproc__ LStrAddRef(a1);
v22 = &savedregs;
v21 = &loc_45BAAA;
v20 = NtCurrentTeb()->NtTib.ExceptionList;
__writefsdword(0, (unsigned int)&v20);
v2 = 0;
v3 = 0;
v33 = 0;
v4 = (char *)v36;
if ( v36 )
v4 = (char *)*((_DWORD *)v36 - 1);
if ( (int)v4 > 0 )
{
v5 = 1;
do
{
v6 = 0x772 * (v2 + (unsigned __int8)*((char *)v36 + v5 - 1));
v3 = 0x8E8 * (v6 * v6 + v6);
v2 = v3;
++v5;
--v4;
}
while ( v4 );
}
v7 = (int)v36;
if ( v36 )
v7 = *((_DWORD *)v36 - 1);
if ( v7 >= 1 )
{
do
v33 += 0x93C84 * ((unsigned __int8)*((char *)v36 + --v7) + 12);
while ( v7 );
}
System::__linkproc__ LStrCat3((int)&v31, v36, &str_w09__720_______[1]);
sub_45B54C(v31, (int)&v35);
v8 = 0;
v9 = 0;
v10 = (int)v36;
if ( v36 )
v10 = *((_DWORD *)v36 - 1);
if ( v10 >= 1 )
{
do
{
v8 = 33682 * (v9 + (unsigned __int8)*((char *)v36 + v10 - 1) + v8 + 4240);
v9 = v8 + v8 * (v8 - 51);
--v10;
}
while ( v10 );
}
v11 = 0;
v12 = (char *)v36;
if ( v36 )
v12 = (char *)*((_DWORD *)v36 - 1);
if ( (int)v12 > 0 )
{
v32 = 1;
do
{
v13 = 2 * ((unsigned __int8)*((char *)v36 + v32 - 1) + v11);
v14 = (unsigned __int8)*((char *)v36 + v32 - 1) + 883 * ((v13 * v13 * v13) ^ 0x10 | 0x44) + 1091;
v11 = v14 * v14;
++v32;
--v12;
}
while ( v12 );
}
Sysutils::IntToHex(v3, 4);
System::__linkproc__ LStrCopy((int)&v30, (int)v20);
v20 = (_EXCEPTION_REGISTRATION_RECORD *)v30;
Sysutils::IntToHex(v33, 0);
System::__linkproc__ LStrCopy((int)&v29, (int)&str___13[1]);
v19 = v29;
System::__linkproc__ LStrCopy((int)&v28, (int)&str___13[1]);
v18 = v28;
Sysutils::IntToHex(v8, 0);
System::__linkproc__ LStrCopy((int)&v27, (int)&str___13[1]);
v17 = v27;
Sysutils::IntToHex(v11, 0);
System::__linkproc__ LStrCopy((int)&v26, (int)&str___13[1]);
System::__linkproc__ LStrCatN(v34, 9, v15, v23, v22, v21, v20, v19, v18, v17, v26);
__writefsdword(0, v24);
v26 = (int)&loc_45BAB1;
System::__linkproc__ LStrArrayClr(&v25, 10);
return System::__linkproc__ LStrArrayClr(&v35, 2);
}
맨 마지막 StrCat 을 통해 생성한 키 값을 이어붙인다. 중간중간 하이픈으로 연결한다.
키 사이즈는 Name에 상관없이 고정 사이즈이다
ex) 0000-0000-00000000-0000-0000
초반 부분을 보면
v3=0
v5=0
if ( (int)v4 > 0 )
{
v5 = 1;
do
{
v6 = 0x772 * (v3 + (unsigned __int8)*((char *)v36 + v5 - 1));
v3 = 0x474 * (v6 * v6 + v6);
v3 = v3+v3;
++v5;
--v4;
}
while ( v4 );
}
다음과 같이 계산되는데 Name의 한바이트를 가지고 연산을 진행한다. 연산결과는 4바이트 이상의 값이 나오지만 4바이트까지만 저장된다. 생성되는 키 값을 확인해보면 위 연산 결과의 상위 2바이트 인것을 알 수 있다
따라서 위 로직을 파이썬 코드로 포팅하여 BEDA-2F56-BC4F4368-8A71-870B 키 값중 첫 4바이트가 나오는 것을 Name으로 하면 된다
3. 풀이
import hashlib
v6 = 0
v2 = 0
for i in range(0x21, 0x7F):
v6 = (v2 + i) * 0x772
tmp = (v6 * v6) & 0xFFFFFFFF
tmp = ((tmp + v6) * 0x474) & 0xFFFFFFFF
tmp = (tmp + tmp) & 0xFFFFFFFF
if (tmp >> (8 * 2)) == 0xBEDA:
print("Name is " + chr(i))
enc = hashlib.md5()
enc.update(chr(i).encode("utf-8"))
encText = enc.hexdigest()
print("md5 hash is " + str(encText))
break
============================================================
Name is F
md5 hash is 800618943025315f869e4e1f09471012
4. 몰랐던 개념
728x90
'워게임 > CodeEngn' 카테고리의 다른 글
[CodeEngine] Basic RCE L19 (0) | 2021.01.13 |
---|---|
[CodeEngine] Basic RCE L18 (0) | 2021.01.12 |
[CodeEngine] Basic RCE L16 (0) | 2021.01.04 |
[CodeEngine] Basic RCE L14 (0) | 2021.01.02 |
[CodeEngine] Basic RCE L15 (0) | 2021.01.02 |
Uploaded by Notion2Tistory v1.1.0