jueves, 26 de diciembre de 2013

Writeup prueba 4 (rompeme.exe) - h4ckc0nt3st - GSICKMINDS 2013




Usamos el IDA Pro para el análisis de RompeMe.exe, primero para encontrar la rutina de checkeo de licencia,

wsprintfA(String1, "%08X.lic", v4);
result = GetFileAttributesA(String1);
if ( result != -1 )
{
result = (DWORD)CreateFileA(String1, 0x80000000, 1u, 0, 3u, 0x20u, 0);
if ( result != -1 )
{
v2 = (void *)result;
v3 = check_license((HANDLE)result);

El nombre de archivo depende de parametros de hardware como CPUID, MAC de la tarjeta, y número de serie de disco. Para la máquina de prueba se encontró usando SysInternals ProcMon y el API Monitor:


En la máquina de prueba la licencia era AAF2FC0D.lic .
El contenido de la licencia se comprueba con la rutina:

int __stdcall check_license(HANDLE hFile)
{
HLOCAL v1; // ST20_4@1
int v2; // ST1C_4@1
DWORD NumberOfBytesRead; // [sp+4h] [bp-Ch]@1
DWORD FileSystemFlags; // [sp+8h] [bp-8h]@1
DWORD VolumeSerialNumber; // [sp+Ch] [bp-4h]@1

GetVolumeInformationA(0, 0, 0, &VolumeSerialNumber, 0, &FileSystemFlags, 0, 0);
ReadFile(hFile, &license_file_content, 0x100u, &NumberOfBytesRead, 0);
v1 = decrypt_license((char *)&license_file_content, (int)&word_404149);
wsprintfA(String1, "%08X", VolumeSerialNumber);
v2 = (*(_DWORD *)&String1[4] ^ *((_DWORD *)v1 + 1)) + (*(_DWORD *)String1 ^ *(_DWORD *)v1) == 0;
LocalFree(v1);
return v2;
}

Donde la función de descifrado de la licencia es

HLOCAL __stdcall decrypt_license(char *content, int mac)
{
HLOCAL result; // eax@1
signed int i; // ecx@2
char v4; // bl@4
__int16 mac1; // [sp+4h] [bp-Ch]@1
__int16 mac0; // [sp+6h] [bp-Ah]@1
char v7; // [sp+Dh] [bp-3h]@1
__int16 mac2; // [sp+Eh] [bp-2h]@1

mac0 = *(_WORD *)mac;
mac1 = *(_WORD *)(mac + 2);
mac2 = *(_WORD *)(mac + 4);
v7 = *content;
result = LocalAlloc(0x40u, (unsigned __int8)*content + 1);
if ( result )
{
for ( i = 1; (char)i <= v7; ++i )
{
v4 = HIBYTE(mac2) ^ content[i];
*((char *)result + i - 1) = v4;
mac2 = mac1 + mac0 * (mac2 + (unsigned __int8)v4);
}
}
return result;
}

El fichero de licencia contiene cifrado el número de serie de disco, la clave es la dirección MAC. Para probar que esto es asi hemos escrito un generador de números de serie:

$ cat lic.py
#!/usr/bin/python

from struct import unpack

mac = '00-0C-29-BE-4B-F7' # get via ipconfig /all
vol = '501B-3C9D' # get via dir

m0, m1, m2 = unpack('3H', mac.replace('-','').decode('hex'))
content = vol.replace('-', '')

result = ''
for c in content:
#print hex(m2)
c = ord(c)
tmp = (m2/256) ^ c
tmp = tmp % 256
result += chr(tmp)
m2 = m1 + m0 * (m2 + c) # tmp
m2 %= 65536

print result.encode('hex')
open('AAF2FC0D.lic','w').write(chr(len(result)) + result)

$ ./lic.py ; hexdump -C AAF2FC0D.lic
c28edbb4f14df712

En nuestro caso la licencia válida es –

$ hexdump -C AAF2FC0D.lic
00000000 08 c2 8e db b4 f1 4d f7 12 |......M..|
00000009

En el caso de la validación web, los pares de usuario/comprobación de licencia puede ser desactivado por completo, porque no se usa para validaciones futuras, así que deshabilitando la comprobación podríamos generar una clave. Pero podemos generar licencias sin ningún parcheado del binario

Para la validación de claves de usuario, RompeMe.exe crea un proceso desde el ejecutable almacenado en la sección de recursos, pide al nuevo proceso que calcule la validación de la clave de usuario, calcula la validación del nombre de usuario, los compara y si los dos coinciden, prueba superada.

Creación de este nuevo proceso:

v4 = GetTickCount();
wsprintfA(ApplicationName, "%08X", v4);
result = CreateFileA(ApplicationName, 0x40000000u, 2u, 0, 2u, 0x20u, 0);
hFile = result;
if ( result != (void *)-1 )
{
WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0);
CloseHandle(hFile);
StartupInfo.cb = 68;
GetStartupInfoA(&StartupInfo);
wsprintfA(&CommandLine, "%08X", hw_parameters);
CreateProcessA(ApplicationName, &CommandLine, 0, 0, 0, 0, 0, 0, &StartupInfo, &ProcessInformation);
WaitForSingleObject(ProcessInformation.hProcess, 0xFFFFFFFF);
if ( results_received == 1 )
check_results(results);
else
nop();
result = (void *)DeleteFileA(ApplicationName);

El binario de este proceso puede ser obtenido simplemente arrancando el proceso principal en el debugger y copiando el fichero temporal del directorio de trabajo

$ ls -la 00739347
-rwxr-xr-x 1 user user 10240 Oct 24 22:17 00739347

$ sha256sum 00739347
41b2928d4ad584f8b975d051f6e53fe6c3231d786db8be1faaa96c21fde4cbc7 00739347

Después de arrancar, el binario del proceso auxiliar pide al proceso principal parametros:

LRESULT __stdcall StartAddress(LPARAM lParam)
{
return SendMessageA(dword_40400C, 1034u, 0, lParam);
}

El proceso principal responde con un handler del control de dialogo para la clave

case 1034:
PostMessageA(a4, 1035u, wParam, hwnd);
break;

El proceso auxiliar calcula el código de validación y lo devuelve al proceso principal

if ( a2 == 1035 )
{
hWnd = a3;
dword_404014 = a4;
if ( (char *)a4 + (_DWORD)a3 )
solve_quadratic_equation(lpParameter, dword_40400C);


SendMessageA(::hWnd, 13u, 260u, (LPARAM)sz);
SendMessageA(dword_404014, 13u, 260u, (LPARAM)&unk_40411C);
if ( !unk_40411C
|| (v4 = lstrlenA(sz), CharUpperBuffA(sz, v4), v4 < 6)
|| v4 > 6
|| (LOBYTE(v2) = is_hexstring(sz), v2) )
{
result = SendMessageA(hWnd, 16u, 0, 0);
}
else
{
v5 = *(_WORD *)sz;
v6 = 0;
w0 = (char)hex2word(&v5);
v5 = *(_WORD *)&sz[2];
v6 = 0;
w1 = (char)hex2word(&v5);
v5 = *(_WORD *)&sz[4];
v6 = 0;
w2 = (char)hex2word(&v5);
result = check(w0, w1, w2, hWnd, a2);
}
return result;

El algoritmo del código de validación:

La clave debe ser de longitud 6 (hex), cada byte es un parámetro de una ecuación cuadrática

aa * x^2 + bb*x + cc, donde aabbcc es la clave introducida por el usuario

El binario auxiliar lo calcula y manda de vuelta una de las raices de la ecuación

det = (signed int)((double)w1 * (double)w1 + (double)-4 * (double)w0 * (double)w2);
if ( det < 0 )
{
result = SendMessageA(a4, 16u, 0, 0);
}
else
{
PostMessageA(hWnd, 1036u, (signed int)((sqrt((double)det) + (double)w1 * (double)-1) / (double)w0 / (double)2), 0);
result = SendMessageA(a4, 0x10u, 0, 0);
}

El binario principal calcula el valor medio del valor ASCII de las letras del nombre de usuario, y lo compara con el valor de validación del binario auxiliar

.text:004029B4 check_results proc near ; CODE XREF: StartAddress+151#p
.text:004029B4
.text:004029B4 lParam = dword ptr -104h
.text:004029B4 arg_0 = dword ptr 8
.text:004029B4
.text:004029B4 push ebp
.text:004029B5 mov ebp, esp
.text:004029B7 add esp, 0FFFFFEFCh
.text:004029BD lea eax, [ebp+lParam]
.text:004029C3 push eax ; lParam
.text:004029C4 push 104h ; wParam
.text:004029C9 push 0Dh ; Msg
.text:004029CB push username ; hWnd
.text:004029D1 call SendMessageA
.text:004029D6 lea edi, [ebp+lParam]
.text:004029DC xor eax, eax
.text:004029DE mov al, [edi]
.text:004029E0 or al, al
.text:004029E2 jz short loc_402A0B
.text:004029E4 xor edx, edx
.text:004029E6
.text:004029E6 loc_4029E6: ; CODE XREF: check_results+39#j
.text:004029E6 add edx, eax
.text:004029E8 inc edi
.text:004029E9 mov al, [edi]
.text:004029EB cmp al, 0
.text:004029ED jnz short loc_4029E6
.text:004029EF lea esi, [ebp+lParam]
.text:004029F5 sub edi, esi
.text:004029F7 mov eax, edx
.text:004029F9 xor edx, edx
.text:004029FB idiv edi
.text:004029FD xor eax, [ebp+arg_0]
.text:00402A00 or eax, eax
.text:00402A02 jnz short loc_402A0B
.text:00402A04 call winner

Así que la generación de claves es trivial, usaremos la ecuación cuadrática

(x-N)*(x-1)=0
x^2 - (N+1)*x + N = 0

donde N = sum(name)/len(name), entonces la clave será la concatenación de los valores

key = 01 || (255 – N) || N

Generador de claves final:

$ cat kg.py
#!/usr/bin/python

from sys import argv

name = 'pADAwan'
if len(argv) > 1:
name = argv[-1]

sum = 0
for c in name:
sum += ord(c)
avg = sum / len(name)

key = '01%02x%02x' % (255-avg, avg)

print 'Name:', name
print 'Key:', key

Clave valida para nosotros

$ ./kg.py
Name: pADAwan
Key: 01a55a




9 comentarios:

  1. Whoa! This blog looks just like my old one! It's on a completely different topic but it has pretty much the same page layout and design. Great choice of colors! aol.com mail login sign

    ResponderEliminar
  2. To use our mortgage affordability calculator, simply enter you along with your partner's income (or maybe your co-applicant's income), along with your living costs and debt payments. mortgage calculator Check out our mortgage calculator for refinancing and have a rundown on savings, penalties and benefits. canadian mortgage calculator

    ResponderEliminar
  3. Saham adalah sekuritas yang mewakili kepemilikan saham dalam suatu perusahaan. Bagi perusahaan, menerbitkan saham adalah cara mengumpulkan uang untuk tumbuh dan berinvestasi dalam bisnis mereka. Bagi investor, saham adalah cara untuk menumbuhkan uang mereka dan melampaui inflasi dari waktu ke waktu.cek juga Peluang Usaha dan Potensi Ekspor Bengkulu dan markets Ketika Anda memiliki saham di sebuah perusahaan, Anda disebut pemegang saham karena Anda ikut ambil bagian dalam keuntungan perusahaan.Perusahaan publik menjual sahamnya melalui bursa saham, seperti Nasdaq atau Bursa Efek New York. (Berikut lebih lanjut tentang dasar-dasar pasar saham.) Investor kemudian dapat membeli dan menjual saham ini di antara mereka sendiri melalui pialang saham. Bursa saham melacak penawaran dan permintaan saham masing-masing perusahaan, yang secara langsung memengaruhi harga saham.

    ResponderEliminar
  4. I am really enjoying the design and layout of your blog.Tourist visa to turkey. Complete the online application form on the Turkish eVisa website and confirm your application. Within minutes, you should receive an email asking you to confirm that you have started an application for a eVisa.

    ResponderEliminar
  5. You wrote a very interesting and informative post. Thanks for taking the time to write it. Very useful for readers interested in travel information. Do you want to apply for a Turkish e visa, we provide Turkey e Visa information. You can visit our visa to Turkey page. Read more about e visa of Turkey.

    ResponderEliminar
  6. Hii everyone, Do you know how to fill Turkey e visa application form. You can get this info on our Turkey visa website.We provide Turkey visa related information. You can check my website.

    ResponderEliminar
  7. Intriguing content section! I stumbled onto your blog and genuinely relished absorbing your blog posts. Subscribing to your feed, and I'm hopeful for consistently quick access. Egypt boosts eco-tourism plans, emphasizing sustainable practices and diverse natural attractions.

    ResponderEliminar
  8. This day couldn't get any better! I'm immersed in this incredibly informative article, all from the comfort of my home. A huge thank you for the dedicated hard work! Explore Egypt's allure with hassle-free yacht adventures! Experience simplicity as Egypt simplifies yacht tourism procedures.

    ResponderEliminar
  9. I hope you're doing well as you read this message. I wanted to take a moment to extend my profound thanks for your consistently remarkable blog. Your dedication to producing meaningful and enlightening content is genuinely motivating. latest update now the Pros And Cons Of Flixbus Service, this information looks great. Do you want to learn more about it?

    ResponderEliminar