콘텐츠로 건너뛰기

Position

README.txt

ReversingKr KeygenMe

Find the Name when the Serial is 76876-77776
This problem has several answers.

Password is ***p

Exeinfo PE

Not Packed

Analysis

시험삼아 Name에 abcd, Serial은 README.txt에서 가져와
디버깅해서 한번 확인해보자.

void __thiscall sub_2B1CD0(char *this)
{
  int v2; // eax
  CWnd *v3; // ecx

  v2 = sub_2B1740((int)this);
  v3 = (CWnd *)(this + 188);
  if ( v2 )
    CWnd::SetWindowTextW(v3, L"Correct!");
  else
    CWnd::SetWindowTextW(v3, L"Wrong");
}

“Wrong” 문자열을 역참조해서 확인해보면,
sub_2B1740에서 검증이 진행된다는 것을 알 수 있다.

int __stdcall sub_2B1740(int a1)
{
  int v1; // edi
  int v3; // esi
  int v4; // esi
  __int16 v5; // bx
  char v6; // al
  char v7; // al
  unsigned __int8 v8; // bl
  wchar_t *Buffer; // eax
  __int16 v10; // di
  wchar_t *v11; // eax
  __int16 v12; // di
  wchar_t *v13; // eax
  __int16 v14; // di
  wchar_t *v15; // eax
  __int16 v16; // di
  wchar_t *v17; // eax
  __int16 v18; // di
  char v19; // al
  char v20; // al
  unsigned __int8 v21; // 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 v32; // [esp+10h] [ebp-28h]
  unsigned __int8 v33; // [esp+10h] [ebp-28h]
  unsigned __int8 v34; // [esp+11h] [ebp-27h]
  unsigned __int8 v35; // [esp+11h] [ebp-27h]
  unsigned __int8 v36; // [esp+13h] [ebp-25h]
  unsigned __int8 v37; // [esp+13h] [ebp-25h]
  unsigned __int8 v38; // [esp+14h] [ebp-24h]
  unsigned __int8 v39; // [esp+14h] [ebp-24h]
  unsigned __int8 v40; // [esp+18h] [ebp-20h]
  unsigned __int8 v41; // [esp+18h] [ebp-20h]
  unsigned __int8 v42; // [esp+19h] [ebp-1Fh]
  unsigned __int8 v43; // [esp+19h] [ebp-1Fh]
  unsigned __int8 v44; // [esp+1Ah] [ebp-1Eh]
  unsigned __int8 v45; // [esp+1Ah] [ebp-1Eh]
  unsigned __int8 v46; // [esp+1Bh] [ebp-1Dh]
  unsigned __int8 v47; // [esp+1Bh] [ebp-1Dh]
  unsigned __int8 v48; // [esp+1Ch] [ebp-1Ch]
  unsigned __int8 v49; // [esp+1Ch] [ebp-1Ch]
  int v50; // [esp+20h] [ebp-18h] BYREF
  int v51; // [esp+24h] [ebp-14h] BYREF
  char v52[4]; // [esp+28h] [ebp-10h] BYREF
  int v53; // [esp+34h] [ebp-4h]

  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v50);
  v1 = 0;
  v53 = 0;
  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v51);
  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(v52);
  LOBYTE(v53) = 2;
  CWnd::GetWindowTextW(a1 + 304, &v50);
  if ( *(_DWORD *)(v50 - 12) == 4 )             // name length
  {
    v3 = 0;
    while ( (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v3) >= 'a'
         && (unsigned int)(unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v3) <= 'z' )// range: a~z
    {
      if ( ++v3 >= 4 )
      {
LABEL_7:
        v4 = 0;
        while ( 1 )
        {
          if ( v1 != v4 )
          {
            v5 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v4);
            if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v1) == v5 )
              goto LABEL_2;
          }
          if ( ++v4 >= 4 )
          {
            if ( ++v1 < 4 )
              goto LABEL_7;
            CWnd::GetWindowTextW(a1 + 420, &v51);
            if ( *(_DWORD *)(v51 - 12) == 0xB && (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 5) == '-' )
            {
              v6 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, 0);
              v40 = (v6 & 1) + 5;
              v48 = ((v6 & 0x10) != 0) + 5;
              v42 = ((v6 & 2) != 0) + 5;
              v44 = ((v6 & 4) != 0) + 5;
              v46 = ((v6 & 8) != 0) + 5;
              v7 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, 1);
              v32 = (v7 & 1) + 1;
              v38 = ((v7 & 0x10) != 0) + 1;
              v34 = ((v7 & 2) != 0) + 1;
              v8 = ((v7 & 4) != 0) + 1;
              v36 = ((v7 & 8) != 0) + 1;
              Buffer = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
              itow_s(v40 + v8, Buffer, 0xAu, 10);
              v10 = ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0);
              if ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 0) == v10 )
              {
                ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                v11 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                itow_s(v46 + v36, v11, 0xAu, 10);
                v12 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 1);
                if ( v12 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                {
                  ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                  v13 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                  itow_s(v42 + v38, v13, 0xAu, 10);
                  v14 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 2);
                  if ( v14 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                  {
                    ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                    v15 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                    itow_s(v44 + v32, v15, 0xAu, 10);
                    v16 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 3);
                    if ( v16 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                    {
                      ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                      v17 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                      itow_s(v48 + v34, v17, 0xAu, 10);
                      v18 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 4);
                      if ( v18 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                      {
                        ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                        v19 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, 2);
                        v41 = (v19 & 1) + 5;
                        v49 = ((v19 & 0x10) != 0) + 5;
                        v43 = ((v19 & 2) != 0) + 5;
                        v45 = ((v19 & 4) != 0) + 5;
                        v47 = ((v19 & 8) != 0) + 5;
                        v20 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, 3);
                        v33 = (v20 & 1) + 1;
                        v39 = ((v20 & 0x10) != 0) + 1;
                        v35 = ((v20 & 2) != 0) + 1;
                        v21 = ((v20 & 4) != 0) + 1;
                        v37 = ((v20 & 8) != 0) + 1;
                        v22 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                        itow_s(v41 + v21, v22, 0xAu, 10);
                        v23 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 6);
                        if ( v23 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                        {
                          ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                          v24 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                          itow_s(v47 + v37, v24, 0xAu, 10);
                          v25 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 7);
                          if ( v25 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                          {
                            ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                            v26 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                            itow_s(v43 + v39, v26, 0xAu, 10);
                            v27 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 8);
                            if ( v27 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                            {
                              ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                              v28 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                              itow_s(v45 + v33, v28, 0xAu, 10);
                              v29 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 9);
                              if ( v29 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                              {
                                ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                                v30 = (wchar_t *)ATL::CSimpleStringT<wchar_t,1>::GetBuffer(v52);
                                itow_s(v49 + v35, v30, 0xAu, 10);
                                v31 = ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 10);
                                if ( v31 == (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(v52, 0) )
                                {
                                  ATL::CSimpleStringT<wchar_t,1>::ReleaseBuffer(v52, -1);
                                  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(v52);
                                  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v51);
                                  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v50);
                                  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>>>(v52);
  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v51);
  ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v50);
  return 0;
}

sub_2B1740을 디컴파일해서 Pseudo Code로 나타내면 위와 같다.
하나씩 살펴보면,

name 길이가 4인지 확인하고, a~z 범위여야 된다.

serial 길이가 11이고 serial[5]가 “-” 문자인지 확인한다.

serial의 문자 하나씩과 name 문자간의 연산을 통해 서로 비교하는데,
name이 ‘abcd’이고, serial이 ‘76876-77776’일떄의 분석한 결과를 주석에 적어두었다.

solve.py

ida를 통해 디컴파일된 내용을 토대로 name들간의 연산을 구현하고,
마지막 name의 한글자가 p라는 것을 참고해서,
name 1글자씩 a~z까지 브루트포싱을 진행하면 쉽게 구할 수 있다.

serial = "76876-77776"

for i in range(ord('a'), ord('z')+1):
    for j in range(ord('a'), ord('z')+1):
        for k in range(ord('a'), ord('z')+1):
            v6 = i
            v40 = (v6 & 1) + 5
            v48 = ((v6 & 0x10) != 0) + 5
            v42 = ((v6 & 0x2) != 0) + 5
            v44 = ((v6 & 0x4) != 0) + 5
            v46 = ((v6 & 0x8) != 0) + 5

            v7 = j
            v32 = (v7 & 1) + 1
            v38 = ((v7 & 0x10) != 0) + 1
            v34 = ((v7 & 2) != 0) + 1
            v8 = ((v7 & 4) != 0) + 1
            v36 = ((v7 & 8) != 0) + 1

            if(ord(serial[0]) != ord(str(v40+v8))):
                continue

            if(ord(serial[1]) != ord(str(v46+v36))):
                continue

            if(ord(serial[2]) != ord(str(v42+v38))):
                continue

            if(ord(serial[3]) != ord(str(v44+v32))):
                continue

            if(ord(serial[4]) != ord(str(v48+v34))):
                continue

            # print(f"i: {chr(i)}, j: {chr(j)}")

            v19 = k
            v41 = (v19 & 1) + 5
            v49 = ((v19 & 0x10) != 0) + 5
            v43 = ((v19 & 2) != 0) + 5
            v45 = ((v19 & 4) != 0) + 5
            v47 = ((v19 & 8) != 0) + 5

            v20 = ord('p')
            v33 = (v20 & 1) + 1
            v39 = ((v20 & 0x10) != 0) + 1
            v35 = ((v20 & 2) != 0) + 1
            v21 = ((v20 & 4) != 0) + 1
            v37 = ((v20 & 8) != 0) + 1

            if(ord(serial[6]) != ord(str(v41+v21))):
                continue

            if(ord(serial[7]) != ord(str(v47+v37))):
                continue

            if(ord(serial[8]) != ord(str(v43+v39))):
                continue

            if(ord(serial[9]) != ord(str(v45+v33))):
                continue

            if(ord(serial[10]) != ord(str(v49+v35))):
                continue

            print(f"{chr(i)}{chr(j)}{chr(k)}{chr(v20)}")

Result

PS C:\Users\Seo Hyun-gyu\Desktop\Position> python3 solve.py
bump
cqmp
ftmp
gpmp

그러면 4개의 결과가 나오는데,
사이트를 통해 flag 인증을 해보니 “bump” 문자열이 flag였다!

태그:

답글 남기기