Position

ReadMe.txt
ReversingKr KeygenMe Find the Name when the Serial is 76876-77776 This problem has several answers. Password is ***p
Python
프로그램 실행에 오류가 난다.
IDA로 정적 분석을 해보는것도 나쁘지 않을지도?
한번 시도해 봅시다
이런 함수를 찾았다. v2에 True 값이 들어오도록하면 답이 된다.
그럼 v2에 값이 들어가게 하는 sub_401750을 보면 되겠다
int __stdcall sub_401740(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 ) { v3 = 0; while ( (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v3) >= 0x61u && (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v50, v3) <= 0x7Au ) { 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) == 11 && (unsigned __int16)ATL::CSimpleStringT<wchar_t,1>::GetAt(&v51, 5) == 45 ) { 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; }
Python
엄청 길다
LABEL2로 가지 않고, Return 1을 만나야 한다.
if 문 16개 지나면 된다. password를 알아내야 하므로 이 부분을 분석하면 되겠다.
차근차근 봅시다
v50에 이제 a1+304에 대한 값을 가져온다.
while 문에서는 각 자리가 소문자인지 확인하는 것 같다. (0x61 : a, 0x7A : z)
먼저 v3은 길이 각각에 대한 인덱스 값이다. 어느 위치의 문자를 다루는지에 대한 아이이다.
while 문을 4번 돈 다음부터, 그니까 4자리에 대해서 검사를 마친 이후에,
LABEL7로 들어간다
v4에 대해서 무한 루프를 도는데, v1과 v4가 다르다면, v5에 v50의 v4번째 문자와 v1번째 문자가 같은지를 비교하고, 같다면 LABEL 2 로 간다.
근데 둘다 0으로 초기화 되어있는 상황이기 때문에 처음 루프에서는 갈일이 없긴 하다.
v4가 4 보다 커진 다음부터는, v1이 4보다 작아야한다. 여기서 password? 값이 4보다 작은지 검사하는 로직이 있다는 것을 의미한다.
v1도 4가 된 다음부터는 if 문 안으로 들어오게 되는데, a1의 문자열을 v51에 넣어준다. → 이게 뭔지 알아야지. 아마 눈치로 본다면 Serial number가 되면 말이 될거같다.
v51-12 ==11 이고, 6번째 문자가 45면('-'), if 문 안으로 들어간다. serial이 맞는거 같다.
6번쨰가 - 이어야 하므로, v51은 serial 인가보다.
그럼 이부분이 serial 을 생성하는 과정일 것 같다.
v6에 pass값을 가져온 다음에 연산을 해주는데, 일단은 분기 조건만 보고 싶으니까 나중에 보도록 하자
v10 과 첫 자리가 같아야 한다. 그럼 v10은 뭔가?
v52의 첫번째 자리인듯 → 계속해서 비교하는 것을 보니 생성된 serial 인가 보다.
그래서 같은 로직을 5번 하고, 다시 생성한 다음에 다시 5번 비교한다. 완전 serial을 비교하는 과정인듯
그럼 v52가 어떻게 만들어지는지를 확인하면 되겠다.
일단 v6는 pass의 첫 자리이고,
a = pass의 첫 자리 문자 v40 = a&1 + 5 v42 = a&2 + 5 v44 = a&4 + 5 v46 = a&8 + 5 v48 = a&16 + 5
Python
두번째 문자에 대해서도 똑같이 진행해준다. & 연산이 shift연산이라는걸 아는데 좀 걸렸다
serial[0] = shift(5)1 + shift(1)4
serial[1] = shift(5)8 + shift(1)8
serial[2] = shift(5)2 + shift(1)16
serial[3] = shfit(5)4 + shift(1)1
serial[4] = shift(5)16 + shfit(1)2
그럼 이제 뭔가 될거같다. 역 연산이 정확하게 떨어지는 것이 아니라,
덧셈으로 이루어져 있기 때문에 전수조사를 해보아야 할 것 같다.
def decodeBF(serial): for i in range(0x61,0x7B): for j in range(0x61,0x7B): tmpse = "" v0 = (i & 1) + 5 v1 = ((i >> 1) & 1) + 5 v2 = ((i >> 2) & 1) + 5 v3 = ((i >> 3) & 1) + 5 v4 = ((i >> 4) & 1) + 5 v10 = (j & 1) + 1 v11 = ((j >> 1) & 1) + 1 v12 = ((j >> 2) & 1) + 1 v13 = ((j >> 3) & 1) + 1 v14 = ((j >> 4) & 1) + 1 tmpse = str(v0+v12) + str(v3+v13) + str(v1+v14) + str(v2+v10)+str(v4+v11) if tmpse == serial.split('-')[0]: print("front : "+chr(i)+chr(j)) if tmpse == serial.split('-')[1]: if chr(j) == 'p': print("back : "+chr(i)+chr(j)) if __name__ == "__main__": serial = "76876-77776" decodeBF(serial)
Python
결과는 다음과 같다
front : bu front : cq front : ft front : gp back : mp
Python
답은 bump.cqmp,ftmp,gpmp 중에 하나일듯
다 넣어보자.
바이너리가 실행이 안되도 할수 있긴 하다.