Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Key Generation Knowledge Base / Forum #3

Open
CONIGUERO opened this issue Apr 12, 2023 · 48 comments
Open

Key Generation Knowledge Base / Forum #3

CONIGUERO opened this issue Apr 12, 2023 · 48 comments
Labels
question Further information is requested

Comments

@CONIGUERO
Copy link

CONIGUERO commented Apr 12, 2023

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

@Endermanch
Copy link
Owner

There is a 5-in-1 generator from MSKey for Windows 95, Windows 95 / NT 4 OEM, Windows 98, Windows 98 OEM and Windows 98 Upgrade. Even if I theoretically implemented Windows 98 generation, that would be a job for a different keygen.

image

@Endermanch Endermanch added the wontfix This will not be worked on label Apr 13, 2023
@grechnik
Copy link

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.

As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

@CONIGUERO
Copy link
Author

CONIGUERO commented May 19, 2023

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.

As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

Woah, that's amazing! Thank you!

Also, how did you calculate pri? Or did you just extract it from MSKey4in1?

@grechnik
Copy link

Or did you just extract it from MSKey4in1?

No. MSKey4in1 knows nothing about Win98, and mskey.exe from the second comment just prints some hardcoded keys for Win98 (and some of them are not even valid, using '1' or 'A').

In fact, I have implemented and run Pollard's rho for these points and curve, but I don't want to share the code.

@Endermanch
Copy link
Owner

Or did you just extract it from MSKey4in1?

No. MSKey4in1 knows nothing about Win98, and mskey.exe from the second comment just prints some hardcoded keys for Win98 (and some of them are not even valid, using '1' or 'A').

In fact, I have implemented and run Pollard's rho for these points and curve, but I don't want to share the code.

I don't remember getting any garbage keys from the mskey.exe I sent.

Why would you not want to share the code? It would be helpful, especially that you seem to know what you're talking about.

@Endermanch
Copy link
Owner

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.

As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

Acquiring the private key and the order of the curve isn't sufficient but necessary to the generation process. Surely, though, the generation algorithm itself is different.

Besides, I don't expect the Raw Product Key format to be the same either in Windows 98.

Addressing the OP's question, you clearly must have extracted the pubkey from the pIDgen.dll, which you also should have the code for.

That would be excellent learning material!

@Endermanch Endermanch reopened this May 19, 2023
@grechnik
Copy link

grechnik commented May 20, 2023

I don't remember getting any garbage keys from the mskey.exe I sent.

well, mskey.exe has 47 keys in "Windows 98 OEM" group and maybe five of them are not valid win98 keys, and "Full"/"Upgrade" groups are much smaller and fully correct, so it does take some luck (misfortune?) to get one

Besides, I don't expect the Raw Product Key format to be the same either in Windows 98.

Yet, it is literally the same except that different behaviour for ChannelID has only appeared in XP, so one does not need to worry about setting a "correct" BBB (in terms of README.md). Even the BINK resources have the same format, except that pidgen.dll was 16-bit back then, so finding the blob in the file is different - but once one finds the blob, its structure is the same (already with 32-bit fields).

Rewind to 1995. Windows 95 has just been released, product keys have no cryptographic protection, and that is sort of bad. Elliptic-curve cryptography is either a thing from frontiers of science or some lunatic math depending on your point of view. Given a problem of protecting product keys that should nevertheless be reasonably short, Microsoft Research develops a cryptographic scheme that we all know. For 1995, it makes some sense.

Fast-forward three years. Windows 98 incorporates the new scheme of cryptographically-signed product keys. Nobody cares because everyone just uses the same key. MS takes it as a sign that the scheme is good; everything else (Office/WinME/Win2k) uses the same scheme, only concrete numbers are changed (a key from win98 shouldn't be valid for win2k).

Fast-forward another three years. XP introduces WPA, nobody wants to share keys anymore (okay, that is not exactly true, but it is true enough to make a pressure to find alternate ways; and "Devil's Own" VL key was banned after all), so people actually try to make keygens. Moore's law is good, ECC slowly expands its usage and becomes better known. The scheme is still cryptographically secure in the sense that nobody knows better-than-generic-blackbox-attacks, but suddenly it turns out that the parameters are just too small, and the generic attacks are within the reach, and even in two different ways. (One way is what this repository does: blackbox discrete logarithm for n-bit groups uses O(2^(n/2)) operations, it is not too much for n=55. Another way uses the fact that the check field is 28-bit, so a random key with a correct ChannelId has probability 2^(-28) to pass the check; just keep checking random keys until one of them passes, that requires 2^28 checks per key on average - I think computers from 2001 could do that in maybe several hours per key.)

MS has noticed the keygens, but it is hard to totally redesign a cryptographic scheme on a short notice. For 2003 Server (and XP64 which is essentially 2003 Server with repainted wallpapers), they raised parameters as much as they could (and also introduced 10-bit server-auth field at expense of ChannelId that is encoded in more complicated way), which may have stopped keygenners for some time, but not forever.

In Vista, the product keys are finally checked in entirely different way, it marks the end of this story. (I have not seen any discussion on how Vista does this.) (And in Win8, MS has entirely dropped client-side crypto checks for product keys, leaving only 10-bit CRC to prevent typos and hoping for server-side checks during activation.) But before that, everything used one of two variations (XP vs 2003Server) of the same scheme where the only things that differ are concrete numbers to plug in.

@CONIGUERO
Copy link
Author

CONIGUERO commented May 20, 2023

I don't remember getting any garbage keys from the mskey.exe I sent.

well, mskey.exe has 47 keys in "Windows 98 OEM" group and maybe five of them are not valid win98 keys, and "Full"/"Upgrade" groups are much smaller and fully correct, so it does take some luck (misfortune?) to get one

Besides, I don't expect the Raw Product Key format to be the same either in Windows 98.

Yet, it is literally the same except that different behaviour for ChannelID has only appeared in XP, so one does not need to worry about setting a "correct" BBB (in terms of README.md). Even the BINK resources have the same format, except that pidgen.dll was 16-bit back then, so finding the blob in the file is different - but once one finds the blob, its structure is the same (already with 32-bit fields).

Rewind to 1995. Windows 95 has just been released, product keys have no cryptographic protection, and that is sort of bad. Elliptic-curve cryptography is either a thing from frontiers of science or some lunatic math depending on your point of view. Given a problem of protecting product keys that should nevertheless be reasonably short, Microsoft Research develops a cryptographic scheme that we all know. For 1995, it makes some sense.

Fast-forward three years. Windows 98 incorporates the new scheme of cryptographically-signed product keys. Nobody cares because everyone just uses the same key. MS takes it as a sign that the scheme is good; everything else (Office/WinME/Win2k) uses the same scheme, only concrete numbers are changed (a key from win98 shouldn't be valid for win2k).

Fast-forward another three years. XP introduces WPA, nobody wants to share keys anymore (okay, that is not exactly true, but it is true enough to make a pressure to find alternate ways; and "Devil's Own" VL key was banned after all), so people actually try to make keygens. Moore's law is good, ECC slowly expands its usage and becomes better known. The scheme is still cryptographically secure in the sense that nobody knows better-than-generic-blackbox-attacks, but suddenly it turns out that the parameters are just too small, and the generic attacks are within the reach, and even in two different ways. (One way is what this repository does: blackbox discrete logarithm for n-bit groups uses O(2^(n/2)) operations, it is not too much for n=55. Another way uses the fact that the check field is 28-bit, so a random key with a correct ChannelId has probability 2^(-28) to pass the check; just keep checking random keys until one of them passes, that requires 2^28 checks per key on average - I think computers from 2001 could do that in maybe several hours per key.)

MS has noticed the keygens, but it is hard to totally redesign a cryptographic scheme on a short notice. For 2003 Server (and XP64 which is essentially 2003 Server with repainted wallpapers), they raised parameters as much as they could (and also introduced 10-bit server-auth field at expense of ChannelId that is encoded in more complicated way), which may have stopped keygenners for some time, but not forever.

In Vista, the product keys are finally checked in entirely different way, it marks the end of this story. (I have not seen any discussion on how Vista does this.) (And in Win8, MS has entirely dropped client-side crypto checks for product keys, leaving only 10-bit CRC to prevent typos and hoping for server-side checks during activation.) But before that, everything used one of two variations (XP vs 2003Server) of the same scheme where the only things that differ are concrete numbers to plug in.

That's a nice bit of history and explanation, I appreciate the in-depth look.

However, why couldn't you want to release the code so that we can all generate keys for all editions? It would greatly improve the field and preservation ease, not having to rely on keys posted all over the place and having everything documented and easily accessible is always a plus.

@Endermanch
Copy link
Owner

I don't remember getting any garbage keys from the mskey.exe I sent.

well, mskey.exe has 47 keys in "Windows 98 OEM" group and maybe five of them are not valid win98 keys, and "Full"/"Upgrade" groups are much smaller and fully correct, so it does take some luck (misfortune?) to get one

Besides, I don't expect the Raw Product Key format to be the same either in Windows 98.

Yet, it is literally the same except that different behaviour for ChannelID has only appeared in XP, so one does not need to worry about setting a "correct" BBB (in terms of README.md). Even the BINK resources have the same format, except that pidgen.dll was 16-bit back then, so finding the blob in the file is different - but once one finds the blob, its structure is the same (already with 32-bit fields).

Rewind to 1995. Windows 95 has just been released, product keys have no cryptographic protection, and that is sort of bad. Elliptic-curve cryptography is either a thing from frontiers of science or some lunatic math depending on your point of view. Given a problem of protecting product keys that should nevertheless be reasonably short, Microsoft Research develops a cryptographic scheme that we all know. For 1995, it makes some sense.

Fast-forward three years. Windows 98 incorporates the new scheme of cryptographically-signed product keys. Nobody cares because everyone just uses the same key. MS takes it as a sign that the scheme is good; everything else (Office/WinME/Win2k) uses the same scheme, only concrete numbers are changed (a key from win98 shouldn't be valid for win2k).

Fast-forward another three years. XP introduces WPA, nobody wants to share keys anymore (okay, that is not exactly true, but it is true enough to make a pressure to find alternate ways; and "Devil's Own" VL key was banned after all), so people actually try to make keygens. Moore's law is good, ECC slowly expands its usage and becomes better known. The scheme is still cryptographically secure in the sense that nobody knows better-than-generic-blackbox-attacks, but suddenly it turns out that the parameters are just too small, and the generic attacks are within the reach, and even in two different ways. (One way is what this repository does: blackbox discrete logarithm for n-bit groups uses O(2^(n/2)) operations, it is not too much for n=55. Another way uses the fact that the check field is 28-bit, so a random key with a correct ChannelId has probability 2^(-28) to pass the check; just keep checking random keys until one of them passes, that requires 2^28 checks per key on average - I think computers from 2001 could do that in maybe several hours per key.)

MS has noticed the keygens, but it is hard to totally redesign a cryptographic scheme on a short notice. For 2003 Server (and XP64 which is essentially 2003 Server with repainted wallpapers), they raised parameters as much as they could (and also introduced 10-bit server-auth field at expense of ChannelId that is encoded in more complicated way), which may have stopped keygenners for some time, but not forever.

Could you elaborate on the server-auth (prefix) field and how it's related to the ChannelID? What exactly do you mean by more complicated encoding? I searched enough, but I couldn't find the Product ID <-> Raw Product Key relation for Server 2003, so it's still kind of a mystery. You very likely know much more.

But most importantly, Server 2003 seems to be oblivious to the prefix (that server-auth field). I tested the code with that field generated with RNG and it works about half of the times, given the high bits are set.

At first, I thought it was a SHA prefix, but if it actually serves a real purpose other than being salt, it might explain why the generation fails sometimes.

In Vista, the product keys are finally checked in entirely different way, it marks the end of this story. (I have not seen any discussion on how Vista does this.) (And in Win8, MS has entirely dropped client-side crypto checks for product keys, leaving only 10-bit CRC to prevent typos and hoping for server-side checks during activation.) But before that, everything used one of two variations (XP vs 2003Server) of the same scheme where the only things that differ are concrete numbers to plug in.

Vista abandoned the initial activation mechanism, it uses SLP 2.0 exclusively, which is rather easy to crack. People moved on from using keygens to instead emulating ACPI SLIC tables to trick Windows into thinking its activated.

//

Are there any papers/resources you could suggest on this particular topic, asides from the known MSKey 4-in-1 ReadMe? The code would MARGINALLY help too. You don't have to share it, but if you did it really would help everyone with understanding how to approach this task. Any help is appreciated!

@Endermanch Endermanch pinned this issue May 20, 2023
@grechnik
Copy link

But most importantly, Server 2003 seems to be oblivious to the prefix (that server-auth field).

That's the point. The client never checks this field. That field exists so that MS servers (mainly activation servers, maybe update center servers) can distinguish between a true key and a generated one: if there is no code in the OS, then nobody can reverse-engineer how the field is checked, so any keygen can not do better than a random guess.

On the other hand, if you don't care about MS servers, this field doesn't matter at all.

XP keys don't have this field. In the initial release of XP, activation servers happily proceeded with anything that the OS itself accepted. First keygens have shown the weakness. Then, MS presumably has built a database of MS-generated keys - maybe only new ones starting from some moment? - and made activation servers contact this database; this closed the weakness, but presumably MS wasn't too happy - maybe maintaining such a database is a pain? - and decided to implement other measures.

and it works about half of the times

You don't check the return value of BN_sqrt_mod. Half of numbers modulo a prime are not squares, so BN_sqrt_mod fails about half of the times, you should just restart with a different seed if BN_sqrt_mod returns NULL.

What exactly do you mean by more complicated encoding?

Patent US7512232: https://patents.google.com/patent/US7512232B2/en . XP keys have bitfields 1+30+28+55 for UpgradeOnly+SerialNumber+r+s, where SerialNumber is later split as ChannelId*1000000+CCCCCC, and r,s form a ECC signature. 2k3 keys have larger ECC signature and additional server-auth field, but the same length, so MS had to get creative with SerialNumber field; 2k3 bitfields are 1+10+31+62+10 for UpgradeOnly+ChannelId+r+s+ServerAuth, and the CCCCCC part is encoded inside r,s. For the details, see the patent or https://github.com/Endermanch/XPKeygen/blob/main/server.cpp in this repository.

@Endermanch
Copy link
Owner

and it works about half of the times

You don't check the return value of BN_sqrt_mod. Half of numbers modulo a prime are not squares, so BN_sqrt_mod fails about half of the times, you should just restart with a different seed if BN_sqrt_mod returns NULL.

That's what MSKey 4-in-1 stated, and that's exactly why I rerun the generator function if it returns an invalid point. Thanks for clarifying! I'm rather new to cryptography, so my intuition failed me when I thought squares should appear more often than not.

What exactly do you mean by more complicated encoding?

Patent US7512232: https://patents.google.com/patent/US7512232B2/en . XP keys have bitfields 1+30+28+55 for UpgradeOnly+SerialNumber+r+s, where SerialNumber is later split as ChannelId*1000000+CCCCCC, and r,s form a ECC signature. 2k3 keys have larger ECC signature and additional server-auth field, but the same length, so MS had to get creative with SerialNumber field; 2k3 bitfields are 1+10+31+62+10 for UpgradeOnly+ChannelId+r+s+ServerAuth, and the CCCCCC part is encoded inside r,s. For the details, see the patent or https://github.com/Endermanch/XPKeygen/blob/main/server.cpp in this repository.

I guess I just didn't get what you meant by "encoding".

A rather credible source I found today explained everything. It makes much, much more sense now.

MSKey 4in1 Readme is just completely wrong. But that's what I assumed anyway.
Thank you for explaining everything in detail. Not too happy though - I'll have to completely rewrite my Readme on the subject. Haha

The final thing I don't entirely understand is how the signature scalar cap affects the discrete logarithm computation time despite the 512-bit curve parameters. It's relatively tangent to key generation, but it might help if you do know that as well.

@Endermanch Endermanch added question Further information is requested and removed wontfix This will not be worked on labels May 20, 2023
@CONIGUERO
Copy link
Author

CONIGUERO commented May 20, 2023

and it works about half of the times

You don't check the return value of BN_sqrt_mod. Half of numbers modulo a prime are not squares, so BN_sqrt_mod fails about half of the times, you should just restart with a different seed if BN_sqrt_mod returns NULL.

That's what MSKey 4-in-1 stated, and that's exactly why I rerun the generator function if it returns an invalid point. Thanks for clarifying! I'm rather new to cryptography, so my intuition failed me when I thought squares should appear more often than not.

What exactly do you mean by more complicated encoding?

Patent US7512232: https://patents.google.com/patent/US7512232B2/en . XP keys have bitfields 1+30+28+55 for UpgradeOnly+SerialNumber+r+s, where SerialNumber is later split as ChannelId*1000000+CCCCCC, and r,s form a ECC signature. 2k3 keys have larger ECC signature and additional server-auth field, but the same length, so MS had to get creative with SerialNumber field; 2k3 bitfields are 1+10+31+62+10 for UpgradeOnly+ChannelId+r+s+ServerAuth, and the CCCCCC part is encoded inside r,s. For the details, see the patent or https://github.com/Endermanch/XPKeygen/blob/main/server.cpp in this repository.

I guess I just didn't get what you meant by "encoding".

A rather credible source I found today explained everything. It makes much, much more sense now.

MSKey 4in1 Readme is just completely wrong. But that's what I assumed anyway. Thank you for explaining everything in detail. Not too happy though - I'll have to completely rewrite my Readme on the subject. Haha

The final thing I don't entirely understand is how the signature scalar cap affects the discrete logarithm computation time despite the 512-bit curve parameters. It's relatively tangent to key generation, but it might help if you do know that as well.

Speaking of that source you found, I've been trying to find the ECDLP software program they're talking about but the link seems to be dead and the wayback machine only archived the 404 page 🤦

Might this help? https://github.com/stefan2904/ecdlp-pollard

@grechnik
Copy link

how the signature scalar cap affects the discrete logarithm computation time despite the 512-bit curve parameters

Generic algorithms for discrete logarithm are bound by the order of the group in question. (And there are no specific algorithms for a random elliptic curve.) As an extreme example, consider a group of order 3, i.e. generated by a point G with 3G=0, so the entire group is {0,G,2G}. Obviously, finding a discrete logarithm in such a group would be easy even without anything fancy regardless of how many bits coordinates of G have.

Scalar cap must be close to the group order. If you just follow the standard signing, the resulting values will be capped by the group order. If you are willing to repeat a few times and take the minimum, then you can get a better bound (and MS does this, the limit for XP-style keys being 2^55 and the order somewhere between 2^55 and 2^56), but you can't get too far without astronomical number of retries.

Number of all points on an elliptic curve modulo p is close to p. Order of any point divides number of all points, and normally one chooses a generator such that its order is not much less (in which case, bitlength of parameters indeed defines security level because it is roughly the same as the order). But that is not a requirement, all the math works even when the order is much less than the number of all points - usually this does not make much sense because you're lowering the security level, but if the security level is capped anyway, choosing larger parameters slows down an attacker (512-bit arithmetic is obviously slower than 64-bit). (Of course, it also slows down yourself by the same reason, but you might be okay with that.)

@Endermanch
Copy link
Owner

Endermanch commented May 23, 2023

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.

As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

So I did extract the curve constants from the BINK of Windows 98, calculated order of the base point and the private key. Here's what I got:

BINK header:
Operating System:	Windows 98 / XP x86
Identifier:			0x0002
sizeof(BINKEY):		364
Header Length:		7
Checksum:			0x81A195A5 (2174850469)
Creation Date:		1998-02-06 00:00:00
ECC Key Size:		384 bits (12 DWORDs)
Hash Length:		28 bits
Signature Length:	55 bits

BINK Elliptic Curve Parameters:
Finite Field Order p:
Hex: 0xF2F1C54EB7F01DED40C52AF55D4994D53D78C425292A91344D6A1D20BE292045776AC9CA3D4D2337348E2177304CC3C1
Dec: 37392568050767930319799988287205396758117017539972057881598316494924185591542182483195697473804013824755052059608001

Curve Parameter a:
Hex: 0x01
Dec: 1

Curve Parameter b:
Hex: 0x00
Dec: 0

Base Point x-coordinate Gx:
Hex: 0x541BD6F01E811D44308971A014A08DDA42F97D1F2FE0D104946D4C7E3B02583D30F6A2816BD9AF6120CC74DF0D327B51
Dec: 12945521200488607599028656523227600834645282385529945429027333942356897353457141653432411062448887162429396839725905

Base Point y-coordinate Gy:
Hex: 0xBB6EB8C546C6F1FDC55BEF78A28C6B238225F9A79C85DADF5679E251B16775EE1A44FA0FB6F7157E49DFC511B014B208
Dec: 28848503114551943942613290154239739502710619007562434518751494790901286961962988591861282401800949710517326509814280

Public Key x-coordinate Kx:
Hex: 0xD13B9794F20DFE26B8F1029330695244C3762C5F7CA58CC3DE6015967384D7C9F6618C27C34AC6DEF764AE8EE3EC25B9
Dec: 32203872504800826193860578257942098817761632037322936149898772567823772721868451723895290957871284796960470523979193

Public Key y-coordinate Ky:
Hex: 0xC055572B8B15FD56658C0BF146CBA480D8E685BCC27A8AC6269FE3B399673682046580C3C4E5E45229262CE86E792574
Dec: 29602813656567751793759332218082879597530452170215742929397002601119577441784146888237119786583675093403524212008308

Inverse coordinate of the public key -Ky:
Hex: 0x329C6E232CDA2096DB391F04167DF05464923E6866B0066E26CA396D24C1E9C37305490678673EE50B67F48EC1D39E4D
Dec: 7789754394200178526040656069122517160586565369756314952201313893804608149758035594958577687220338731351527847599693

Order of base point G, n:
Hex: 0xFD5BF182B5E5E9
Dec: 71314261946000873

Private Key:
Hex: 0x95E1A9256A0149
Dec: 42187888123314505

Private Key (calculated using inverse):
Hex: 0x677A485D4BE4A0
Dec: 29126373822686368

I did not bother extracting the second BINK, but this proves your calculated data is correct.

The check is exactly the same as in XP, only parameters are different

The algorithm seems to be different. I plugged all my calculated Windows 98 values into the XP generator function (I even tried the inverse of the Private Key), but it did not work at all. The algorithm must have been different on Windows 98, I don't have any explanation to such behavior otherwise.

image

P. S. I also tried the Server 2003 algorithm with calculated values for Windows XP x64. That failed as well.

Update (fixed)

It appears that my Windows 98 version required values from the second BINK, it worked with OEM values.
Apparently there's a clear distinction between Windows editions and BINK resources they utilize.

image

@CONIGUERO
Copy link
Author

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.
As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

So I did extract the curve constants from the BINK of Windows 98, calculated order of the base point and the private key. Here's what I got:

BINK header:
Operating System:	Windows 98 / XP x86
Identifier:			0x0002
sizeof(BINKEY):		364
Header Length:		7
Checksum:			0x81A195A5 (2174850469)
Creation Date:		1998-02-06 00:00:00
ECC Key Size:		384 bits (12 DWORDs)
Hash Length:		28 bits
Signature Length:	55 bits

BINK Elliptic Curve Parameters:
Finite Field Order p:
Hex: 0xF2F1C54EB7F01DED40C52AF55D4994D53D78C425292A91344D6A1D20BE292045776AC9CA3D4D2337348E2177304CC3C1
Dec: 37392568050767930319799988287205396758117017539972057881598316494924185591542182483195697473804013824755052059608001

Curve Parameter a:
Hex: 0x01
Dec: 1

Curve Parameter b:
Hex: 0x00
Dec: 0

Base Point x-coordinate Gx:
Hex: 0x541BD6F01E811D44308971A014A08DDA42F97D1F2FE0D104946D4C7E3B02583D30F6A2816BD9AF6120CC74DF0D327B51
Dec: 12945521200488607599028656523227600834645282385529945429027333942356897353457141653432411062448887162429396839725905

Base Point y-coordinate Gy:
Hex: 0xBB6EB8C546C6F1FDC55BEF78A28C6B238225F9A79C85DADF5679E251B16775EE1A44FA0FB6F7157E49DFC511B014B208
Dec: 28848503114551943942613290154239739502710619007562434518751494790901286961962988591861282401800949710517326509814280

Public Key x-coordinate Kx:
Hex: 0xD13B9794F20DFE26B8F1029330695244C3762C5F7CA58CC3DE6015967384D7C9F6618C27C34AC6DEF764AE8EE3EC25B9
Dec: 32203872504800826193860578257942098817761632037322936149898772567823772721868451723895290957871284796960470523979193

Public Key y-coordinate Ky:
Hex: 0xC055572B8B15FD56658C0BF146CBA480D8E685BCC27A8AC6269FE3B399673682046580C3C4E5E45229262CE86E792574
Dec: 29602813656567751793759332218082879597530452170215742929397002601119577441784146888237119786583675093403524212008308

Inverse coordinate of the public key -Ky:
Hex: 0x329C6E232CDA2096DB391F04167DF05464923E6866B0066E26CA396D24C1E9C37305490678673EE50B67F48EC1D39E4D
Dec: 7789754394200178526040656069122517160586565369756314952201313893804608149758035594958577687220338731351527847599693

Order of base point G, n:
Hex: 0xFD5BF182B5E5E9
Dec: 71314261946000873

Private Key:
Hex: 0x95E1A9256A0149
Dec: 42187888123314505

Private Key (calculated using inverse):
Hex: 0x677A485D4BE4A0
Dec: 29126373822686368

I did not bother extracting the second BINK, but this proves your calculated data is correct.

The check is exactly the same as in XP, only parameters are different

The algorithm seems to be different. I plugged all my calculated Windows 98 values into the XP generator function (I even tried the inverse of the Private Key), but it did not work at all. The algorithm must have been different on Windows 98, I don't have any explanation to such behavior otherwise.

image

P. S. I also tried the Server 2003 algorithm with calculated values for Windows XP x64. That failed as well.

Update (fixed)

It appears that my Windows 98 version required values from the second BINK, it worked with OEM values. Apparently there's a clear distinction between Windows editions and BINK resources they utilize.

image

Wow. You managed to get the ECDLP solver then... kudos. I didn't achieve it myself. Massive props!

Now for the next steps, will you add all the XP/Server 2003 editions into the keygen?

@Endermanch
Copy link
Owner

Wow. You managed to get the ECDLP solver then... kudos. I didn't achieve it myself. Massive props!

My friend nephacks did. It's pretty dang hard to find, so I uploaded the software to my website. You can download it here.
Mr. HAANDI was truly a genius for his time.

Now for the next steps, will you add all the XP/Server 2003 editions into the keygen?

I would probably go for a generalization at this point. The BINK extraction and the order of the point isn't that big of a deal. I could probably implement that myself. The only actual problem at this point is that I don't have the discrete logarithm solution code. And more importantly, if I find one - it's VERY important to parallelize that task, which requires extra work and knowledge.

@CONIGUERO
Copy link
Author

CONIGUERO commented May 24, 2023

I would probably go for a generalization at this point. The BINK extraction and the order of the point isn't that big of a deal. I could probably implement that myself. The only actual problem at this point is that I don't have the discrete logarithm solution code. And more importantly, if I find one - it's VERY important to parallelize that task, which requires extra work and knowledge.

Per my understanding of the situation, don't we already have all the pieces? E,g: with the ECDLP software, don't we already get the order and the private key? Isn't that enough to finish the keygen for all editions?
EDIT: Nevermind. The ECDLP solver doesn't give you the order of G.

As for the parallelization issue, is it really necessary? There are a total of 7 editions and 17 .pubs in XP.
From the MDL post you linked to earlier:

The private key (the scalar corresponding to K) can be recovered with a closed-source software called Mr. HAANDI's ECDLP Solver given some prep work; I am not aware of another publicly available tool that can do the same with equal efficiency. On modern hardware, this takes a few minutes.

@MeowTechOpenSource
Copy link

It would be pretty useful to know how Windows 98 (and all its editions) verifies its product keys. At first glance, it seems to be a pretty similar system to XP's. 98 seems to be an outlier in the retro Windows scene, as nobody has come up with a generator yet, whereas XP has this one and the versions before 98 use a simple algorithm with many GitHub repos implementing it, some in creative ways.

The check is exactly the same as in XP, only parameters are different:

p=0xf2f1c54eb7f01ded40c52af55d4994d53d78c425292a91344d6a1d20be292045776ac9ca3d4d2337348e2177304cc3c1
G=(0x541bd6f01e811d44308971a014a08dda42f97d1f2fe0d104946d4c7e3b02583d30f6a2816bd9af6120cc74df0d327b51,
    0xbb6eb8c546c6f1fdc55bef78a28c6b238225f9a79c85dadf5679e251b16775ee1a44fa0fb6f7157e49dfc511b014b208)
pub=(0xd13b9794f20dfe26b8f1029330695244c3762c5f7ca58cc3de6015967384d7c9f6618c27c34ac6def764ae8ee3ec25b9,
    0xc055572b8b15fd56658c0bf146cba480d8e685bcc27a8ac6269fe3b399673682046580c3c4e5e45229262ce86e792574)
order=0xFD5BF182B5E5E9
pri=0x95E1A9256A0149

for Retail keys,

p=0xec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029
G=(0xb5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340,
    0xa84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b)
pub=(0x26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811,
    0x1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2)
order=0xE778E33AEE6B3D
pri=0xB9E99B9BB9812E

for OEM keys.
As far as I know, these parameters are the same for all editions except betas. (Upgrade keys differ from normal keys by the lower bit of Product Key.)

So I did extract the curve constants from the BINK of Windows 98, calculated order of the base point and the private key. Here's what I got:

BINK header:
Operating System:	Windows 98 / XP x86
Identifier:			0x0002
sizeof(BINKEY):		364
Header Length:		7
Checksum:			0x81A195A5 (2174850469)
Creation Date:		1998-02-06 00:00:00
ECC Key Size:		384 bits (12 DWORDs)
Hash Length:		28 bits
Signature Length:	55 bits

BINK Elliptic Curve Parameters:
Finite Field Order p:
Hex: 0xF2F1C54EB7F01DED40C52AF55D4994D53D78C425292A91344D6A1D20BE292045776AC9CA3D4D2337348E2177304CC3C1
Dec: 37392568050767930319799988287205396758117017539972057881598316494924185591542182483195697473804013824755052059608001

Curve Parameter a:
Hex: 0x01
Dec: 1

Curve Parameter b:
Hex: 0x00
Dec: 0

Base Point x-coordinate Gx:
Hex: 0x541BD6F01E811D44308971A014A08DDA42F97D1F2FE0D104946D4C7E3B02583D30F6A2816BD9AF6120CC74DF0D327B51
Dec: 12945521200488607599028656523227600834645282385529945429027333942356897353457141653432411062448887162429396839725905

Base Point y-coordinate Gy:
Hex: 0xBB6EB8C546C6F1FDC55BEF78A28C6B238225F9A79C85DADF5679E251B16775EE1A44FA0FB6F7157E49DFC511B014B208
Dec: 28848503114551943942613290154239739502710619007562434518751494790901286961962988591861282401800949710517326509814280

Public Key x-coordinate Kx:
Hex: 0xD13B9794F20DFE26B8F1029330695244C3762C5F7CA58CC3DE6015967384D7C9F6618C27C34AC6DEF764AE8EE3EC25B9
Dec: 32203872504800826193860578257942098817761632037322936149898772567823772721868451723895290957871284796960470523979193

Public Key y-coordinate Ky:
Hex: 0xC055572B8B15FD56658C0BF146CBA480D8E685BCC27A8AC6269FE3B399673682046580C3C4E5E45229262CE86E792574
Dec: 29602813656567751793759332218082879597530452170215742929397002601119577441784146888237119786583675093403524212008308

Inverse coordinate of the public key -Ky:
Hex: 0x329C6E232CDA2096DB391F04167DF05464923E6866B0066E26CA396D24C1E9C37305490678673EE50B67F48EC1D39E4D
Dec: 7789754394200178526040656069122517160586565369756314952201313893804608149758035594958577687220338731351527847599693

Order of base point G, n:
Hex: 0xFD5BF182B5E5E9
Dec: 71314261946000873

Private Key:
Hex: 0x95E1A9256A0149
Dec: 42187888123314505

Private Key (calculated using inverse):
Hex: 0x677A485D4BE4A0
Dec: 29126373822686368

I did not bother extracting the second BINK, but this proves your calculated data is correct.

The check is exactly the same as in XP, only parameters are different

The algorithm seems to be different. I plugged all my calculated Windows 98 values into the XP generator function (I even tried the inverse of the Private Key), but it did not work at all. The algorithm must have been different on Windows 98, I don't have any explanation to such behavior otherwise.

image

P. S. I also tried the Server 2003 algorithm with calculated values for Windows XP x64. That failed as well.

Update (fixed)

It appears that my Windows 98 version required values from the second BINK, it worked with OEM values. Apparently there's a clear distinction between Windows editions and BINK resources they utilize.

image

Did you use a Program to extract that or you extract it yourself. I would like to get the code if it is a program

@daf-scripts
Copy link

Hey everyone wanted to jump in here with a few of my findings:

Steps I took:

  1. Downloaded all XP, Server 2003, and Home Server isos from https://files.dog/MSDN/
  2. Utilize pycdlib (https://github.com/clalancette/pycdlib ) to open each iso file and extract and files containing "pid"
  3. Expand the compressed files ending in "_"
  4. This effort can be found here https://1drv.ms/u/s!AlPIFTdGZCGGbSq5Ax3IXJpu33Q?e=b3ppx7
  5. Next utilize EllipticCurveTool (from: https://forums.mydigitallife.net/threads/elliptic-curve-product-keys.84765/page-2#post-1791162 ) to convert all the de-duplicated dll files found above into the ks2 format
  6. These ks2 files can be found https://1drv.ms/u/s!AlPIFTdGZCGGbMOLMWysalJCmZw?e=TTGiQz
  7. Next take all the dll files and use this (https://www.nirsoft.net/utils/resources_extract.html) to extract the BINK resources
  8. Utilize the BINK decoder script here (https://github.com/Endermanch/XPKeygen/blob/main/BINKReader.py) to output BINK data in txt format
  9. You can find the BINK files and the decoded data in txt format here https://1drv.ms/u/s!AlPIFTdGZCGGa1vSUlp3MnVQeK0?e=cr0qV2

I also took a stab at modifying the sage script to input the ks2 files and output the job file for Mr. HAANDI's ECDLP Solver v0.2a (can be downloaded from https://dl.malwarewatch.org/software/advanced/ecc-research-tools/ )
You can find this converter script here: https://1drv.ms/u/s!AlPIFTdGZCGGahta_OnkGk35f-E?e=U4XiVu
This has only been tested that it outputs numbers not that the numbers are correct :P

If you download all of the above you will have 24 BINKs to play with and find k and n values. Then it is just a matter of matching up the BINK with a specific iso.

Let me know if there are other file names I should look at or other iso directories!

@MeowTechOpenSource
Copy link

Is there a equivelent of PID on Office or other MS Products?

@Endermanch
Copy link
Owner

Is there a equivelent of PID on Office or other MS Products?

MSKey 4-in-1 generates Office 2003 keys. That means the algorithm must be very similar if not identical.

@Endermanch
Copy link
Owner

Endermanch commented May 28, 2023

Hey everyone wanted to jump in here with a few of my findings:

Steps I took:

  1. Downloaded all XP, Server 2003, and Home Server isos from https://files.dog/MSDN/
  2. Utilize pycdlib (https://github.com/clalancette/pycdlib ) to open each iso file and extract and files containing "pid"
  3. Expand the compressed files ending in "_"
  4. This effort can be found here https://1drv.ms/u/s!AlPIFTdGZCGGbSq5Ax3IXJpu33Q?e=b3ppx7
  5. Next utilize EllipticCurveTool (from: https://forums.mydigitallife.net/threads/elliptic-curve-product-keys.84765/page-2#post-1791162 ) to convert all the de-duplicated dll files found above into the ks2 format
  6. These ks2 files can be found https://1drv.ms/u/s!AlPIFTdGZCGGbMOLMWysalJCmZw?e=TTGiQz
  7. Next take all the dll files and use this (https://www.nirsoft.net/utils/resources_extract.html) to extract the BINK resources
  8. Utilize the BINK decoder script here (https://github.com/Endermanch/XPKeygen/blob/main/BINKReader.py) to output BINK data in txt format
  9. You can find the BINK files and the decoded data in txt format here https://1drv.ms/u/s!AlPIFTdGZCGGa1vSUlp3MnVQeK0?e=cr0qV2

I also took a stab at modifying the sage script to input the ks2 files and output the job file for Mr. HAANDI's ECDLP Solver v0.2a (can be downloaded from https://dl.malwarewatch.org/software/advanced/ecc-research-tools/ ) You can find this converter script here: https://1drv.ms/u/s!AlPIFTdGZCGGahta_OnkGk35f-E?e=U4XiVu This has only been tested that it outputs numbers not that the numbers are correct :P

If you download all of the above you will have 24 BINKs to play with and find k and n values. Then it is just a matter of matching up the BINK with a specific iso.

Let me know if there are other file names I should look at or other iso directories!

Appreciate it, man! These findings are in fact extremely helpful. I'll make sure to compile everything we found and learned into the README.md

As an exercise, you may try finding pIDgen's and BINK's inside Windows ME / Windows 2000 / Office 97 / Office 2000 / Office 2003 image files.

The image files listed in their respective order:

  1. https://dl.malwarewatch.org/windows/Windows%20ME.iso
  2. https://dl.malwarewatch.org/windows/Windows%202000.iso
    (I think I uploaded SP4 there, but it would work as a nice edge case, I bet older service packs contain exact same BINKS)
  3. https://dl.malwarewatch.org/software/useful/office/MSOffice97.zip
  4. https://dl.malwarewatch.org/software/useful/office/MSOffice2000.zip
  5. https://dl.malwarewatch.org/software/useful/office/MSOffice2003.zip

@Endermanch Endermanch changed the title Windows 98 equivalent? Key Generation Knowledge Base / Forum May 28, 2023
@Endermanch
Copy link
Owner

Did you use a Program to extract that or you extract it yourself. I would like to get the code if it is a program

Look into BINKReader.py file in this repository, I wrote it in Python.

@MeowTechOpenSource
Copy link

MeowTechOpenSource commented May 28, 2023

An interesting thought, will it be able to generate keys for Neptune, Whistler or Longhorn Builds given their PIDGENs?

@Endermanch
Copy link
Owner

An interesting thought, will it be able to generate keys for Neptune, Whistler or Longhorn Builds given their PIDGENs?

The second-generation elliptic curve license validation mechanism has been present ever since Windows 98 and hasn't been changed until Server 2003. So that's a firm yes from me.

@YoshiRulz
Copy link

Hello from HN! Wasn't expecting stuff like this to be cutting-edge, but I guess you're the first to both put in the effort and do it in public. I'd like to help if I can.

My interest in old editions of Windows is for software preservation of PC-exclusive games. Not my project, but a sister project under the umbrella of TASVideos is PCem, specifically scripting the Windows installation process in libTAS+PCem so that machine images can be reproduced without distributing copyrighted material. A big problem for us at the moment is Windows 98 keys, which are easily found online but we're keen to avoid the ire and lawyers of Big Tech.

I have some experience in C/C++, systems programming (on Linux), and reverse engineering, and I have a limited understanding of EC encryption from uni. My most relevant expertise would probably be in reproducibility, due to my knowledge of the Nix ecosystem. If you'd prefer to discuss over IM, I'm YoshiRulz#4472 on Discord.

@Hackerpcs
Copy link

Did you use a Program to extract that or you extract it yourself. I would like to get the code if it is a program

Look into BINKReader.py file in this repository, I wrote it in Python.

Which file contains the BINK on Windows 98 SE and ME?

@CONIGUERO
Copy link
Author

Did you use a Program to extract that or you extract it yourself. I would like to get the code if it is a program

Look into BINKReader.py file in this repository, I wrote it in Python.

Which file contains the BINK on Windows 98 SE and ME?

pidgen.dll

@Hackerpcs
Copy link

How to extract BINK from Win98 and WinME's pidgen.dll? Resouce Hacker that works on pidgen files from Win 2000 to Server 2003 R2 SP3 doesn't work, it says not a Win32 binary file. BINKReader.py also doesn't work as it works with BINK directly, not the dll file

@WitherOrNot
Copy link

WitherOrNot commented Jun 2, 2023

I don't have this pidgen, but maybe try to look for a BINK header in the dll with a hex editor? You should see AE DF 30 01 somewhere, this is the BINK version for Windows 98.

Then, the BINK file should start 0x10 bytes before this value, with a size of 0x170 bytes.

@Hackerpcs
Copy link

Hackerpcs commented Jun 2, 2023

Thanks, it was easy to find it with a hex editor by searching for that sequence and by also looking at a BINK hex "structure" from an XP version extracted with Resource Hacker.

@Neo-Desktop
Copy link

I loaded the 16 bit ones in ghidra and copied the hex strings of those resources into a hex editor and saved it

@Hackerpcs
Copy link

As an exercise, you may try finding pIDgen's and BINK's inside Windows ME / Windows 2000 / Office 97 / Office 2000 / Office 2003 image files.

Which files contains the BINK of Office (and also Office XP)? There doesn't seem to be a pigden.dll

@Neo-Desktop
Copy link

Neo-Desktop commented Jun 3, 2023

As an exercise, you may try finding pIDgen's and BINK's inside Windows ME / Windows 2000 / Office 97 / Office 2000 / Office 2003 image files.

Which files contains the BINK of Office (and also Office XP)? There doesn't seem to be a pigden.dll

office 2000 has pidca embedded in the msi, sometimes its not named - I'm still looking for Office 2003 and Office XP

@Hackerpcs
Copy link

Hackerpcs commented Jun 3, 2023

Let me post my findings:
Using the method from here
https://forums.mydigitallife.net/threads/elliptic-curve-product-keys.84765/page-4#post-1791679
that uses the said tool from the topic:
What works:
Win98 SE Memphis beta
Win98 SE
WinME beta
WinME
Win 2000 beta -- no key required
Win2000
win2000 Datacenter -- no key required
Neptune -- no key required
WinXP Whistler 2250 -- Same BINK as Win 2000
winXP home
winXP Pro
winXP Pro VL
winXP MCE
winXP Tablet
WinXP Fundamentals for Legacy PCs 2006
WinXP POSReady 2009
Win2k3 x86 SP3
Win2k3 x64 SP3
WinXP x64

What doesn't:
WinXP Whistler 2428 -- fails to login with both Retail/VL and also xp_activate32 with a valid key from the internet doesn't work (button and manually typing it)
WinXP Whistler 2504 -- fails to login with both Retail/VL and also xp_activate32 with a valid key from the internet doesn't work (button and manually typing it)
Longhorn everything from 3683 to before Omega 13 reset --- fails to login with both Retail/VL

More detailed:
ISOs with "=" in same line have SHA512 hash equal PIDGEN files, different lines mean different PIDGEN files but same parameters. Hash is the "p" parameter of the BINK, first one is the first one of the PIDGEN, second from OEM

Win 98 SE Memphis Win ME beta Win XP Whistler BINK ID00.ks2
Win 98 SE Memphis Win ME beta Win XP Whistler BINK ID01.ks2
93F34FD7BDC8DF <rest of it redacted>
OEM: 8CED085EB6834E <rest of it redacted>
Microsoft Windows 98 Second Edition (''Memphis'' 4.10.2120) (beta).7z
Microsoft Windows 98 Second Edition (''Memphis'' 4.10.2183A) (beta).7z
Microsoft Windows 98 Second Edition (''Memphis'' 4.10.2185) (beta).7z
Microsoft Windows ME (''Millennium'' 4.90.2380.2 B1)
Microsoft Windows ME (''Millennium'' 4.90.2419 B2)
Microsoft Windows ME (''Millennium'' 4.90.2499.3 B3)
Microsoft Windows ME (''Millennium'' 4.90.2525 RC0)
Microsoft Windows XP (''Whistler'' 5.1.2428.1 Professional B1)
Microsoft Windows XP (''Whistler'' 5.1.2504.0 Professional RC1)

Win 98 SE BINK1 ID02
Win 98 SE BINK2 ID00
F2F1C54EB7F01D <rest of it redacted>
OEM: EC224FF2613A9F <rest of it redacted>
Microsoft Windows 98 Second Edition [Greek] (OEM) (ISO)

Win Me BINK1 ID1C
Win Me BINK2 ID00
F1AF939098E965 <rest of it redacted>
OEM: B4EAB97C6DEB7D <rest of it redacted>
Microsoft Windows ME [Greek] (OEM) (ISO)

Win 2000 Pro SP3 BINK ID12.ks2
Win 2000 Pro SP3 OEM BINK ID13.ks2
85FC84B75ACF83 <rest of it redacted>
OEM: D33D46BCF4B09C <rest of it redacted>
Windows 2000 Professional With Service Pack 3 OEM Greek (FFFFFFFF) = Windows 2000 Professional (OEM) [Greek] (ISO) SP0 (FFFFFFFF) win 2000 pro GR PIDGEN

Win 2000 Datacenter BINK ID0A.ks2
F197163D2F8C82 <rest of it redacted>
OEM: same as "Win 2000 Pro SP3 OEM BINK ID13.ks2"
Microsoft Windows 2000 Datacenter (5.00.2195.6717.sp4)5.00.2195.6717_x86fre_DTCServer_en-us PIDGEN.DLL

Win XP Home SP3 BINK ID2A.ks2
Win XP Home SP3 OEM BINK ID2B.ks2
C6DF4AADAD63FC <rest of it redacted>
OEM: 991C0E04D13B28 <rest of it redacted>
en_windows_xp_home_with_service_pack_3_x86_cd_x14-92413 = el_windows_xp_home_with_service_pack_3_x86_cd_x14-92417

Win XP Pro SP3 BINK ID2C.ks2
Win XP Pro SP3 OEM BINK ID2D.ks2
9E9C1B126AF9F2 <rest of it redacted>
OEM: DFB971F2B49B5E <rest of it redacted>
en_windows_xp_professional_with_service_pack_3_x86_cd_x14-80428 PIDGEN.DLL
el_windows_xp_professional_with_service_pack_3_x86_cd_x14-80448 PIDGEN.DLL
en_winxp_mce_2005_cd1 = en_winxp_tablet_2005_cd1 PIDGEN

Win XP Pro SP3 VL BINK ID2E.ks2
Win XP Pro SP3 VL OEM BINK ID2F.ks2
92DDCF14CB9E71 <rest of it redacted>
OEM: B211C74AF6A89D <rest of it redacted>
en_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-73974 PIDGEN.DLL
el_windows_xp_professional_with_service_pack_3_x86_cd_vl_x14-73988 PIDGEN.DLL
en_win_xp_tabletpc_2005_disc1_vl PIDGEN
SW_CD_SA_Win_Fundamentals_LPC_2006_English_MultiLang_WinFLp_Core_CD_MLF_X12-27765

Win XP POSReady 2009 Product ID 620 BINK ID0D
8A257D5BD5C995 <rest of it redacted>
OEM: no OEM, it only contains one BINK
en_windows_embedded_posready_2009_x86_dvd_283454 pidgen

@WitherOrNot
Copy link

I generated an interesting key for Longhorn 4074: CB2DK-H2CFP-WY9YK-X4C7H-QV4B3

Supposedly, this key has an "infinite" evaluation period (pid 105):

{
	"index": 7,
	"bink": "00000074",
	"pid_range": [
		105,
		105
	],
	"type": "Evaluation",
	"days_to_activate": 0,
	"days_evaluation": 2147483647
}

I set the date a year forward and I can still login, but I have no idea if this is because of the key or not.

@MeowTechOpenSource
Copy link

I generated an interesting key for Longhorn 4074: CB2DK-H2CFP-WY9YK-X4C7H-QV4B3

Supposedly, this key has an "infinite" evaluation period (pid 105):

{
	"index": 7,
	"bink": "00000074",
	"pid_range": [
		105,
		105
	],
	"type": "Evaluation",
	"days_to_activate": 0,
	"days_evaluation": 2147483647
}

I set the date a year forward and I can still login, but I have no idea if this is because of the key or not.

WinXP x64, Win2k3 x86 SP3, Win2k3 x64 SP3, Longhorn everything from 3683 to before Omega 13 reset --- unsolvable Server 2003 SP3 type BINK

How do you generate LH keys?

@WitherOrNot
Copy link

WitherOrNot commented Jun 5, 2023

I will PR support for x64/Longhorn/Server key generation to Neo-Desktop/WindowsXPKg once @Endermanch finishes refactoring.

For the impatient, here is my testing Jupyter notebook:

https://gist.github.com/WitherOrNot/e2f1f4a6b17a7ffcd7e2426c75bc2278

You will need an installation of SageMath to use it.

@MeowTechOpenSource
Copy link

I will PR support for x64/Longhorn/Server key generation to Neo-Desktop/WindowsXPKg once @Endermanch finishes refactoring.

For the impatient, here is my testing Jupyter notebook:

https://gist.github.com/WitherOrNot/e2f1f4a6b17a7ffcd7e2426c75bc2278

You will need an installation of SageMath to use it.

Thanks. I would like to know is k and n value Found by the solver app? We can extract the other value but not these.

@Neo-Desktop
Copy link

For the record, none of these keys are unsolvable

They may take up to about 20 minutes

But if there are any that are more intensive, version 0.3a of the solver is GPU/CUDA assisted

@WitherOrNot
Copy link

v0.3a CUDA is not usable, its CUDA SDK is too old for modern GPUs...

@Endermanch
Copy link
Owner

I will PR support for x64/Longhorn/Server key generation to Neo-Desktop/WindowsXPKg once @Endermanch finishes refactoring.

For the impatient, here is my testing Jupyter notebook:

https://gist.github.com/WitherOrNot/e2f1f4a6b17a7ffcd7e2426c75bc2278

You will need an installation of SageMath to use it.

Thanks. I would like to know is k and n value Found by the solver app? We can extract the other value but not these.

Read the README file.

@Neo-Desktop
Copy link

v0.3a CUDA is not usable, its CUDA SDK is too old for modern GPUs...

unrelated and off topic:

@WitherOrNot: I went ahead and sent you a signed email regarding communication outside of GitHub
just wondering if you got it and if you're interested feel free to respond to it (:

@WitherOrNot
Copy link

Thanks! Just sent my response

@Hackerpcs
Copy link

For the record, none of these keys are unsolvable

They may take up to about 20 minutes

But if there are any that are more intensive, version 0.3a of the solver is GPU/CUDA assisted

This is correct, Server 2003 R2 x86 worked in ~5-10 minutes with ECDLP Solver v0.2a on a 5600x with PBO on, to be honest I saw

For some reason, I also failed to calculate the Windows Server 2003 base point order using SageMath. I gave it 12 hours to compute on my i7-12700K, but it was still stuck calculating.

in the readme and didn't even try. I will try more "unsolvable" from above and will edit my comment

@Neo-Desktop
Copy link

For what its worth, keys.json in the WindowsXPKg repo has everything precalculated, if we're missing BINKs just tell us where to find them and we'll get them calculated

@ess7
Copy link

ess7 commented Apr 15, 2024

I can't prove it but I'm the author of xpkey and win2k3key on AntiWPA.

Back in 2002 there was a Slashdot article about a Windows XP keygen by TheBlueList. Someone posted a base64 encoded .zip of the .exe if you want to try it out (good old days when a keygen can fit in a comment and not removed as spam). It was slow so I figured it was using some kind of brute force.

bluelist

I eventually reversed the keygen (found the IDA .idb created Aug 2003). I was studying elliptic curves at that time so it was nice to find ECC in the XP product key. The signature verification was not something familiar, it probably took a week before I found it by chance in the Handbook of Applied Cryptography as the Schnorr signature. At that time they did not know the private key, thus the brute force approach. It was done by fixing a random signature then trying different PID values until the 28-bit hash matched.

At this point I had a clone of TheBlueList keygen using my own ECC library and GMP.

The private key seemed feasible to solve given the small order of the subgroup. The basic (non-parallel) Pollard's rho algorithm is simpler than the keygen, just 114 SLOC excluding the ECC library. The group order was found on my home PC; the private key on an internet cafe where I left the program running and got the result the next day (sorry). My keygen was updated to use the private key for signing instead of bruteforcing the hash.

I sat on this for ~3 years until around 2006 when I first discussed my work on the AntiWPA forum. The old forum is gone but some of it got archived. That was the first time I became aware of MSKey4in1. My 2003 keygen was based on the README (I probably copied the EC parameters/private key from the .exe). I got in contact with cw2k who suggested to upload the XP and 2003 keygen sources on AntiWPA. I rewrote it to use OpenSSL instead of my ECC library.

cw2k was also working on the beta version of Vista's pidgenx.dll but it was obfuscated. Speculation from PDB strings suggest the algorithm is a pairing-based short signature, confirmed here.

If you read this thread, apologies for the unreadable code that looks like compiler optimizations.

@qtqgyt
Copy link

qtqgyt commented Nov 18, 2024

Can someone help a simple minded idiot like me EXACTLY understand the 98 key algorithm?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

12 participants