Search

[CodeEngn] Advance RCE L08

Tags
reversing
Category
CodeEngn
Last Edited time
2022/01/07 12:50
Visibility
Public

1. 문제

Key 값이 5D88-53B4-52A87D27-1D0D-5B09 일때 Name은 무엇인가 힌트 : Name은 두자리인데.. 알파벳일수도 있고 숫자일수도 있고.. 정답인증은 Name의 MD5 해쉬값(대문자)
Plain Text
복사
이번엔 반대로 키젠되는 값을 주고 그에 해당하는 Name을 맞춰야한다
델파이로 만들어짐

2. 접근방법

basic 17번 문젠가 그거랑 비슷하다.
int __usercall TForm1_Button1Click@<eax>(int a1@<eax>, int a2@<ebx>) { int name_len; // eax int v4; // eax char v5; // zf int v7; // [esp-14h] [ebp-2Ch] unsigned int v8[2]; // [esp-10h] [ebp-28h] BYREF int *v9; // [esp-8h] [ebp-20h] int v10; // [esp-4h] [ebp-1Ch] void *serial; // [esp+0h] [ebp-18h] BYREF int v12; // [esp+4h] [ebp-14h] BYREF int v13; // [esp+8h] [ebp-10h] BYREF int v14; // [esp+Ch] [ebp-Ch] int v15; // [esp+10h] [ebp-8h] int v16; // [esp+14h] [ebp-4h] BYREF int savedregs; // [esp+18h] [ebp+0h] BYREF v14 = 0; v13 = 0; v12 = 0; serial = 0; v10 = a2; v9 = &savedregs; v8[1] = (unsigned int)&loc_45BC02; v8[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v8); Controls::TControl::GetText(*(Controls::TControl **)(a1 + 872)); v15 = v16; name_len = v16; if ( v16 ) name_len = *(_DWORD *)(v16 - 4); if ( name_len >= 3 ) // Name의 사이즈가 3이상이야지 들어옴. 문제에선 2바이트라했으니 패치해야함 { Controls::TControl::GetText(*(Controls::TControl **)(a1 + 872)); v15 = v14; v4 = v14; if ( v14 ) v4 = *(_DWORD *)(v14 - 4); if ( v4 <= 0x1E ) // Name size <= 0x1e { Controls::TControl::GetText(*(Controls::TControl **)(a1 + 884)); v7 = v13; // v13=serial Controls::TControl::GetText(*(Controls::TControl **)(a1 + 872)); keygen(serial, (int)&v12); // keygen 함수 System::__linkproc__ LStrCmp(v7, v12); if ( v5 ) Forms::TApplication::MessageBox(*(Forms::TApplication **)off_45E9C0[0], "Well done!", "Good Boy!!!", 0x40u); else Sleep_0(0x14Du); } else { Controls::TControl::SetText(*(Controls::TControl **)(a1 + 884), (const int)&str_Please_Enter_No[1]); } } else { Controls::TControl::SetText(*(Controls::TControl **)(a1 + 884), (const int)&str_Please_Enter_Mo[1]); } __writefsdword(0, v8[0]); v9 = (int *)&loc_45BC09; System::__linkproc__ LStrClr(&serial); System::__linkproc__ LStrClr(&v12); System::__linkproc__ LStrArrayClr(&v13, 2); return System::__linkproc__ LStrClr(&v16); }
C++
복사
결국 keygen() 함수를 분석해야한다. 첫번째 인자로 serial을 갖고 들어간다
int __fastcall keygen(void *input, int a2) { .... v31 = a2; v33 = input; System::__linkproc__ LStrAddRef(input); v21 = &savedregs; v20[1] = (unsigned int)&loc_45BAAA; v20[0] = (unsigned int)NtCurrentTeb()->NtTib.ExceptionList; __writefsdword(0, (unsigned int)v20); v2 = 0; v3 = 0; v30 = 0; v4 = (char *)v33; if ( name ) v4 = (char *)*((_DWORD *)name - 1); if ( (int)v4 > 0 ) { v5 = 1; do { v6 = 0x772 * (v2 + (unsigned __int8)name[v5 - 1]); v3 = 2280 * (v6 * v6 + v6); v2 = v3; ++v5; --v4; } while ( v4 ); } v7 = (int)v33; if ( v33 ) v7 = *((_DWORD *)v33 - 1); if ( v7 >= 1 ) { do v30 += 605316 * ((unsigned __int8)*((char *)v33 + --v7) + 12); while ( v7 ); } System::__linkproc__ LStrCat3((int)&v28, v33, &str_w09__720_______[1]); sub_45B54C(v28, &v32); v8 = 0; v9 = 0; v10 = (int)v33; if ( v33 ) v10 = *((_DWORD *)v33 - 1); if ( v10 >= 1 ) { do { v8 = 33682 * (v9 + (unsigned __int8)*((char *)v33 + v10 - 1) + v8 + 4240); v9 = v8 + v8 * (v8 - 51); --v10; } while ( v10 ); } v11 = 0; v12 = (char *)v33; if ( v33 ) v12 = (char *)*((_DWORD *)v33 - 1); if ( (int)v12 > 0 ) { v29 = 1; do { v13 = 2 * ((unsigned __int8)*((char *)v33 + v29 - 1) + v11); v14 = (unsigned __int8)*((char *)v33 + v29 - 1) + 883 * ((v13 * v13 * v13) ^ 0x10 | 0x44) + 1091; v11 = v14 * v14; ++v29; --v12; } while ( v12 ); } Sysutils::IntToHex(v3, 4); System::__linkproc__ LStrCopy(&v27); Sysutils::IntToHex(v30, 0); System::__linkproc__ LStrCopy(&v26); v19 = v26; System::__linkproc__ LStrCopy(&v25); v18 = v25; Sysutils::IntToHex(v8, 0); System::__linkproc__ LStrCopy(&v24); v17 = v24; Sysutils::IntToHex(v11, 0); System::__linkproc__ LStrCopy(&v23); System::__linkproc__ LStrCatN(v31, 9, v15, &str___13[1], v19, &str___13[1], v18, &str___13[1], v17, &str___13[1], v23); __writefsdword(0, v20[0]); v21 = (int *)&loc_45BAB1; System::__linkproc__ LStrArrayClr(&v22, 10); return System::__linkproc__ LStrArrayClr(&v32, 2); }
C++
복사
basic 17번 문제와 동일한 로직이다. 다른점은 Name의 값이 2바이트라는 점이다.
5D88-53B4-52A87D27-1D0D-5B09 의 키가 생성되는데, 맨 처음 4바이트가 위 코드의 형광펜쳐진 부분에서 생성된다. 따라서 우리는 저번 17번 코드에서 포팅한 코드에서 2바이트 형식으로 조금만 손봐주면 된다. 로직 설명은 아예 동일해서 아래 글을 참고하면 된다

3. 풀이

import hashlib v6 = 0 v2 = 0 flag = 0 for i in range(0x21, 0x7F): for j in range(0x21, 0x7F): # i = ord("A") # j = ord("B") v6 = (v2 + i) * 0x772 tmp = (v6 * v6) & 0xFFFFFFFF tmp = ((tmp + v6) * 0x474) & 0xFFFFFFFF tmp = (tmp + tmp) & 0xFFFFFFFF v6 = (tmp + j) * 0x772 tmp = (v6 * v6) & 0xFFFFFFFF tmp = ((tmp + v6) * 0x474) & 0xFFFFFFFF tmp = (tmp + tmp) & 0xFFFFFFFF if tmp >> (8 * 2) == 0x5D88: flag = chr(i) + chr(j) print("Name is " + flag) enc = hashlib.md5() enc.update(flag.encode("utf-8")) encText = enc.hexdigest() print("md5 hash is " + str(encText).upper()) flag = 1 break
Python
복사
> E:\JungJaeho\STUDY\Self\hacking\Wargame\CodeEngine\advance rev\08>C:/Users/wogh8732/AppData/Local/Programs/Python/Python37/python.exe "e:/JungJaeho/STUDY/Self/hacking/Wargame/CodeEngine/advance rev/08/ex3.py" Name is C6 md5 hash is 7E8B9F5CAB4A8FE24FAD9FE4B7452702
Bash
복사
참고로 원본 바이너리로는 위와같이 출력 안됌. 코드 패치해서 Name 사이즈 비교를 2로 수정해야함

4. 몰랐던 개념