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; // [email protected]
int v2; // [email protected]
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; // [email protected]
signed int i; // [email protected]
char v4; // [email protected]
__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
41b2928d4ad584f8b975d051f6e53f e6c3231d786db8be1faaa96c21fde4 cbc7 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
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
ResponderEliminarGreat Article Journal Paper Writing Services projects for cse JavaScript Training in Chennai JavaScript Training in Chennai Project Centers in Chennai
EliminarTo 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