블로그 이전했습니다. https://jeongzero.oopy.io/
[CodeEngn] Advance RCE L08
본문 바로가기
워게임/CodeEngn

[CodeEngn] Advance RCE L08

728x90

1. 문제


Key 값이 5D88-53B4-52A87D27-1D0D-5B09 일때 Name은 무엇인가
힌트 : Name은 두자리인데.. 알파벳일수도 있고 숫자일수도 있고..
정답인증은 Name의 MD5 해쉬값(대문자)

이번엔 반대로 키젠되는 값을 주고 그에 해당하는 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);
}

결국 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);
}

basic 17번 문제와 동일한 로직이다. 다른점은 Name의 값이 2바이트라는 점이다.

5D88-53B4-52A87D27-1D0D-5B09 의 키가 생성되는데, 맨 처음 4바이트가 위 코드의 형광펜쳐진 부분에서 생성된다. 따라서 우리는 저번 17번 코드에서 포팅한 코드에서 2바이트 형식으로 조금만 손봐주면 된다. 로직 설명은 아예 동일해서 아래 글을 참고하면 된다

[CodeEngine] Basic RCE L17
1. 문제 Key 값이 BEDA-2F56-BC4F4368-8A71-870B 일때 Name은 무엇인가 힌트 : Name은 한자리인데.. 알파벳일수도 있고 숫자일수도 있고.. 정답인증은 Name의 MD5 해쉬값(대문자) 이번엔 반대로 키에 해당하는 Nam..
https://wogh8732.tistory.com/361?category=712222

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
> 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

참고로 원본 바이너리로는 위와같이 출력 안됌. 코드 패치해서 Name 사이즈 비교를 2로 수정해야함

4. 몰랐던 개념


728x90

'워게임 > CodeEngn' 카테고리의 다른 글

[CodeEngn] Advance RCE L10  (0) 2021.02.05
[CodeEngn] Advance RCE L09  (0) 2021.02.04
[CodeEngn] Advance RCE L07  (0) 2021.02.02
[CodeEngn] Advance RCE L06  (0) 2021.01.30
[CodeEngn] Advance RCE L05  (0) 2021.01.29