Contribute  :  Web Resources  :  Past Polls  :  Site Statistics  :  Downloads  :  Forum  
    BiW ReversingThe challenge is yours    
 Welcome to BiW Reversing
 Wednesday, September 22 2021 @ 03:47 AM CEST

Fishing and keygenning games CD keys


TutorialsLevel : beginner

Fishing and keygenning games CD keys

Maybe the best protection today are game protections. Although such protections are very hard to unwrap, it's interesting how their key checks stay very simple in most cases.
Indeed, they are simple but the hardest problem is to actually find where the keygen algo lies in application. This tutorial will show a couple of examples on how game CD keys can be fished or keygened more or less with ease in some cases.

1. HL1

Half Life 1 is now pretty much old game from 10/30/98, but still impressive one and better than some todays. Game has very simple key check and this was first game that I manage to keygen. CD check is very simple too, but that is not objective of this tutorial. After installing game you will probably want to play it. At game start we get nice dialog asking us for game key. On inserting some fake key , we will normally get BadBoy message. Loading game exe in Olly, placing bp on GetWindowTextA, we can break when game is grabbing key from dialog:

But main problem is to find where key check is. Games are big and find such algo is usually mayor problem. But after returning from api, I placed memory bp on serial in memory and found where algo reading it. This first check will read my serial:

It will count how many there is digits in serial and if there is no 0D(hex) digits, I will get BadBoy message. That mean, serial can be long as we wish and non-numeric characters are not important. Conclusion Ė serial is all in numbers and it's length is 13.

00442FB1   . 8A10           MOV DL,BYTE PTR DS:[EAX]
00442FB3   . 84D2           TEST DL,DL

00442FB5   . 74 0E          JE SHORT hl.00442FC5
00442FB7   . 80FA 30        CMP DL,30
00442FBA   . 7C 09          JL SHORT hl.00442FC5
00442FBC   . 80FA 39        CMP DL,39
00442FBF   . 7F 04          JG SHORT hl.00442FC5
00442FC1   . 8813           MOV BYTE PTR DS:[EBX],DL
00442FC3   . 43             INC EBX
00442FC4   . 46             INC ESI
00442FC5   > 40             INC EAX
00442FC6   . 83FE 0D        CMP ESI,0D  8D7D BC        LEA EDI,DWORD PTR SS:[EBP-44]
00442FCE   . B9 FFFFFFFF    MOV ECX,-1
00442FD3   . 2BC0           SUB EAX,EAX
00442FD5   . C603 00        MOV BYTE PTR DS:[EBX],0
00442FD8   . F2:AE          REPNE SCAS BYTE PTR ES:[EDI]
00442FDA   . F7D1           NOT ECX
00442FDC   . 49             DEC ECX
00442FDD   . 75 21          JNZ SHORT hl.00443000  85F6           TEST ESI,ESI
00442FE3   . 0F84 A5000000  JE hl.0044308E 

I entered new serial to pass that check, 1111222233334. GoodBoy jump throws us below:
00443000   > 8D45 BC        LEA EAX,DWORD PTR SS:[EBP-44]
00443003   . 8D4D F0        LEA ECX,DWORD PTR SS:[EBP-10]
00443006   . 50             PUSH EAX
00443007   . E8 D1020500    CALL hl.004932DD
0044300C   . C645 FC 04     MOV BYTE PTR SS:[EBP-4],4
00443010   . E8 C2000000    CALL hl.004430D7
00443015   . C645 FC 01     MOV BYTE PTR SS:[EBP-4],1
00443019   . E8 C1000000    CALL hl.004430DF
0044301E   > 8B45 F0        MOV EAX,DWORD PTR SS:[EBP-10]
00443021   . 8B4D EC        MOV ECX,DWORD PTR SS:[EBP-14]
00443024   . 50             PUSH EAX
00443025   . E8 D6FCFFFF    CALL hl.00442D00
0044302A   . 85C0           TEST EAX,EAX
0044302C   . 0F85 B8000000  JNZ hl.004430EA 

This TEST EAX,EAX and CALL abowe are interesting. Tracing in we can see another length check:

00442D1C  |. 83F9 0D        CMP ECX,0D  33C0           XOR EAX,EAX
00442D38  |. 5F             POP EDI    
00442D39  . C2 0400        RETN 4

If we pass that check, we enter to serial algo routine which is very small and simple:
00401000  PUSH ESI
00401001  MOV EAX,3  31-30=1,
0040101D  |XOR EDX,EDI 

That algo will take al characters except last one. Then that summ in EAX is divided by 0Ah and we get reminder in EDX. Reminder is placed in AL then, and to EDX is placed last
00401026  MOV ECX,0A
0040102B  SUB EDX,EDX
0040102D  DIV ECX
0040102F  MOVSX EAX,DL 

And here is end. Remider must be equal to last character of serial. So my serial 111122223333(4) must be 111122223333(3) and CD key will be correct.

2. STEF2

Star Treck Elite Force 2 is shooting 3D game from 5/21/2003. Altough newer, keycheck is still very simple. Main problem would be to find actuall keycheck algorithm. Upon inserting CD and lounching installer, "CD key" dialog box shows:

Todays games/games protections create couple temp files in temp folders which are actually dllís. Some of those dllís are checking CD key. But in this example, dll that check key is ordinal dll on CD, ef2dll.dll. There is also ef2dll.ini file in same folder. This ini file just holds GoodBoy/BadBoy messages.

Easy approach for finding key routine is to attach Olly to main exe, which is probably install louncher. In this example, application gets key characters using GetWindowTextA api. After entering fake serial, Olly stopped in user32.dll on api. Returning from api brings me to subroutine which is part of another one:
00AE13B0   . 53             PUSH EBX
00AE13B1   . 56             PUSH ESI
00AE13B2   . 8B7424 0C      MOV ESI,DWORD PTR SS:[ESP+C]             ;  ef2dll.00AED059
00AE13B6   . 57             PUSH EDI
00AE13B7   . 8BF9           MOV EDI,ECX
00AE13B9   . 8D5F 5C        LEA EBX,DWORD PTR DS:[EDI+5C]
00AE13BC   . 53             PUSH EBX                                 ; /Arg3 = 0013DAE8
00AE13BD   . 68 D0070000    PUSH 7D0                                 ; |Arg2 = 000007D0
00AE13C2   . 56             PUSH ESI                                 ; |Arg1 = 0013D4BC
00AE13C3   . E8 34DC0000    CALL ef2dll.00AEEFFC                     ; ef2dll.00AEEFFC
00AE13C8   . 6A 04          PUSH 4
00AE13CA   . 53             PUSH EBX
00AE13CB   . 56             PUSH ESI
00AE13CC   . E8 7DDC0000    CALL ef2dll.00AEF04E
00AE1447   . E8 02DC0000    CALL ef2dll.00AEF04E
00AE144C   . 83C7 74        ADD EDI,74
00AE144F   . 57             PUSH EDI                                 ; /Arg3 = 0013DA8C
00AE1450   . 68 D5070000    PUSH 7D5                                 ; |Arg2 = 000007D5
00AE1455   . 56             PUSH ESI                                 ; |Arg1 = 0013D4BC
00AE1456   . E8 A1DB0000    CALL ef2dll.00AEEFFC                     ; ef2dll.00AEEFFC
00AE145B   . 68 FF000000    PUSH 0FF
00AE1460   . 57             PUSH EDI
00AE1461   . 56             PUSH ESI
00AE1462   . E8 E7DB0000    CALL ef2dll.00AEF04E
00AE1467   . 5F             POP EDI                                  ;  00159448
00AE1468   . 5E             POP ESI                                  ;  00159448
00AE1469   . 5B             POP EBX                                  ;  00159448
00AE146A   . C2 0400        RETN 4

This subroutine just collects characters from those 5 fields. And that routine is subroutine of main key check one:
00AE1620   . 83EC 0C        SUB ESP,0C
00AE1623   . 53             PUSH EBX
00AE1624   . 55             PUSH EBP
00AE1625   . 56             PUSH ESI
00AE1626   . 57             PUSH EDI
00AE1627   . 8BE9           MOV EBP,ECX
00AE1629   . 6A 01          PUSH 1
00AE162B   . C64424 17 00   MOV BYTE PTR SS:[ESP+17],0
00AE1630   . C74424 1C E8A4>MOV DWORD PTR SS:[ESP+1C],ef2dll.00AFA4E>
00AE1638   . E8 C7B90000    CALL ef2dll.00AED004 
00AE16FF   . 8BCA           MOV ECX,EDX
00AE1701   . 83E1 03        AND ECX,3
00AE1704   . F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00AE1706   . BF D8A4AF00    MOV EDI,ef2dll.00AFA4D8
00AE170B   . 83C9 FF        OR ECX,FFFFFFFF
00AE170E   . F2:AE          REPNE SCAS BYTE PTR ES:[EDI]
00AE1710   . F7D1           NOT ECX
00AE1712   . 49             DEC ECX
00AE1713   . 51             PUSH ECX
00AE1714   . E8 9A8B0000    CALL ef2dll.00AEA2B3
00AE1719   . 8BD8           MOV EBX,EAX
00AE171B   . BF D8A4AF00    MOV EDI,ef2dll.00AFA4D8
00AE1720   . 83C9 FF        OR ECX,FFFFFFFF
00AE1723   . 33C0           XOR EAX,EAX
00AE1725   . F2:AE          REPNE SCAS BYTE PTR ES:[EDI]
00AE1727   . F7D1           NOT ECX
00AE1729   . 2BF9           SUB EDI,ECX
00AE172B   . 68 D8A4AF00    PUSH ef2dll.00AFA4D8
00AE1730   . 8BC1           MOV EAX,ECX
00AE1732   . 8BF7           MOV ESI,EDI
00AE1734   . 8BFB           MOV EDI,EBX
00AE1736   . C1E9 02        SHR ECX,2
00AE1739   . F3:A5          REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
00AE173B   . 8BC8           MOV ECX,EAX
00AE173D   . 83E1 03        AND ECX,3
00AE1740   . F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00AE1742   . E8 79FEFFFF    CALL ef2dll.00AE15C0 

My serial is 11112222333344445555. In this call above, real serial will be calculated:
00AE15C0  PUSH
00AE15C9  SUB ESI,ef2dll.00AFA4C0

So correct serial is 11112222333444457EF. That check will be performed below:
00AE178F   . BF D4A4AF00   MOV EDI,ef2dll.00AFA4D4                  ;  ASCII "57ef"
00AE1794   . C1E9 02       SHR ECX,2
00AE1797   . F3:A5         REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS>
00AE1799   . 8BCA          MOV ECX,EDX
00AE179B   . 83E1 03       AND ECX,3
00AE179E   . F3:A4         REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00AE17A0   . 33F6          XOR ESI,ESI
00AE17A2   > 33C0          XOR EAX,EAX
00AE17A4   . 8A86 D4A4AF00 MOV AL,BYTE PTR DS:[ESI+AFA4D4]
00AE17AA   . 50            PUSH EAX
00AE17AB   . E8 A20F0000   CALL ef2dll.00AE2752
00AE17B0   . 8B7C24 1C     MOV EDI,DWORD PTR SS:[ESP+1C]
00AE17B4   . 33C9          XOR ECX,ECX
00AE17B6   . 83C4 04       ADD ESP,4
00AE17B9   . 8A0F          MOV CL,BYTE PTR DS:[EDI]
00AE17BB   . 47            INC EDI
00AE17BC   . 3BC1          CMP EAX,ECX  B2 01         MOV DL,1
00AE17D2   > 8BFB          MOV EDI,EBX
00AE17D4   . 83C9 FF       OR ECX,FFFFFFFF
00AE17D7   . 33C0          XOR EAX,EAX
00AE17D9   . 6A 00         PUSH 0
00AE17DD   . F7D1          NOT ECX
00AE17DF   . 2BF9          SUB EDI,ECX
00AE17E1   . 68 5C72AF00   PUSH ef2dll.00AF725C                     ;  ASCII "CD Key"
00AE17E6   . 8BC1          MOV EAX,ECX
00AE17E8   . 8BF7          MOV ESI,EDI
00AE17EA   . BF D8A4AF00   MOV EDI,ef2dll.00AFA4D8
00AE17EF   . C1E9 02       SHR ECX,2
00AE17F4   . 8BC8          MOV ECX,EAX
00AE17F6   . 83E1 03       AND ECX,3
00AE17F9   . 84D2          TEST DL,DL
00AE17FB   . F3:A4         REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00AE17FD   . 74 13         JE SHORT ef2dll.00AE1812
00AE17FF   . 8B4D 7C       MOV ECX,DWORD PTR SS:[EBP+7C]
00AE1802   . 51            PUSH ECX
00AE1803   . 8BCD          MOV ECX,EBP
00AE1805   . E8 9EB00000   CALL ef2dll.00AEC8A8  8B55 78       MOV EDX,DWORD PTR SS:[EBP+78]
00AE1815   . 8BCD          MOV ECX,EBP
00AE1817   . 52            PUSH EDX
00AE1818   . E8 8BB00000   CALL ef2dll.00AEC8A8 

As we sow, serial routine is very small and simple. It is easy to make small keygen that would give correct random keys and all games from this publisher (Activision) has similar algorithm , from older RTCW (2001) to newer Doom3 (2005).

3. FF

Freedom fighters is game from well known Electronic Arts developers. Date of game is 29-July-2003. Game has interesting registration algo, very easy to find it. In a one folder on CD, there is "Freedom Fighters_Code.exe" that is doing registration check. Running it gives registration dialog:

Finding place where serial is taken from dialog is not easy since all api's that can do that are triggered numerous times. GetWindowsTextA is api that takes serial, but I tok different approach. On "Next>" click, program shows error message giving user information that serial is invalid. I just placed bp on MessageBoxA and found routine that calls it. Then I placed bp on beggining of that procedure. Rest was easy , just tracing and I found algo. However, there is second way. This registration app uses CRC32 table while producing serial. We can simply scan app with PEiD and found where is CRC32 referenced. And all EA games have same registration scheme (that means hundreds of games).

Algo is little long so I want paste it here. I entered 1234567890ABCDEFGHIJ as serial. First algo creates CRC32 table with constants. Then it swaps places of 14 characters in my serial



It takes 13 chars from such serial and caculate some summ of it:



then is some string calculated:


which is concated to 13 char one:


On a base of that string characters, algo picks dwords from CRC32 table and calculates some summ's and then new string is created:


again attached to that 13 chars:


and chars are swaped again like first time:


And that makes valid CD key.

Algo easily can be ripped for making generic keygen. As said before, ALL EA games from that year has same register algo. I sow that in "Medal Of Honnor - Paccific Assault" , algo is little different. They probably every year change algo a little.

4. Conclusion

As you can see, it is not so hard to fish serial or to keygen some game. Some games uses Wise Installer and there serial check differ because wise installer uses scripts (.msi files). In this case finding serial can be hard but there are some decompilers like "Wise For Windows Installer" that can help.

That's it and I hope that this small tutorial will give you some pointers. Sorry for usual grammar mistakes.

Greets flies to all good peoples on this great site, to arteam comunity and to best crackmes site See you :)

haggar 22.02.2006

What's Related

Story Options

Fishing and keygenning games CD keys | 6 comments | Create New Account
The following comments are owned by whomever posted them. This site is not responsible for what they say.
Fishing and keygenning games CD keys
Authored by: highenergy on Thursday, February 23 2006 @ 08:25 PM CET
Congratulations haggar, you're the One.
Fishing and keygenning games CD keys
Authored by: Devoney on Saturday, February 25 2006 @ 10:34 AM CET
Thank you for your contibution I have just printed out your story! Gonna read it today. Grtz Devoney.

--< Share Your Knowledge >---

Fishing and keygenning games CD keys
Authored by: xor_mind on Friday, March 03 2006 @ 10:50 AM CET
Nice tut haggar. I especially like how you decided to find the algo by tracing backwards from the error message when were reverse engineering that start trek game.

Games are really large, so it is always a pain traversing the different components, its good to experiment with different possibilities.
Fishing and keygenning games CD keys
Authored by: Fredro on Friday, March 24 2006 @ 10:29 AM CET
nice one, I didn't think it was that straight farward to reverse games, but now I know, thanks mate :)
Fishing and keygenning games CD keys
Authored by: BioDuo on Friday, March 24 2006 @ 11:11 AM CET
Thanks you for you great tutorial and support!
Finally I found out how it works, thanks a lot.
 Copyright © 2021 BiW Reversing
 All trademarks and copyrights on this page are owned by their respective owners.
Powered By Geeklog 
Created this page in 0.72 seconds