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
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
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
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:
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.
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
Comentarios
Publicar un comentario