DISCLAIMER: THE
FOLLOWING TEXT IS FOR EDUCATIONAL PURPOSES ONLY. THE AUTHOR OF THIS TEXT DOES
NOT ADVOCATE OR ENCOURAGE ILLEGAL PRACTICES IN ANY FORM. THE AUTHOR OF THIS
ARTICLE IS NOT RESPONSIBLE FOR ILLEGAL USE OF THIS TEXT. ANY
COMMERCIAL/MALICIOUS USES BASED ON THE TEXT ARE SOLELY THE READER'S LIABILITY.
Globeriz Project
by Globeriz
Submitted on: 21 Dec
2013
Analysis started: 20
Dec 2013
---------------------------------------------------------------------------------------------------------------------------
Product Name:
JoyToKey
Version: 5.4.2
(5.42.305)
Official
Website:http://joytokey.net/en/
Main executable:
JoyToKey.exe
Executable size:
1.62MB (1,629,184B)
MD5:
88defd0e09b0d0759f268ab7689388df
SHA-1:
e1d3f28a96b8d767ce6c3943ef9f9ea66b263f76
---------------------------------------------------------------------------------------------------------------------------
Product Desciption (according to official site):
JoyToKey (or Joy2Key) enables PC game controllers to emulate a mouse and the keyboard input, so that windows applications and web games can be controlled with your favorite joysticks! Whenever joystick buttons and sticks are pressed, JoyToKey converts them into keyboard strokes and/or mouse movements so that the targeted application will work as if you are using a real keyboard and a mouse!
---------------------------------------------------------------------------------------------------------------------------
Screenshot of Application (click to enlarge:
---------------------------------------------------------------------------------------------------------------------------
Product Desciption (according to official site):
JoyToKey (or Joy2Key) enables PC game controllers to emulate a mouse and the keyboard input, so that windows applications and web games can be controlled with your favorite joysticks! Whenever joystick buttons and sticks are pressed, JoyToKey converts them into keyboard strokes and/or mouse movements so that the targeted application will work as if you are using a real keyboard and a mouse!
---------------------------------------------------------------------------------------------------------------------------
Screenshot of Application (click to enlarge:
---------------------------------------------------------------------------------------------------------------------------
Difficulty level:
Easy[ ] Normal [x] Hard [ ] Insane [ ] Nightmare [ ]
---------------------------------------------------------------------------------------------------------------------------
Achieved:
License key sniffing
[20 Dec 2013]
KeyGen [21 Dec 2013]
---------------------------------------------------------------------------------------------------------------------------
//start
PEiD:Borland C++ 1999
//no shell, yay!
Observations:
Unlicensed product
diaplays [Unregistered] in title bar
New files created
after closing application for first time
License code input in
format XXXX-XXXX-XXXX
Shows popup window if
registration failed/succeeded
No interesting
changes to registry
Notations:
a"" ASCII literal
<licenseKey> placeholder for license Key, e.g.
1234-5678-ABCD
Assumption(s):
Valid license key
characters: ABCDEFGHJKLMNPQRSTUVWXYZ123456789
Magic string(s):
ABCDEFGHJKLMNPQRSTUVWXYZ123456789
//missing I, O and 0
DEKIMOUSE
JTE4
Sniffed License
Key(s):
[withheld]
Validation files:
JoyToKey.ini
Essential Content:
[License]
Key=<licenseKey>
Notes on runtime
debugging:
Loop for serial
calculation
00426032 |> 8B45 FC |MOV EAX,DWORD PTR SS:[EBP-4]
00426035 |. F7EE |IMUL ESI
00426037 |. 03C7 |ADD EAX,EDI
00426039 |. 8945 FC |MOV DWORD PTR SS:[EBP-4],EAX
0042603C |. FF45 F4 |INC DWORD PTR SS:[EBP-C]
0042603F |. 035D F8 |ADD EBX,DWORD PTR SS:[EBP-8]
00426042 |. 837D F4 04 |CMP DWORD PTR SS:[EBP-C],4
00426046 |.^7C CC \JL SHORT JoyToKey.00426014
//asm note: IMUL ESI
--> eax *= esi
//1.loop start
1. //hypothesis:
calculation based on a"4"
eax=0x00
edi=0x1b
esi=0x21 //suspected CONSTANT
[edx]=a"456789"
2. //a"E"
eax=0x37b+0x04=0x37f //0x1b * 0x21 = 0x37b
ebx=<part of
JTE4> //[ebp+8]=a"JTE4"
[edx]=a"EFG...789" //EFGHJKLMNPQRSTUVWXYZ123456789
edi=0x04
3. //a"T"
eax=0x735f+0x11=0x7370 //0x37b * 0x21 = 0x735f
edi=0x11
[edx]=a"TUV...789" //TUVWXYZ123456789
4. //a"J"
eax=0xee170+0x08=0xee178
edi=0x08
[edx]=a"JKL...789"
// end of first loop
//extra:
[esp-4]=a"ABC...789"
//We can then
establish a"4ETJ" = 0xee178
//Main Analysis:
(1) Odd-looking
string literal
004038C1 |. BA E2975400 MOV EDX,JoyToKey.005497E2 ; ASCII "DEKI-MOUS-E"
(2) Loop for
calculating first 8 digits
00426011 |. 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
00426014 |> 33FF /XOR EDI,EDI
00426016 |. 33C0
|XOR EAX,EAX
00426018 |. 8B15 307A5500 |MOV EDX,DWORD PTR DS:[557A30] ;
JoyToKey.00557A06
0042601E |. 3BF0 |CMP ESI,EAX
00426020 |. 7E 10 |JLE SHORT JoyToKey.00426032
00426022 |> 8A0B |/MOV CL,BYTE PTR DS:[EBX] //start of nested loop
00426024 |. 3A0A ||CMP CL,BYTE PTR DS:[EDX]
00426026 |. 75 04 ||JNZ SHORT JoyToKey.0042602C
00426028 |. 8BF8 ||MOV EDI,EAX
0042602A |. EB 06 ||JMP SHORT JoyToKey.00426032
0042602C |> 40 ||INC EAX
0042602D |. 42 ||INC EDX
0042602E |. 3BF0 ||CMP ESI,EAX
00426030 |.^7F F0 |\JG SHORT JoyToKey.00426022
00426032 |> 8B45 FC |MOV EAX,DWORD PTR SS:[EBP-4]
00426035 |. F7EE |IMUL ESI
00426037 |. 03C7 |ADD EAX,EDI
00426039 |. 8945 FC |MOV DWORD PTR SS:[EBP-4],EAX
0042603C |. FF45 F4 |INC DWORD PTR SS:[EBP-C]
0042603F |. 035D F8 |ADD EBX,DWORD PTR SS:[EBP-8]
00426042 |. 837D F4 04 |CMP DWORD PTR SS:[EBP-C],4
00426046 |.^7C CC \JL SHORT JoyToKey.00426014
00426048 |. 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
//psuedo-code
translation for loop above:
00426011 |. 8945 F4 [EBP-C]:=EAX
00426014 |> 33FF /EDI:=0
00426016 |. 33C0 |EAX:=0
00426018 |. 8B15 307A5500 |EDX:=0x00557a06 ;
JoyToKey.00557A06 //=a"ABC..789" (null-terminated ASCII
string), i.e.[edx]=a"ABC...789"
0042601E |. 3BF0 |setflags (ESI-EAX) //note: ESI=0x21
00426020 |. 7E 10 |if (ESI>=EAX) then goto
JoyToKey.00426032 //skips nested loop
00426022 |> 8A0B |/CL:=first char of EBX //start of nested loop,
note:[ebx]=a"<licenseKey>"
00426024 |. 3A0A ||setflags CL-<first char of
EDX>
00426026 |. 75 04 ||if CL != <first char of EDX>
then goto JoyToKey.0042602C //INC EAX
00426028 |. 8BF8 ||EDI:=EAX
0042602A |. EB 06 ||goto JoyToKey.00426032 //MOV
EAX,DWORD PTR SS:[EBP-4]
0042602C |> 40 ||EAX++
0042602D |. 42 ||IEDX++
0042602E |. 3BF0 ||setflags (ESI-EAX)
00426030 |.^7F F0 |\if (ESI>EAX) then goto
JoyToKey.00426022 //while loop condition
-> start of nested loop
00426032 |> 8B45 FC |MOV EAX,DWORD PTR SS:[EBP-4]
00426035 |. F7EE |EAX:=EAX*ESI
00426037 |. 03C7 |EAX:=EAX+EDI
00426039 |. 8945 FC |DWORD PTR SS:[EBP-4]:=EAX
0042603C |. FF45 F4 |INC DWORD PTR SS:[EBP-C]
0042603F |. 035D F8 |EBX=EBX+EBP-8]
00426042 |. 837D F4 04 |setflags ([EBP-C]-4) //number of digits checked
00426046 |.^7C CC \JL SHORT JoyToKey.00426014
00426048 |. 8B45 FC EAX:=DWORD PTR SS:[EBP-4]
//C++ for above
routine:
{
edi = 0;
eax = 0;
*ebx =
"XXXX-XXXX-XXXX";
*edx =
"ABCDEFGHJKLMNPQRSTUVWXYZ123456789";
if (eax <= esi)
goto loc0 //esi=0x21
do {
cl = ebx[0];
if (cl != edx[0]) {
eax++;
edx++;
} else { //ebx[0] = edx[0]
edi = eax;
goto loc0
}
} while (esi>eax)
loc0:
. . .
eax=eax*esi+edi;
. . .
}
(3) Loop for
calculating last 4 digits:
//Note: EBX=last 4
digits
//EAX=EBP-1C > 00557A06 ASCII
"ABCDEFGHJKLMNPQRSTUVWXYZ123456789"
step 4 each recursion, i.e.
"GHJK...6789" -> finally "9999"
00537778 |> 8B10 /MOV EDX,DWORD PTR DS:[EAX]
0053777A |. 83C0 04 |ADD EAX,4
0053777D |. 8BCA |MOV ECX,EDX
0053777F |. 81EA 01010101 |SUB EDX,1010101
00537785 |. 81E2 80808080 |AND EDX,80808080
0053778B |.^74 EB |JE SHORT JoyToKey.00537778
0053778D |. F7D1 |NOT ECX
0053778F |. 23D1 |AND EDX,ECX
00537791 |.^74 E5 \JE SHORT JoyToKey.00537778
(4) Key comparison
location:
00426139 |. 3BF0 CMP ESI,EAX //EAX=calculated serial, ESI=calculated
"JTE4"=0xee178
//Note: If calculated
serial = calulated "JTE4" then verification will succeed
Some selected
calulated serials:
//Call first 4 digits
group1, middle 4 digits group2, last 4 digits group3. . .
Serial Calculated serial
AAAA-AAAA-AAAA 0x0
AAAA-AAAA-AAAB 0x1
AAAB-AAAA-AAAA 0x1
AAAB-BAAA-AAAB 0x1 //interesting.
. . looks like a comparison of each group (groups of 4 digits)
AAAB-AAAA-AAAC 0x3
AAAC-AAAA-AAAB 0x3
9999-AAAA-AAAB 0x121881
//so I assume the
result is group1+group2+group3
AAAA-AAAB-AAAA 0x8c61 //=0x01*0x21*0x21*0x21
AAAA-AAAA-AAA9 0x20
//Now, we can see the
calculation is in radix 20
AAAA-AAA9-AAAA 0x118c20 //=0x20*0x21*0x21*0x21
//Since 0x118c20 >
0xee178, we can use the last 4 digits to calculate the correct serial while the
first 8 digits can be totally random
//Now, see if we can
reduce to 3 check digits
AAAA-AAA9-A9AA 0x8820
//So no, we must use
4 check digits
9999-9999-9999 0x121880 //wait. . . the value isn't quite right. . .I assume
group1+group2+group3 ?
9999-9999-AAAB 0x1 //wtf?
3333-3333-AAAB 0x1
AAAB-BAAA-AAAC 0x2
//if group1=group2
then take group3?
ZXCV-VCXZ-AAAB 0x1
//What if
group2=group3?
AAAB-VBNM-MNBV 0x1
//What if
group1=group3?
EGHJ-AAAB-EGHJ 0x8c61
EGHJ-AAAA-AAAA 0x24bf9 //well.
. . maybe it's more complicated than I think?
9997-8999-9999 0x121881
//I give up. .
.better look into the actual code closely. . .
0042612B |. 8B4D D8 MOV ECX,DWORD PTR SS:[EBP-28] //[ebp-28]=result of
group2, [ebp-48]=result of group1, [ebp-58]=result of group1
0042612E |. 8BD0 MOV EDX,EAX //eax=result of group3
00426130 |. 33CF XOR ECX,EDI //edi=result of group1
00426132 |. 83C4 08 ADD ESP,8
00426135 |. 8BC1 MOV EAX,ECX
00426137 |. 33C2 XOR EAX,EDX
00426139 |. 3BF0 CMP ESI,EAX
//therefore. . . EAX
at last line is calculated as follows:
ecx = g2
edx = g3
ecx = ecx xor g1
eax = ecx
eax = eax xor edx
//i.e.
eax = (g2 xor g1) xor
g3 = g1 xor g2 xor g3
//Now the calculation
of serial is clear, we have to reverse the process to write a keygen
//Using properties of
xor:
a xor b = c
<--> a = c xor b
//We want to let
eax=0xee178, so we must find g1,g2,g3 such that
g1 xor g2 xor g3 =
0xee178
g1 = 0xee178 xor g2
xor g3 //where g2,g3 can be random
//Now it's left to
check if solution of g1 falls within range:
0x0 =< g1 =<
0x121880 <--> 0x0 =< 0xee178 xor g2 xor g3 =< 0x121880
//There exists some
combination of g2 and g3 that doesn't satisfy the constriant above
//In fact, to satisfy
the constraint, g2 xor g3 < 0xee178
(5) Algorithm draft:
Format:
XXXX-XXXX-XXXX
Order:
[1][2][3][4]-[8][7][6][5]-[9][10][11][12]
Range of a group:
0x0~0x121880
Range of calculated
serial:
0x0~0x1FFFFF
Keygen can be
composed by 2 parts:
1. Calculation of
serial in each group
2. Calculation of
check digits
Flowchart of keygen:
Generate random first
8 digits -> calculate the two groups -> check if 0xee178 xor g1 xor g2
=< 0x121880 ->
yes: Calculate g3
-> Full license key is given
no: Regenerate random
first 8 digits, start over
//Now we can write a
keygen using our favorite program, and we are done.
//end
---------------------------------------------------------------------------------------------------------------------------
Test your understanding:
1. Complete the
unknown part of the license key to make it usable: GLOB-ERIZ-xxxx
2. Write another
keygen that allows user to input the first 7 digits and the keygen will
calculate the rest to make it usable.
3. Is there any
problem if the keygen allows user to input 8 digits instead of 7?
4. Try to make a
patch for the program to force it accept any license keys.
No comments:
Post a Comment