jueves, 29 de agosto de 2013

RDG Simple Crackme .NET

Aquí esta mi solución para el RDG Simple Crackme .NET, un crackme muy sencillo, ya que RDGMax nos ayuda con un botón "Sample Serial" que nos muestra el serial para su usuario y esto facilita las cosas.  Por ejemplo, la solución es trivial si la longitud del nombre de usuario es menor o igual a seis caracteres, pues basta con cambiar el binario en un editor hexadecimal, buscando la cadena en unicode "RDGMax" Y cambiándola por el valor que deseemos :P



Si la longitud es mayor, nos encontramos con cierta ofuscación, pero usando de4dot se remueve sin problemas y podemos pasar a inspeccionar el binario ya limpio en .NET Reflector.

Desde el Reflector, podríamos ir a WindowsApplication1.Form2 y usar Reflexil para parchar el valor del TextBox1.Text en la funcion InitializeComponent().  Con Reflexil ya no tenemos el limite de seis caracteres y el binario modificado funciona.

Sin embargo, ya estando aqui, y siendo tan fácil con un parche, decidimos mas bien escribir un generador de claves.  Para estudiar la rutina de generación basta con mirar la funcion Button1_Click() en el WindowsApplication1.Form1:

private void Button1_Click(object sender, EventArgs e)
{
    clsx clsx = new clsx();
    MyProject.Forms.Form2.Show();
    clsx.K = Conversions.ToString((long) ((((((((((((((((this.xa() + this.xb()) - this.xb()) + this.xa()) + this.xa()) - this.xb()) - 100L) + 0x34L) + this.xb()) - this.xa()) + this.xb()) + this.xb()) - this.xa()) + this.xa()) - this.xa()) - this.xa()) + this.xb()));
    this.t2.Text = this.Sth(clsx.Se(this.t1.Text));
}

La clase clsx() suministra el servicio de cifrado DES, ese clsx.K es un valor intermedio usad para el calulo de la clave de cifrado, y clsx.Se() es la rutina encargada de cifrar cadenas de texto. Podemos ver que clsx.K se calcula desde xa() y xb(), estas simplemente hacen algunas operaciones matematicas y retornan un flotante cada una.  Despues de todos lso calculos clsx.K = "5167449".  Finalmente, Sth() es solo una conversion de string a hexstring.

En el set_K() de la clase clsx(), podemos ver como se genera la clave:

public void set_K(string value)
{
...
        encoding.GetBytes(value, charIndex, value.Length, bytes, charIndex);
...
        byte[] buffer2 = new SHA1CryptoServiceProvider().ComputeHash(bytes);
        charIndex = 0;
        do
        {
            this.TheKey[charIndex] = buffer2[charIndex];
            charIndex++;
        }
        while (charIndex <= 7);
...
}

Allí vemos que TheKey se calcula desde el hash SHA1 de los bytes en clsx.K, para obtener la clave de cifrado.  Después del proceso, TheKey = {0xd4, 0xed, 0x34, 0x93, 0x1c, 0x48, 0xac, 0x08}, asi que usaremos directamente este valor en el keygen.

Ahora veamos la función de cifrado:

public string Se(string strSource)
...
        CryptoStream stream2 = new CryptoStream(stream, this.objDES.CreateEncryptor(this.TheKey, this.Vector), CryptoStreamMode.Write);
stream2.Write(bytes, 0, bytes.Length);
        stream2.FlushFinalBlock();
        str = Convert.ToBase64String(stream.ToArray());
...
    return str;
}

Allí vemos como el cifrador retorna codificado en base64, y encontramos una referencia al Vector que contiene el IV.  Los valores del IV los encontraremos en el constructor de la clase:

public clsx()
{
    this.Vector = new byte[] { 0x12, 0x44, 0x16, 0xee, 0x88, 0x15, 0xdd, 0x41 };
...
}

Usando estos trozos de código como base, pero asignando directamente el valor a TheKey, logre escribir este trozo de C#, y verificar que funcionaba usando un compilador online de C#:

using System.Security.Cryptography;
using System.IO;
using System.Text;
using System;

class Program
{
    static void Main()
    {
        byte[] TheKey = { 0xd4, 0xed, 0x34, 0x93, 0x1c, 0x48, 0xac, 0x08 };
        byte[] Vector = { 0x12, 0x44, 0x16, 0xee, 0x88, 0x15, 0xdd, 0x41 };
        byte[] bytes = Encoding.UTF8.GetBytes("rmolina");
        MemoryStream stream = new MemoryStream();
        DESCryptoServiceProvider objDES = new DESCryptoServiceProvider();
        CryptoStream stream2 = new CryptoStream(stream, objDES.CreateEncryptor(TheKey, Vector), CryptoStreamMode.Write);
        stream2.Write(bytes, 0, bytes.Length);
        stream2.FlushFinalBlock();
        string str = Convert.ToBase64String(stream.ToArray());
        foreach(char ch in str)
            Console.Write("{0:X}", Convert.ToUInt32(ch));
    }
}

Finalmente, escribí mi generador de claves en python, usando el PyDes de Todd Whiteman:

from pyDes import *
from base64 import b64encode
TheKey = b"\xd4\xed\x34\x93\x1c\x48\xac\x08"
Vector = b"\x12\x44\x16\xee\x88\x15\xdd\x41"
k = des(TheKey, CBC, Vector, padmode=PAD_PKCS5)
Username = input("Name: ")
d = b64encode(k.encrypt(Username))
print("Serial: " + "".join('%02X' % i for i in d))

Aquí están algunas de las salidas:
_
C:\Python33>python.exe RDG_Simple_Crackme.py
Name: RDGMax
Serial: 456D455A6866384A304E343D

C:\Python33>python.exe RDG_Simple_Crackme.py
Name: rmolina
Serial: 7942596B573755696550553D

C:\Python33>python.exe RDG_Simple_Crackme.py
Name: Ruben Molina
Serial: 347661484671357363615337496B4B517644694231773D3D

Las verificamos y todas son correctas :)


Y eso es todo por hoy :)

lunes, 26 de agosto de 2013

Rnd0Ms keygenme

Aprovechando que no hubo clase de 2pm, y solo por completitud, decidi hacer el ultimo keygen del reto de este mes: "RndOMs keygenme".  Este es el mas facil de los tres y solo me qudaria pendiente el reto de  unpackmg  :)


Al abrirlo en IDA Free encuentro referencias a Borland, asi que preferi trabajar con IDR (Interactive Delphi Reconstructor). Desde alli es trivial cargar el unico fromulario y saltar al procedimiento asociado al unico boton:

 Unit1::TForm1.Button1Click
 0045193C    push       ebp
 0045193D    mov        ebp,esp
 0045193F    xor        ecx,ecx
 00451941    push       ecx
 00451942    push       ecx
 00451943    push       ecx
 00451944    push       ecx
 00451945    push       ebx
 00451946    push       esi
 00451947    mov        ebx,eax
 00451949    xor        eax,eax
 0045194B    push       ebp
 0045194C    push       4519E9
 00451951    push       dword ptr fs:[eax]
 00451954    mov        dword ptr fs:[eax],esp
 00451957    lea        edx,[ebp-8]
 0045195A    mov        eax,dword ptr [ebx+304]; TForm1.Edit1:TEdit
 00451960    call       TControl.GetText
 00451965    mov        eax,dword ptr [ebp-8]
 00451968    call       @LStrLen
 0045196D    mov        esi,eax
 0045196F    lea        edx,[ebp-4]
 00451972    mov        eax,dword ptr [ebx+304]; TForm1.Edit1:TEdit
 00451978    call       TControl.GetText
 0045197D    mov        eax,esi
 0045197F    add        eax,0FFFFFFFE
 00451982    sub        eax,4
>00451985    jb         0045198E
 00451987    sub        eax,0F
>0045198A    jb         004519A7
>0045198C    jmp        004519BE
 0045198E    lea        edx,[ebp-0C]
 00451991    mov        eax,dword ptr [ebp-4]
 00451994    call       ReverseString
 00451999    mov        ecx,dword ptr [ebp-0C]
 0045199C    mov        edx,esi
 0045199E    mov        eax,ebx
 004519A0    call       00451524
>004519A5    jmp        004519BE
 004519A7    lea        edx,[ebp-10]
 004519AA    mov        eax,dword ptr [ebp-4]
 004519AD    call       UpperCase
 004519B2    mov        ecx,dword ptr [ebp-10]
 004519B5    mov        edx,esi
 004519B7    mov        eax,ebx
 004519B9    call       00451730
 004519BE    xor        eax,eax
 004519C0    pop        edx
 004519C1    pop        ecx
 004519C2    pop        ecx
 004519C3    mov        dword ptr fs:[eax],edx
 004519C6    push       4519F0
 004519CB    lea        eax,[ebp-10]
 004519CE    mov        edx,2
 004519D3    call       @LStrArrayClr
 004519D8    lea        eax,[ebp-8]
 004519DB    call       @LStrClr
 004519E0    lea        eax,[ebp-4]
 004519E3    call       @LStrClr
 004519E8    ret
<004519E9    jmp        @HandleFinally
<004519EE    jmp        004519CB
 004519F0    pop        esi
 004519F1    pop        ebx
 004519F2    mov        esp,ebp
 004519F4    pop        ebp
 004519F5    ret

Leemos el nombre con GetText, y calculamos la longitud con @LStrLen, las instrucciones en resaltado naranja muestran que esta longitud se almacena en esi, luego se mueve a eax, se le suma -2, se le resta 4 y se toma una decisión.  Luego se resta un 0xf y se toma otra decision.

Básicamente, si la longitud del nombre es menor que 5 tomaremos el primer salto  (hacia 0045198E) y si no pero es menor que 21 (6 + 0xf) entonces tomamos el segundo salto (hacia 004519A7).

Luego, si habíamos tomado el primer salto el nombre se invierte (ReverseString) y seguimos hacia una llamada a 00451524 (en amarillo), pero si habiamos tomado el segundo salto el nombre se lleva a mayúsculas (UpperCase) y seguimos con una llamada a 00451730

Miremos la primera llamada:

 Unit1::sub_00451524
 00451524    push       ebp
 00451525    mov        ebp,esp
 00451527    push       ecx
 00451528    mov        ecx,8
 0045152D    push       0
 0045152F    push       0
 00451531    dec        ecx
<00451532    jne        0045152D
 00451534    xchg       ecx,dword ptr [ebp-4]
 00451537    push       ebx
 00451538    mov        dword ptr [ebp-8],ecx
 0045153B    mov        dword ptr [ebp-4],edx
 0045153E    mov        ebx,eax
 00451540    mov        eax,dword ptr [ebp-8]
 00451543    call       @LStrAddRef
 00451548    xor        eax,eax
 0045154A    push       ebp
 0045154B    push       4516B4
 00451550    push       dword ptr fs:[eax]
 00451553    mov        dword ptr fs:[eax],esp
 00451556    lea        eax,[ebp-10]
 00451559    mov        edx,4516CC; 'R'
 0045155E    call       @LStrLAsg
 00451563    lea        eax,[ebp-14]
 00451566    mov        edx,4516D8; 'e'
 0045156B    call       @LStrLAsg
 00451570    lea        eax,[ebp-18]
 00451573    mov        edx,4516E4; 'g'
 00451578    call       @LStrLAsg
 0045157D    lea        eax,[ebp-1C]
 00451580    mov        edx,4516F0; 'i'
 00451585    call       @LStrLAsg
 0045158A    lea        eax,[ebp-20]
 0045158D    mov        edx,4516FC; 's'
 00451592    call       @LStrLAsg
 00451597    lea        eax,[ebp-24]
 0045159A    mov        edx,451708; 't'
 0045159F    call       @LStrLAsg
 004515A4    lea        eax,[ebp-28]
 004515A7    mov        edx,451714; 'd '
 004515AC    call       @LStrLAsg
 004515B1    lea        eax,[ebp-2C]
 004515B4    mov        edx,451708; 't'
 004515B9    call       @LStrLAsg
 004515BE    lea        eax,[ebp-34]
 004515C1    mov        edx,451720; 'o '
 004515C6    call       @LStrLAsg
 004515CB    lea        eax,[ebp-30]
 004515CE    mov        edx,45172C; 'r'
 004515D3    call       @LStrLAsg
 004515D8    pushad
 004515D9    mov        edx,dword ptr [ebp-4]
 004515DC    mov        esi,dword ptr [ebp-8]
 004515DF    mov        ecx,1
 004515E4    xor        ebx,ebx
 004515E6    xor        eax,eax
 004515E8    movzx      eax,byte ptr ds:[esi+ecx]
 004515ED    add        ebx,eax
 004515EF    xor        ebx,0FFF
 004515F5    shr        ebx,1
 004515F7    inc        ecx
 004515F8    cmp        ecx,edx
<004515FA    jne        004515E8
 004515FC    mov        dword ptr [ebp-0C],ebx
 004515FF    popad
 00451600    lea        edx,[ebp-38]
 00451603    mov        eax,dword ptr [ebp-0C]
 00451606    call       IntToStr
 0045160B    mov        eax,dword ptr [ebp-38]
 0045160E    push       eax
 0045160F    lea        edx,[ebp-3C]
 00451612    mov        eax,dword ptr [ebx+308]
 00451618    call       TControl.GetText
 0045161D    mov        eax,dword ptr [ebp-3C]
 00451620    pop        edx
 00451621    call       CompareStr
 00451626    test       eax,eax
>00451628    jne        00451679
 0045162A    push       dword ptr [ebp-10]
 0045162D    push       dword ptr [ebp-14]
 00451630    push       dword ptr [ebp-18]
 00451633    push       dword ptr [ebp-1C]
 00451636    push       dword ptr [ebp-20]
 00451639    push       dword ptr [ebp-24]
 0045163C    push       dword ptr [ebp-14]
 0045163F    push       dword ptr [ebp-30]
 00451642    push       dword ptr [ebp-14]
 00451645    push       dword ptr [ebp-28]
 00451648    push       dword ptr [ebp-2C]
 0045164B    push       dword ptr [ebp-34]
 0045164E    lea        edx,[ebp-44]
 00451651    mov        eax,dword ptr [ebx+304]
 00451657    call       TControl.GetText
 0045165C    push       dword ptr [ebp-44]
 0045165F    lea        eax,[ebp-40]
 00451662    mov        edx,0D
 00451667    call       @LStrCatN
 0045166C    mov        edx,dword ptr [ebp-40]
 0045166F    mov        eax,[00454BD0]; 0x0 gvar_00454BD0:TForm1
 00451674    call       TControl.SetText
 00451679    xor        eax,eax
 0045167B    pop        edx
 0045167C    pop        ecx
 0045167D    pop        ecx
 0045167E    mov        dword ptr fs:[eax],edx
 00451681    push       4516BB
 00451686    lea        eax,[ebp-44]
 00451689    call       @LStrClr
 0045168E    lea        eax,[ebp-40]
 00451691    call       @LStrClr
 00451696    lea        eax,[ebp-3C]
 00451699    call       @LStrClr
 0045169E    lea        eax,[ebp-38]
 004516A1    mov        edx,0B
 004516A6    call       @LStrArrayClr
 004516AB    lea        eax,[ebp-8]
 004516AE    call       @LStrClr
 004516B3    ret
<004516B4    jmp        @HandleFinally
<004516B9    jmp        00451686
 004516BB    mov        eax,dword ptr [ebp-0C]
 004516BE    pop        ebx
 004516BF    mov        esp,ebp
 004516C1    pop        ebp
 004516C2    ret

Para cada byte desde el segundo (ecx se setea a 1 en la primera linea resaltada, no a 0), acumulu su representacion en ebx, luego hago xor con 0xfff y luego un shr de 1.  Ese es todo el calculo, tambien se ve en negritas como se va conformado el "Registd to " que se concatenara con @LStrCatN y que luego se usara para establecer el texto de algun control con SetText.

Si miramos la segunda call, tenemos esto:

 Unit1::sub_00451730
 00451730    push       ebp
 00451731    mov        ebp,esp
 00451733    push       ecx
 00451734    mov        ecx,8
 00451739    push       0
 0045173B    push       0
 0045173D    dec        ecx
<0045173E    jne        00451739
 00451740    xchg       ecx,dword ptr [ebp-4]
 00451743    push       ebx
 00451744    mov        dword ptr [ebp-8],ecx
 00451747    mov        dword ptr [ebp-4],edx
 0045174A    mov        ebx,eax
 0045174C    mov        eax,dword ptr [ebp-8]
 0045174F    call       @LStrAddRef
 00451754    xor        eax,eax
 00451756    push       ebp
 00451757    push       4518C0
 0045175C    push       dword ptr fs:[eax]
 0045175F    mov        dword ptr fs:[eax],esp
 00451762    lea        eax,[ebp-10]
 00451765    mov        edx,4518D8; 'R'
 0045176A    call       @LStrLAsg
 0045176F    lea        eax,[ebp-14]
 00451772    mov        edx,4518E4; 'e'
 00451777    call       @LStrLAsg
 0045177C    lea        eax,[ebp-18]
 0045177F    mov        edx,4518F0; 'g'
 00451784    call       @LStrLAsg
 00451789    lea        eax,[ebp-1C]
 0045178C    mov        edx,4518FC; 'i'
 00451791    call       @LStrLAsg
 00451796    lea        eax,[ebp-20]
 00451799    mov        edx,451908; 's'
 0045179E    call       @LStrLAsg
 004517A3    lea        eax,[ebp-24]
 004517A6    mov        edx,451914; 't'
 004517AB    call       @LStrLAsg
 004517B0    lea        eax,[ebp-28]
 004517B3    mov        edx,451920; 'd '
 004517B8    call       @LStrLAsg
 004517BD    lea        eax,[ebp-2C]
 004517C0    mov        edx,451914; 't'
 004517C5    call       @LStrLAsg
 004517CA    lea        eax,[ebp-34]
 004517CD    mov        edx,45192C; 'o '
 004517D2    call       @LStrLAsg
 004517D7    lea        eax,[ebp-30]
 004517DA    mov        edx,451938; 'r'
 004517DF    call       @LStrLAsg
 004517E4    pushad
 004517E5    mov        edx,dword ptr [ebp-4]
 004517E8    mov        esi,dword ptr [ebp-8]
 004517EB    mov        ecx,2
 004517F0    xor        ebx,ebx
 004517F2    xor        eax,eax
 004517F4    movzx      eax,byte ptr ds:[esi+ecx]
 004517F9    add        ebx,eax
 004517FB    xor        ebx,0AF
 00451801    shl        ebx,1
 00451803    inc        ecx
 00451804    cmp        ecx,edx
<00451806    jne        004517F4
 00451808    mov        dword ptr [ebp-0C],ebx
 0045180B    popad
 0045180C    lea        edx,[ebp-38]
 0045180F    mov        eax,dword ptr [ebp-0C]
 00451812    call       IntToStr
 00451817    mov        eax,dword ptr [ebp-38]
 0045181A    push       eax
 0045181B    lea        edx,[ebp-3C]
 0045181E    mov        eax,dword ptr [ebx+308]
 00451824    call       TControl.GetText
 00451829    mov        eax,dword ptr [ebp-3C]
 0045182C    pop        edx
 0045182D    call       CompareStr
 00451832    test       eax,eax
>00451834    jne        00451885
 00451836    push       dword ptr [ebp-10]
 00451839    push       dword ptr [ebp-14]
 0045183C    push       dword ptr [ebp-18]
 0045183F    push       dword ptr [ebp-1C]
 00451842    push       dword ptr [ebp-20]
 00451845    push       dword ptr [ebp-24]
 00451848    push       dword ptr [ebp-14]
 0045184B    push       dword ptr [ebp-30]
 0045184E    push       dword ptr [ebp-14]
 00451851    push       dword ptr [ebp-28]
 00451854    push       dword ptr [ebp-2C]
 00451857    push       dword ptr [ebp-34]
 0045185A    lea        edx,[ebp-44]
 0045185D    mov        eax,dword ptr [ebx+304]
 00451863    call       TControl.GetText
 00451868    push       dword ptr [ebp-44]
 0045186B    lea        eax,[ebp-40]
 0045186E    mov        edx,0D
 00451873    call       @LStrCatN
 00451878    mov        edx,dword ptr [ebp-40]
 0045187B    mov        eax,[00454BD0]; 0x0 gvar_00454BD0:TForm1
 00451880    call       TControl.SetText
 00451885    xor        eax,eax
 00451887    pop        edx
 00451888    pop        ecx
 00451889    pop        ecx
 0045188A    mov        dword ptr fs:[eax],edx
 0045188D    push       4518C7
 00451892    lea        eax,[ebp-44]
 00451895    call       @LStrClr
 0045189A    lea        eax,[ebp-40]
 0045189D    call       @LStrClr
 004518A2    lea        eax,[ebp-3C]
 004518A5    call       @LStrClr
 004518AA    lea        eax,[ebp-38]
 004518AD    mov        edx,0B
 004518B2    call       @LStrArrayClr
 004518B7    lea        eax,[ebp-8]
 004518BA    call       @LStrClr
 004518BF    ret
<004518C0    jmp        @HandleFinally
<004518C5    jmp        00451892
 004518C7    mov        eax,dword ptr [ebp-0C]
 004518CA    pop        ebx
 004518CB    mov        esp,ebp
 004518CD    pop        ebp
 004518CE    ret

Vemos que el procedimiento es casi el mismo, solo que esta vez ecx es igual a 2 en lugar de 1, y hacemos xor con 0xaf en lugar de 0xfff, ahhh y el corrimeinto de bits es al contrario, un shl en lugar de shr,

El código del keygen es muy simple:

name = input("name: ")
serial = 0
if len(name) > 5:
    for c in name.upper()[2:]:
        serial += ord(c)
        serial = serial ^ 0xaf
        serial = serial  << 1
else:
    for c in name[::-1][1:]:
        serial += ord(c)
        serial = serial ^ 0xfff
        serial = serial >> 1
print("serial:", serial)

No me fije mucho mas en la comprobacion de nombres largos, es seguro que no funcionara para mas de 21. Pero probé algunos seriales de  menos de 5 y de mas de 5, y todos funcionaron, para "rmolina" el serial es 10328.





Bonus: Las dimensiones de la ventana no eran adecuadas para esta maquina, tanto que ni se veia el botón al abrirlo.  Ademas, como el mensaje de "Registered to" sale en el Caption, necesitaba agrandarla para poder mostrar el pantllazo.  Para esto, edite el binario con Resource Hacker en RCDATA / TFORM1 y elimine las siguientes lineas:

  Constraints.MaxHeight = 154
  Constraints.MaxWidth = 234
  Constraints.MinHeight = 154
  Constraints.MinWidth = 234


Dark Puzzle KeygenMe

Durante la hora del almuerzo estuve mirando otro reto de los que dejo Ricardo, esta vez fue el Dark-Puzzle_KeygenMe y este me parece que estaba mucho mas fácil, asi que el post no sera muy extenso, solo presento el codigo comentado, el resumen del proceso y el keygen.



Se trata de una aplicación de consola que presenta ese MessageBox al inicio (aqui se reporta otro nombre para el keygenme, pero lo seguire llamando darkpuzzle).  Valida de cierto modo el email, pero finalmente no lo usa para calcular el serial.

Desde IDA Free, entramos directamente en el start() y no necesitaremos nada mas... Por comodidad marque como input() y print() algunas funciones que precan obvias, y cambie la representacion de algunas variables para que aparezcan como chars:

.text:00401000 ; Attributes: noreturn
.text:00401000
.text:00401000                 public start
.text:00401000 start           proc near
.text:00401000                 push    0               ; uType
.text:00401002                 push    offset Caption  ; "ItSecurity.ma KeygenMe (RESTRICTED PATC"...
.text:00401007                 push    offset Text     ; "Itsecurity.ma KeygenME Coded by Souhail"...
.text:0040100C                 push    0               ; hWnd
.text:0040100E                 call    MessageBoxA
.text:00401013                 push    offset aPleaseTypeYour ; "Please type your e-mail: "
.text:00401018                 call    print
.text:0040101D                 push    0C8h            ; nNumberOfBytesToRead
.text:00401022                 push    offset email    ; lpBuffer
.text:00401027                 call    input
.text:0040102C                 lea     eax, email
.text:00401032                 xor     edx, edx
.text:00401034                 xor     ecx, ecx
.text:00401036
.text:00401036 loc_401036:                             ; CODE XREF: start+47 j
.text:00401036                 mov     bl, [eax]
.text:00401038                 cmp     bl, 40h
.text:0040103B                 jz      short loc_401049
.text:0040103D                 cmp     bl, dl
.text:0040103F                 jz      loc_4011EB
.text:00401045                 inc     ecx
.text:00401046                 inc     eax
.text:00401047                 jmp     short loc_401036
.text:00401049 ; ---------------------------------------------------------------------------
.text:00401049
.text:00401049 loc_401049:                             ; CODE XREF: start+3B j
.text:00401049                 cmp     cl, 3
.text:0040104C                 jle     loc_40120B
.text:00401052                 push    offset aPleaseEnterAVa ; "Please Enter a valid serial: "
.text:00401057                 call    print
.text:0040105C                 push    0C8h            ; nNumberOfBytesToRead
.text:00401061                 push    offset serial   ; lpBuffer
.text:00401066                 call    input
.text:0040106B                 push    offset serial   ; lpString
.text:00401070                 call    lstrlenA
.text:00401075                 cmp     eax, 17h
.text:00401078                 jnz     mala
.text:0040107E                 lea     eax, serial
.text:00401084                 xor     ebx, ebx
.text:00401086                 mov     ebx, [eax]
.text:00401088                 cmp     ebx, '-STI'     ; primer bloque
.text:0040108E                 jnz     mala
.text:00401094                 add     eax, 8
.text:00401097                 cmp     byte ptr [eax], '-' ; separa el bloque
.text:0040109A                 jnz     mala
.text:004010A0                 xor     ecx, ecx
.text:004010A2                 xor     edx, edx
.text:004010A4                 mov     cl, 3
.text:004010A6                 mov     dl, 5
.text:004010A8
.text:004010A8 loc_4010A8:                             ; CODE XREF: start+AF j
.text:004010A8                 add     eax, edx
.text:004010AA                 dec     cl
.text:004010AC                 cmp     byte ptr [eax], 2Dh ; ITS-????-????-????-????
.text:004010AF                 jz      short loc_4010A8
.text:004010B1                 cmp     cl, 0
.text:004010B4                 jnz     mala
.text:004010BA                 lea     eax, serial
.text:004010C0                 add     eax, 4              ; posicion 4
.text:004010C3                 mov     ebx, [eax]
.text:004010C5                 lea     ecx, pos4
.text:004010CB                 mov     [ecx], ebx
.text:004010CD                 add     eax, 5              ; posicion 9
.text:004010D0                 mov     ebx, [eax]
.text:004010D2                 lea     ecx, pos9
.text:004010D8                 mov     [ecx], ebx
.text:004010DA                 add     eax, 5              ; posicion 14
.text:004010DD                 mov     ebx, [eax]
.text:004010DF                 lea     ecx, pos14
.text:004010E5                 mov     [ecx], ebx
.text:004010E7                 add     eax, 5              ; posicion 19
.text:004010EA                 mov     ebx, [eax]
.text:004010EC                 lea     ecx, pos19
.text:004010F2                 mov     [ecx], ebx
.text:004010F4                 xor     eax, eax
.text:004010F6                 xor     ebx, ebx
.text:004010F8                 xor     edx, edx
.text:004010FA                 xor     ecx, ecx
.text:004010FC                 lea     eax, pos4
.text:00401102                 mov     eax, [eax]
.text:00401104                 sub     eax, 30303030h  ; numericos, no hexas
.text:00401109                 lea     edx, pos4
.text:0040110F                 mov     [edx], eax
.text:00401111                 mov     bl, [edx]
.text:00401113                 mov     cl, [edx+1]
.text:00401116                 add     bl, cl
.text:00401118                 mov     cl, [edx+2]
.text:0040111B                 add     bl, cl
.text:0040111D                 mov     cl, [edx+3]
.text:00401120                 add     bl, cl
.text:00401122                 cmp     bl, 10h         ; la suma del bloque
.text:00401122                                         ; es 16
.text:00401125                 jnz     mala
.text:0040112B                 lea     edx, pos9       ; otro bloque
.text:00401131                 mov     bl, [edx]
.text:00401133                 cmp     bl, 'O'         ; siguiente bloque en 'O'
.text:00401136                 jnz     mala
.text:0040113C                 mov     cl, [edx+1]
.text:0040113F                 add     bl, cl
.text:00401141                 mov     cl, [edx+2]
.text:00401144                 add     bl, cl
.text:00401146                 mov     cl, [edx+3]
.text:00401149                 sub    bl, cl
.text:0040114B                 cmp     bl, 8Fh         ; 'O' + 2do + 3ro - 4to
.text:0040114E                 jnz     short mala
.text:00401150                 lea     eax, pos14      ; otro bloque
.text:00401156                 mov     eax, [eax]
.text:00401158                 sub     eax, 30303030h  ; numericos, no hexas
.text:0040115D                 lea     edx, pos14
.text:00401163                 mov     [edx], eax
.text:00401165                 mov     bl, [edx]
.text:00401167                 mov     cl, [edx+1]
.text:0040116A                 add     bl, cl
.text:0040116C                 mov     cl, [edx+2]
.text:0040116F                 add     bl, cl
.text:00401171                 mov     cl, [edx+3]
.text:00401174                 sub     cl, 2
.text:00401177                 add     bl, cl
.text:00401179                 cmp     bl, 10h          ; suma - 2 es 16
.text:0040117C                 jnz     short mala
.text:0040117E                 lea     eax, pos19       ; otro bloque
.text:00401184                 mov     eax, [eax] 
.text:00401186                 sub     eax, 30303030h   ; numericos, no hexas
.text:0040118B                 lea     edx, pos19
.text:00401191                 mov     [edx], eax
.text:00401193                 mov     bl, [edx]
.text:00401195                 mov     cl, [edx+1]
.text:00401198                 add     bl, cl
.text:0040119A                 mov     cl, [edx+2]
.text:0040119D                 add     bl, cl
.text:0040119F                 mov     cl, [edx+3]
.text:004011A2                 add     bl, cl
.text:004011A4                 cmp     bl, 12h          ; suma es 18
.text:004011A7                 jnz     short mala
.text:004011A9                 jmp     short $+2
.text:004011AB                 push    offset aValidSerialPre ; "Valid Serial (Press Enter To Exit)"
.text:004011B0                 call    print
.text:004011B5                 push    0C8h            ; nNumberOfBytesToRead
.text:004011BA                 push    offset exit     ; lpBuffer
.text:004011BF                 call    input
.text:004011C4                 push    0               ; uExitCode
.text:004011C6                 call    ExitProcess
.text:004011CB ; ---------------------------------------------------------------------------
.text:004011CB
.text:004011CB mala:                                   ; CODE XREF: start+78 j
.text:004011CB                                         ; start+8E j ...
.text:004011CB                 push    offset aInvalidSerialP ; "Invalid Serial (Press Enter To Exit)"
.text:004011D0                 call    print
.text:004011D5                 push    0C8h            ; nNumberOfBytesToRead
.text:004011DA                 push    offset exit     ; lpBuffer
.text:004011DF                 call    input
.text:004011E4                 push    0               ; uExitCode
.text:004011E6                 call    ExitProcess
.text:004011EB ; ---------------------------------------------------------------------------
.text:004011EB
.text:004011EB loc_4011EB:                             ; CODE XREF: start+3F j
.text:004011EB                 push    offset aPleaseInsertAV ; "Please Insert a Valid Mail Address (Pre"...
.text:004011F0                 call    print
.text:004011F5                 push    0C8h            ; nNumberOfBytesToRead
.text:004011FA                 push    offset exit     ; lpBuffer
.text:004011FF                 call    input
.text:00401204                 push    0               ; uExitCode
.text:00401206                 call    ExitProcess
.text:0040120B ; ---------------------------------------------------------------------------
.text:0040120B
.text:0040120B loc_40120B:                             ; CODE XREF: start+4C j
.text:0040120B                 push    offset aPleaseEnterAnE ; "Please Enter an email with 4 Characters"...
.text:00401210                 call    print
.text:00401215                 push    0C8h            ; nNumberOfBytesToRead
.text:0040121A                 push    offset exit     ; lpBuffer
.text:0040121F                 call    input
.text:00401224                 push    0               ; uExitCode
.text:00401226                 call    ExitProcess
.text:00401226 start           endp
.text:00401226
.text:00401226 ; ---------------------------------------------------------------------------
.text:0040122B                 align 4
.text:0040122C ; [00000006 BYTES: COLLAPSED FUNCTION MessageBoxA. PRESS KEYPAD "+" TO EXPAND]
.text:00401232                 align 4
.text:00401234

La idea es bien simple: el serial tiene una longitud 23 y esta compuesto por cinco bloques separados por guiones, el primer bloque es siempre el mismo "ITS", los demas bloques tiene reglas especificas:

A cada caracter del segundo bloque se le restara 0x30, y los resultados se suman. Esta suma debe dar 16.
Lo mas sencillo es usar solo numeros en este bloque, asi al resta 0x30, estaremos pasando de la representacion en en hex al numero en entero.... Visto asi basta con seleccionar 4 numero al azar cuaya suma de 16, durante mi prueba use cuatro cuatros.

El tercer bloque funciona distinto, primero verificamos que el primer caracter del bloque es una 'O' (no es un cero es uan o mayuscula), luego sumamos el primer, segundo y tercer caracter, y le restamos el cuarto (aqui sumamos sus representaciones, ya que no se resto 0x30 en este paso)... El resultado de estas operaciones debe ser 8F.  En este caso pueden usarse solo mayusculas, por ejemplo, como la primera letra era una 'O', yo seleccione una 'M' y una 'G'  para el segundo y tercer caracteres del bloque, solo para formar un "OMG", a la suma de las representaciones le resto el valor esperado 8F y obtengo que el cuarto caracter para completar esta cadena debe ser una 'T', para el keygen, es cuestion de elegir dos musculas al zar y calcular la ultima

El cuarto bloque es parecido al primero, se resta 0x30 a cada representacion, asi que usaremos numeros para este bloque, ademas a la suma obtenida se le restan 2, y el resultado es perado, es 16, o en otras palabras la suma del bloque debe dar 18.  Para mi prueba simplemente use 4545. PAra el keygen, elegir 4 numeros que sumes 18.

El quinto bloque es muy parecido al anterior, simplemente no se resta el 2, y se compara con 18, directamente. Asi que use el mismo valor del bloque anterior.  La misma estrategia sirve para el keygen

Mi serial fue entonces este: ITS-4444-OMGT-4545-4545


El keygen es muy simple:

from random import choice
from string import ascii_uppercase

serial = [ '-' ] * 23

serial[0] = 'I'
serial[1] = 'T'
serial[2] = 'S'

serial[4] = str(choice(range(9)))
serial[5] = str(choice(range(9)))
serial[6] = str(8 - int(serial[4]))
serial[7] = str(8 - int(serial[5]))

serial[9] = 'O'
while serial[12] not in ascii_uppercase:
    serial[10] = choice(ascii_uppercase)
    serial[11] = choice(ascii_uppercase)
    serial[12] = chr(ord(serial[10]) + ord(serial[11]) - 64)

serial[14] = str(choice(range(10)))
serial[15] = str(choice(range(10)))
serial[16] = str(9 - int(serial[14]))
serial[17] = str(9 - int(serial[15]))

serial[19] = str(choice(range(10)))
serial[20] = str(choice(range(10)))
serial[21] = str(9 - int(serial[19]))
serial[22] = str(9 - int(serial[20]))

print( ''.join(serial))

Agregue ese while, porque me parecia que se veian mejor los seriales si el bloque estaba todo en mayúsculas, pero no es necesario realmente, 

Veamos algunas salidas:

C:\Python33>python.exe darkpuzzle.py
ITS-6523-OMAN-9504-7227

C:\Python33>python.exe darkpuzzle.py
ITS-4642-OGNU-8712-3267

C:\Python33>python.exe darkpuzzle.py
ITS-3751-OMER-8415-0891

C:\Python33>python.exe darkpuzzle.py
ITS-5038-OPBR-0297-9702

Y al probarlas vemos que todas son correctas, asi que eso es todo por hoy y ahora si me voy a almorzar.