Reverse engineering: sblocco di un software proprietario

Un piccolo esempio di reverse engineering e sblocco del software. Tecnica un po’ noob dato che non ho utilizzato alcun disassembler come IDA Pro o altri tool avanzati, ma pur sempre efficace.

Protezione software con licenza controllata da server remoto

Al fine di evitare copie non autorizzate, molti software implementano un meccanismo di protezione che richiede una specifica licenza installata sullo stesso PC dove girerà il programma. Il proprietario del software acquista la licenza d’uso e può così utilizzare il programma. Le copie del programma semplicemente non funzioneranno perchè sprovviste della relativa licenza. I meccanismi di protezione più sofisticati utilizzano un server remoto per controllare la validità della licenza ed è quindi fondamentale che questo server sia accessibile e sempre funzionante, ma non è sempre così.

Sono stato contattato da una persona che, pur avendo regolarmente acquistato la licenza, si è ritrovato con il software bloccato, proprio perchè il relativo server di licenza è stato messo offline.

In questi casi è perfettamente lecita la modifica del software per ripristinarne il funzionamento perchè la licenza d’uso è stata regolarmente acquistata ed è un diritto dell’utente continuare ad utilizzare il programma.

Il software in questione è FinalTable, programma per l’analisti statistiche delle partite a poker :

 

Provando ad avviare il programma si ottiene un errore di connessione con server remoto, la licenza non può essere verificata ed il programma rimane bloccato alla schermata inziale. Questo è quello che lamentava l’utente e mi ha quindi contattato per risolvere il problema.

Alcuni indizi

Nel manuale in pdf si specifica che la licenza viene verificata all’apertura del programma e, se valida, il bottone OK viene abilitato, permettendo l’accesso alla schermata principale. Probabilmente il codice di verifica della licenza, alla fine del processo, non fa altro che abilitare il bottone OK.

Ho notato inoltre che la finestra principale, il font caratteri e lo stesso bottone OK utilizzano lo stile di default in Windows. Probabilmente il programma è scritto in Visual Basic o che almeno utilizza le librerie native MFC. Se così fosse è possibile inviare comandi esterni agli elementi dell’interfaccia, ad esempio è possibile inviare il comando “enable” allo stesso bottone OK così come farebbe il programma stesso dopo la verifica della licenza.

Tentativi & proof of concept

Ho utilizzato il comodissimo tool WinHack (http://sandsprite.com/) per provare a giocare con la UI ed inviare alcuni comandi al bottone OK

 

 

Il tool permette di conoscere l’ID del bottone (ogni elemento grafico ha il suo ID) , in questo caso 131642.

 

 

A questo punto è possibile inviare messaggi al bottone. Noi siamo interessati al messaggio WM_ENABLE

 

 

Inviando il comando WM_ENABLE il bottone si abiliterà e potremo cliccarlo col mouse:

 

 

E potremo così accedere al programma vero e proprio bypassando completamente il controllo di licenza:

 

 

Implementazione del crack

Il più è fatto, abbiamo trovato un modo per aggirare il controllo di licenza ed entrare comunque nel programma. Adesso occorre scrivere un piccolo programma che automatizza gli step visti prima: cerca il bottone, recupera l’id, invia il comando WM_ENABLE al bottone e lo clicca (comando WM_CLICK).

Il lavoro perfetto per C++ e <windows.h>


#include <cstdlib>
#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;

HWND buttonHandle = 0;

BOOL CALLBACK GetButtonHandle(HWND handle, LPARAM)
{
   char label[100];
   int size = GetWindowTextA(handle, label, sizeof(label));

   if (strcmp(label, "OK") == 0)
   {
      buttonHandle = handle;
      cout << handle << endl;

      EnableWindow( handle, TRUE );
      SendMessage(buttonHandle, BM_CLICK, 0, 0);
      exit(0);
      return false;
   }
   return true;
}

int main()
{
   HWND windowHandle = FindWindowA(NULL, "Final Table");
 
   if (windowHandle == NULL)
   {
      cout << "Final Table non trovato!" << endl;
   }

   else
   {
      cout << "Final Table trovato!" << endl;
      SetForegroundWindow(windowHandle);
      BOOL ret = EnumChildWindows(windowHandle, GetButtonHandle, 0);
   }
}

L’utilizzo è semplice: avviare FinalTable e attendere che venga mostrata la schermata principale con il bottone disabilitato (il controllo di licenza è ovviamente fallito). A questo punto basta lanciare il crack e si verrà portati automaticamente alla sezione principale come se la licenza fosse stata correttamente verificata.