Compare commits

..

7 Commits

Author SHA1 Message Date
Andrew 87f567b602
Add more Python utilities 2023-07-05 15:02:36 +03:00
Andrew 4350242e41
Update README.md 2023-06-25 02:01:11 +03:00
Andrew e82c530910 Version 2.7 2023-06-25 01:43:51 +03:00
Andrew cefd2151d0 stopAudio() 2023-06-25 01:42:21 +03:00
Andrew e92e19757c Merge branch 'main' of https://github.com/Endermanch/XPKeygen 2023-06-25 01:41:01 +03:00
Andrew 0756a807b8 BINK Preset Upgrade 2023-06-25 01:40:50 +03:00
Andrew 24df6464d1
Add files via upload 2023-06-23 22:03:39 +03:00
26 changed files with 738 additions and 314 deletions

View File

@ -97,7 +97,7 @@
<ClCompile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<ExceptionHandling>Sync</ExceptionHandling>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<Optimization>Disabled</Optimization>
@ -184,6 +184,7 @@
<SubSystem>Console</SubSystem>
<AdditionalManifestDependencies>"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
<RegisterOutput>true</RegisterOutput>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
@ -274,13 +275,13 @@
<SubSystem>Windows</SubSystem>
<AdditionalManifestDependencies>"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
<EntryPointSymbol>wWinMainCRTStartup</EntryPointSymbol>
<RegisterOutput>true</RegisterOutput>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<Media Include="resources\neon.wav" />
<Media Include="resources\pxiii.wav" />
</ItemGroup>
<ItemGroup>
@ -293,12 +294,14 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\header.h" />
<ClInclude Include="src\presets.h" />
<ClInclude Include="src\resource.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\bink.cpp" />
<ClCompile Include="src\key.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\presets.cpp" />
<ClCompile Include="src\server.cpp" />
<ClCompile Include="src\utilities.cpp" />
<ClCompile Include="src\windows.cpp" />
@ -307,6 +310,16 @@
<ItemGroup>
<ResourceCompile Include="src\resource.rc" />
</ItemGroup>
<ItemGroup>
<None Include="resources\bink\BINK2003.bin" />
<None Include="resources\bink\BINK2003OEM.bin" />
<None Include="resources\bink\BINK98SE.bin" />
<None Include="resources\bink\BINK98SEOEM.bin" />
<None Include="resources\bink\BINKXP.bin" />
<None Include="resources\bink\BINKXP64.bin" />
<None Include="resources\bink\BINKXP64OEM.bin" />
<None Include="resources\bink\BINKXPOEM.bin" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -10,33 +10,39 @@
<Filter Include="Resources">
<UniqueIdentifier>{8c8a7e56-fe48-4168-8eb0-0715690de23e}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\BINK">
<UniqueIdentifier>{f5cd78be-da1c-4cfe-a3b9-56a21fefadf4}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\Bitmaps">
<UniqueIdentifier>{7847a032-b440-4d10-a8a6-ed1b9cb62197}</UniqueIdentifier>
</Filter>
<Filter Include="Resources\Wave">
<UniqueIdentifier>{198e89a5-06ad-4790-bfaa-1e59588bf2d2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Media Include="resources\neon.wav">
<Filter>Resources</Filter>
</Media>
<Media Include="resources\pxiii.wav">
<Filter>Resources</Filter>
<Filter>Resources\Wave</Filter>
</Media>
</ItemGroup>
<ItemGroup>
<Image Include="resources\ender.bmp">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\icon.ico">
<Filter>Resources</Filter>
</Image>
<Image Include="resources\logo.bmp">
<Filter>Resources</Filter>
<Image Include="resources\dropdown.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\ender.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\musicoff.bmp">
<Filter>Resources</Filter>
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\musicon.bmp">
<Filter>Resources</Filter>
<Filter>Resources\Bitmaps</Filter>
</Image>
<Image Include="resources\dropdown.bmp">
<Filter>Resources</Filter>
<Image Include="resources\logo.bmp">
<Filter>Resources\Bitmaps</Filter>
</Image>
</ItemGroup>
<ItemGroup>
@ -46,6 +52,9 @@
<ClInclude Include="src\resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\presets.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\windows.cpp">
@ -69,10 +78,39 @@
<ClCompile Include="src\utilities.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\presets.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="src\resource.rc">
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="resources\bink\BINK98SE.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK98SEOEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK2003.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINK2003OEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP64.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXP64OEM.bin">
<Filter>Resources\BINK</Filter>
</None>
<None Include="resources\bink\BINKXPOEM.bin">
<Filter>Resources\BINK</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -2,7 +2,7 @@
A Windows XP / Windows Server 2003 VLK key generator. This tool allows you to generate _valid Windows XP keys_ based on the _Raw Product Key_, which can be random.
The **Raw Product Key (RPK)** is supplied in form of 9 digits `XXX-YYYYYY` and is only necessary to generate a Windows XP Key.
![Enderman's Keygen](https://github.com/Endermanch/XPKeygen/assets/44542704/bd76ea6a-8bab-4892-8f0a-0cafe529763f)
![XP Keygen](https://github.com/Endermanch/XPKeygen/assets/44542704/dd545c2d-6643-4812-8c41-1b94e1fb0f07)
### Download
@ -301,18 +301,18 @@ but the algorithm is well-documented. The implementation in my case generates ab
I will add more decent reads into the bibliography in later releases.
**Understanding basics of Windows XP Activation**:
* [[1] Inside Windows Product Activation - Fully Licensed](https://www.licenturion.com/xp/fully-licensed-wpa.txt) | [archive.org](https://web.archive.org/web/20230620124157/https://www.licenturion.com/xp/fully-licensed-wpa.txt)
* [[2] MSKey 4-in-1 ReadMe](https://malwarewatch.org/documents/MSKey4in1.pdf) | [archive.org](https://archive.org/details/217618817-mskey-4in-1-read-me)
* [[3] Windows序列号产生原理(椭圆曲线法)](https://blog.csdn.net/zhiyuan411/article/details/5156330) | [archive.org](https://web.archive.org/web/20230523202310/https://blog.csdn.net/zhiyuan411/article/details/5156330)
* [[1] Inside Windows Product Activation - Fully Licensed](https://www.licenturion.com/xp/fully-licensed-wpa.txt)
* [[2] MSKey 4-in-1 ReadMe](https://malwarewatch.org/documents/MSKey4in1.pdf)
* [[3] Windows序列号产生原理(椭圆曲线法)](https://blog.csdn.net/zhiyuan411/article/details/5156330)
**Understanding Elliptic Curve Cryptography**:
* [[4] Elliptic Curve Cryptography for Beginners - Matt Rickard](https://matt-rickard.com/elliptic-curve-cryptography) | [archive.org](https://web.archive.org/web/20230608071430/https://matt-rickard.com/elliptic-curve-cryptography)
* [[5] Elliptic Curve Cryptography (ECC) - Practical Cryptography for Developers](https://cryptobook.nakov.com/asymmetric-key-ciphers/elliptic-curve-cryptography-ecc) | [archive.org](https://web.archive.org/web/2/https://cryptobook.nakov.com/asymmetric-key-ciphers/elliptic-curve-cryptography-ecc)
* [[6] A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography - Cloudflare](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/) | [archive.org](https://web.archive.org/web/20230609014138/https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/)
* [[4] Elliptic Curve Cryptography for Beginners - Matt Rickard](https://matt-rickard.com/elliptic-curve-cryptography)
* [[5] Elliptic Curve Cryptography (ECC) - Practical Cryptography for Developers](https://cryptobook.nakov.com/asymmetric-key-ciphers/elliptic-curve-cryptography-ecc)
* [[6] A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography - Cloudflare](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/)
**Public discussions**:
* [[7] Windows 98 Equivalent // Server 2003 Algorithm](https://github.com/Endermanch/XPKeygen/issues/3) | [archive.org](https://web.archive.org/web/2/https://github.com/Endermanch/XPKeygen/issues/3)
* [[8] Cracking Windows XP](https://forums.mydigitallife.net/threads/is-there-any-way-to-crack-decrypt-the-winxp-consumer-activation-system-to-generate-activation-ids.80133/) | [archive.org](https://web.archive.org/web/20230613025511/https://forums.mydigitallife.net/threads/is-there-any-way-to-crack-decrypt-the-winxp-consumer-activation-system-to-generate-activation-ids.80133/)
* [[7] Windows 98 Equivalent // Server 2003 Algorithm](https://github.com/Endermanch/XPKeygen/issues/3)
* [[8] Cracking Windows XP](https://forums.mydigitallife.net/threads/is-there-any-way-to-crack-decrypt-the-winxp-consumer-activation-system-to-generate-activation-ids.80133/)
## Contributing / Usage
**If you're going to showcase or fork this software, please credit Endermanch, z22 and MSKey**.<br>

99
Vista+.md Normal file
View File

@ -0,0 +1,99 @@
## 6. Product ID
Product ID is 5 groups of decimals, e.g.:
```
AAAAA BBB CCCCCCC DD EEE
52273 005 6861993 09 146
```
If you search `ProductID` in registry, you will find a product ID associated with your currently installed one.
The meaning of each group of numbers:
| Number | Meaning |
| --------- | ----------------------------------------------------------------------------------------------- |
| `AAAAA` | Product code. e.g.: `55661` for Windows Pro; `55660` for Windows Home. |
| `BBB` | First 3 effective number digits of Primary Product Serial. |
| `CCCCCCC` | Last 6 effective number digits of Primary Product Serial, and a digit of checksum. |
| `DD` | Public key index number for product validation. e.g.: Pro is 22, VLK is 23. |
| `EEE` | Nonce (random number), for generating different install ID when doing activation via telephone. |
For `CCCCCCC` mentioned above, it had two parts including 1 digit and 6 digits. The checksum is calculated as follows: **Add all digits together (including the checksum digit), it is divisible by 7.**
For example: the last 6 digits of Primary Product Serial is `728439`, then `7 + 2 + 8 + 4 + 3 + 9 = 33` , then the checksum digit should be `2`, because `7 + 2 + 8 + 4 + 3 + 9 + 2 = 33 + 2 = 35`, and 35 is divisible by 7. So the `CCCCCCC` in Product ID should be `7284392`.
## 7. OEM related mechanism
<!-- Oh boy this section is a total mess... The original content itself is confusing as hell.. -->
For licensed product to OEMs, starting from Windows XP, Microsoft is using SLP (System-Locked Preinstallation) technology, aka.: before installing the OS, lock in the motherboard with the OS. Windows XP used SLP 1.0, it works by detecting specific string set by OEM in BIOS. This method is easy to be spoofed, but the VLK crack is more easy to use so this method is not wide-spread.
From the Windows Vista, SLP upgraded to 2.0 . Primarily the change is using cryptographic key pairs to sign the data to prevent spoofing. This requires a special SLIC (Software Licensing Internal Code) table in BIOS to support this.
In Windows 7 series of product, SLP 2.1 is used, but there is no major changes in SLP for this revision, only updated the marker in SLIC to 2.1 .
SLIC is the important part of SLP, usually directly backed in BIOS ROM, as the most underlying information of OS activation. SLIC contains the digital signature of OEM, when OS is activating, the upper level certificate must can be verified with the OEM information inside SLIC. SLIC usually contained inside SLDT(Software Licensing Description Table), which 374 bytes long, and SLDT itself is contained inside ACPI(Advanced Configuration and Power Management Interface).
OEM certificate is a certification file provided by Microsoft, including to some mandatory information provided by OEM, the extension for the file is `xrm-ms`. The OEM certificate including the OEM identification information and digitally signed by Microsoft. When OS is activating, the OEM certificate must can be validated against SLIC.
OEM product key seems no difference with retail product key, but OEM key is only valid for OEM activation, and it identifies the Windows product variation. Windows Vista cancelled the VLK model, only OEM activation is provided, and used SLP 2.0, used public key instead plain text for validation, caused difficulties for cracking.
### Windows Vista (SLP 2.0)
<!-- Following procedure is for SLP 2.0, which is for Windows Vista. -->
The procedure for SLP 2.0 verification is as follows:
1. When installing Windows Vista, retail version user need to input the serial (CD-KEY) presented on the box. For users who got the OEM version of Windows Vista with the computer, they can find a sticker that corresponding the version they got with the computer, as a voucher for purchasing the Windows Vista OEM version. The system identifies different versions of Windows Vista based on their serial numbers, such as Home Basic, Home Advanced, Business, Ultimate, and so on. After installation, the serial number is converted into 4 sets of letters or numbers, which is the "Product ID" shown in the "System Properties". The second group is the "OEM" one, which is the serial number (CD-KEY) of the OEM version. From now on, the product ID replaces the CD-KEY <!-- as user inputted their retail CD-KEY on the box, this OEM product ID became the CD-KEY in this case -->, and the installer generates an OEM certificate for the OEM version of the installation <!-- "product certificate" maybe? And, installed to where? usually the installation is done by OEM. The information is conflicting with the "OEM certificate is a certification file provided by Microsoft" mentioned above. -->.
2. The information in the BIOS got loaded into RAM every time system boots.
3. After logging into the Windows Vista, OS calls SLP service to check the licensed rights of running product, especially the activation status. It starts to identify the licensing status of the system based on the product ID. If no product ID is detected or no valid retail version product ID is detected, it is considered as inactivated. If a valid retail version product ID is detected, it is considered successfully activated. If an OEM version of the product ID is detected, continue with the OEM verification.
4. If the OEM product ID is detected, the OEM verification process starts, and it will check the installed OEM certificate <!-- "product certificate" ? --> is valid. It mainly uses the SLIC public key from BIOS which is loaded into the RAM, to verify the digital signature of product certificate <!-- Yes, this "product certificate" came from nowhere, so I guess this the OEM certificate that installed while installing the Windows Vista by OEM. -->. If validation failed, it is considered as inactivated.
5. Verify the OEM ID field between SLIC and RSDT (Root System Description Table), and compare the OEM ID field and OEM Table ID fields between SLIC and XSDT (Extended System Description Table). If they didn't match, it is considered as inactivated.
6. After the above hurdles, the OEM license will be considered as activated. If not then fallback to inactivated and continue with normal procedure, like require user to activate the Windows.
### Windows 7 (SLP 2.1)
<!-- Following procedure is for SLP 2.1, which is for Windows 7. -->
Windows 7 still retains the OEM activation policy, but using SLP 2.1 instead.
Here is more detailed verification process:
1. After the activation process starts, if the correct SLP Key is detected, the OEM activation process starts, otherwise the WPA activation (online or telephone activation) is performed.
2. Detect the OEM certificate <!-- "product certificate" ? -->, and use the digital signature inside the OEM certificate to validate the it (Microsoft used their private key to sign the OEM certificate, and verified against the public key), if verified then continue on OEM activation process, otherwise continue on WPA activation process.
3. Compare the OEM public key, OEM ID and various fields with the information presented in the OEM certificate <!-- "product certificate" ? -->. If they match (this means OEM public key and etc. are correct), then continue on OEM activation process, otherwise continue on WPA activation process.
4. Use OEM public key verify against the digital signature of the Marker inside SLIC. if verified (this means the Message in the Marker is correct. <!-- There is no where talked about what is that Message and Marker. -->) then continue on OEM activation process, otherwise continue on WPA activation process.
5. Verify the Windows Logo <!-- I guess? "Windows Logo" part can be directly translate to "Windows Flag Mark", and this "Flag" means that actual waving thing, not a digital bit. I guess this approach is similar as the Nintendo logo bitmap inside Game Boy game cartridge ROM thing. --> inside the Marker. If the Windows Logo is present, then continue on OEM activation process, otherwise continue on WPA activation process.
6. Verify the version of Marker. If it's at least `0x20001` then continue on OEM activation process, otherwise OEM activation failed, and continue on WPA activation process.
7. Compare the OEM ID and OEM Table ID against all corresponding ACPI table headers. If they match, then OEM activation completed successfully, otherwise continue on WPA activation process.
Key points (Not containing all details, this info is only there to emphasize the key points of Microsoft encryption):
1. OEM certificate <!-- "product certificate" ? --> contains
- Data (OEM ID and other information, Microsoft public key, etc.)
- Hash (Hash of data)
- Signature (Hash were signed with Microsoft private key)
2. SLIC contains:
- Data (OEM ID, Marker version, etc., Microsoft public key, etc.)
- Hash (Hash the data)
- Signature (Hash were signed with Microsoft private key)
3. First, use the public key to verify whether the signatures of OEM and SLIC, then, compare the OEM ID, public key and other information in OEM and SLIC to see whether they are the same; verify the Marker version is matching the type of system currently installed.
* * *
Oh boy what a mess...
This source is from CSDN.net, and this is a known "copy paste and profit" site that infamous in China.
This article is old enough that the author is actually had integrity and cited all the actual juicy sources. However, all the actual juicy sources were long gone, because the BBS that the author cited is downonly unusable archives were left (reported by discord member @itsmefeng ).
This article isn't providing enough information on how to crack the Windows Vista/7 activation process. We may need more actual good sources for this.
For better understanding I provided some comment (as HTML comments for Markdown compatibility). Hopefully it will be useful.
-- Some Anonymous Person

BIN
resources/bink/BINK2003.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
resources/bink/BINK98SE.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
resources/bink/BINKXP.bin Normal file

Binary file not shown.

BIN
resources/bink/BINKXP64.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -3,63 +3,56 @@
//
#include "header.h"
#define BINK_RETAIL MAKEINTRESOURCEW(1)
#define BINK_OEM MAKEINTRESOURCEW(2)
#define RT_BINK L"BINK"
#include "resource.h"
#include "presets.h"
/*
Bink resource doesn't exist
The file you selected isn't a library
Bink resource is invalid
*/
typedef struct _EC_BYTE_POINT {
CHAR x[256]; // x-coordinate of the point on the elliptic curve.
CHAR y[256]; // y-coordinate of the point on the elliptic curve.
} EC_BYTE_POINT;
typedef struct _BINKHDR {
// BINK version - not stored in the resource.
ULONG32 dwVersion;
/*BOOL SelectPreset(int nIndex) {
if (nIndex >= WCOUNT) return false;
// Original BINK header.
ULONG32 dwID;
ULONG32 dwSize;
ULONG32 dwHeaderLength;
ULONG32 dwChecksum;
ULONG32 dwDate;
ULONG32 dwKeySizeInDWORDs;
ULONG32 dwHashLength;
ULONG32 dwSignatureLength;
strcpy(pBINKPreset.p, p[nIndex]);
strcpy(pBINKPreset.a, a);
strcpy(pBINKPreset.b, b);
strcpy(pBINKPreset.G.x, gx[nIndex]);
strcpy(pBINKPreset.G.y, gy[nIndex]);
strcpy(pBINKPreset.K.x, kx[nIndex]);
strcpy(pBINKPreset.K.y, ky[nIndex]);
// Extended BINK header. (Windows Server 2003+)
ULONG32 dwAuthCodeLength;
ULONG32 dwProductIDLength;
} BINKHDR;
pBINKPreset.I.x;
pBINKPreset.I.y;
typedef struct _BINKDATA {
CHAR p[256]; // Finite Field order p.
CHAR a[256]; // Elliptic Curve parameter a.
CHAR b[256]; // Elliptic Curve parameter b.
pBINKPreset.n = n[nIndex];
pBINKPreset.k = k[nIndex];
EC_BYTE_POINT G; // Base point (Generator) G.
EC_BYTE_POINT K; // Public key K.
EC_BYTE_POINT I; // Inverse of the public key K.
} BINKDATA;
return true;
}*/
typedef struct _BINKEY {
BINKHDR header;
BINKDATA data;
} BINKEY;
BOOL CALLBACK EnumResourceProc(HMODULE hModule, CONST WCHAR *lpType, WCHAR *lpName, LONG_PTR lParam) {
(*(UINT *)lParam)++;
DWORD extractBINKResource(HMODULE hLibrary, BYTE **pData) {
HRSRC hRes = FindResourceW(hLibrary, BINK_OEM, RT_BINK);
return TRUE;
}
UINT countResources(WCHAR *pName) {
UINT nResources = 0;
EnumResourceNamesW(NULL, pName, EnumResourceProc, (LONG_PTR)&nResources);
return nResources;
}
DWORD extractBINKResource(HMODULE hModule, UINT nPreset, BYTE **pMemory) {
HRSRC hRes = FindResourceW(hModule, MAKEINTRESOURCEW(nPreset), RT_BINK);
DWORD dwSize = 0;
if (hRes != NULL) {
dwSize = SizeofResource(hLibrary, hRes);
*pData = (BYTE *)LoadResource(hLibrary, hRes);
dwSize = SizeofResource(hModule, hRes);
*pMemory = (BYTE *)LoadResource(hModule, hRes);
}
return dwSize;
@ -75,64 +68,135 @@ BYTE hexToDecDigit(CHAR nDigit) {
return nDigit - 'A' + 10;
}
ULONG32 byteToInteger(BYTE *pByte) {
return hexToDecDigit(pByte[0]) << 4 + hexToDecDigit(pByte[1]);
void reverseBytes(BYTE *pBytes) {
UINT nBytes = strlen((CHAR *)pBytes) / 2;
CHAR *pBytesCopy = strdup((CHAR *)pBytes);
for (int i = 0; i < nBytes; i++) {
memcpy(&pBytes[(nBytes - (i + 1)) * 2], &pBytesCopy[i * 2], 2 * sizeof(BYTE));
}
free(pBytesCopy);
}
void reverseBytes(CONST BYTE *pBytes, ULONG32 nBytes, BYTE *pReversed) {
for (int i = nBytes - 1; i >= 0; i--) {
memcpy((BYTE *)&pBytes[i * 2], (BYTE *)&pReversed[(nBytes - i + 1) * 2], 2 * sizeof(BYTE));
VOID byteToHex(BYTE *pDestination, BYTE pByte) {
BYTE loByte = pByte % 16,
hiByte = pByte / 16;
pDestination[0] = hiByte < 10 ? hiByte + '0' : hiByte + 'A' - 10;
pDestination[1] = loByte < 10 ? loByte + '0' : loByte + 'A' - 10;
}
VOID formatBytes(BYTE *pDestination, BYTE *pSource, UINT nLength) {
for (int i = 0; i < nLength; i++) {
byteToHex(pDestination + i * 2, pSource[i]);
}
}
ULONG32 ulToInteger(BYTE *pUL, BOOL bLittleEndian) {
BYTE pULCopy[8] = { 0 };
ULONG32 nUL = 0;
BOOL decodeBINKResource(BYTE *pData, ULONG32 nLength, BINKEYEX *pBINK) {
ULONG32 nStructOffset,
nCurveOffset,
nCurveField = FIELD_BYTES_2003;
if (pUL == NULL)
return 0;
// If BINK is incomplete or the containers are null pointers, return.
if (pData == nullptr || pBINK == nullptr || nLength < 0x170) return false;
if (bLittleEndian)
reverseBytes(pUL, 4, pULCopy);
// Reset structure to 0.
memset(pBINK, 0, sizeof(BINKEYEX));
for (int i = 0; i < 4; i++) {
nUL += byteToInteger(&pULCopy[i * 2]);
// Read ID and the BINK header.
for (nStructOffset = 0; nStructOffset < sizeof(ULONG32) + sizeof(BINKHDR); nStructOffset += sizeof(ULONG32)) {
*(ULONG32 *)((BYTE *)pBINK + nStructOffset) = BYDWORD(pData + nStructOffset);
}
return nUL;
}
// If it's an older BINK, there are only 7 arguments.
if (pBINK->binKey.header.dwVersion == 19980206) {
pBINK->binKey.header.dwProductIDLength = 0;
pBINK->binKey.header.dwAuthCodeLength = 0;
void decodeBINKResource(BYTE *pData, ULONG32 nLength, BINKEY *pBINK) {
ULONG32 nBlockBytes = 4;
nCurveField = FIELD_BYTES;
}
// If BINK is incomplete, return.
if (nLength < 0x170) return;
for (nCurveOffset = (pBINK->binKey.header.dwHeaderLength + 1) * sizeof(ULONG32); nStructOffset < sizeof(ULONG32) + sizeof(BINKDATA); nStructOffset += FIELD_LENGTH_MAX, nCurveOffset += nCurveField) {
BYTE *pCurveParameter = (BYTE *)pBINK + nStructOffset;
ulToInteger(pData, TRUE);
formatBytes(pCurveParameter, pData + nCurveOffset, nCurveField);
reverseBytes(pCurveParameter);
}
/*/ Read BINK header.
for (ULONG32 nOffset = 0; nOffset < sizeof(BINKHDR); nOffset += nBlockBytes) {
pBINK[nOffset] =
// Calculate the inverse of the public key.
// The elliptic curve is symmetric about the x axis, so we only need to calculate the y-coordinate.
// I.y = p - K.y
BIGNUM *fieldOrder = BN_new(),
*publicKeyY = BN_new();
BN_hex2bn(&fieldOrder, pBINK->binKey.data.p);
BN_hex2bn(&publicKeyY, pBINK->binKey.data.K.y);
BN_sub(publicKeyY, fieldOrder, publicKeyY);
CHAR *pInverse = BN_bn2hex(publicKeyY);
strcpy(pBINK->I.x, pBINK->binKey.data.K.x);
strcpy(pBINK->I.y, pInverse);
free(pInverse);
// Additional calculations (not implemented yet)
BIGNUM *derivative = BN_new();
BIGNUM *generatorx = BN_new();
BIGNUM *generatory = BN_new();
BN_CTX *ctx = BN_CTX_new();
BN_hex2bn(&generatorx, pBINK->binKey.data.G.x);
BN_hex2bn(&generatory, pBINK->binKey.data.G.y);
/*EC_POINT *genPoint, *pubPoint, *genDerivative;
EC_GROUP *eCurve = initializeEllipticCurve(
pBINK->data.p,
pBINK->data.a,
pBINK->data.b,
pBINK->data.G.x,
pBINK->data.G.y,
pBINK->data.K.x,
pBINK->data.K.y,
&genPoint,
&pubPoint
);
genDerivative = EC_POINT_new(eCurve);
EC_POINT_copy(genDerivative, genPoint);
for (ULONG64 iter = 0; iter != 65153636961774397; iter++) {
printf("iter: %llu\n", iter);
EC_POINT_add(eCurve, genDerivative, genPoint, genDerivative, ctx);
}*/
return true;
}
void base(WCHAR *pPath) {
HMODULE pIDgen = LoadLibraryExW(pPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
VOID InitializePreset(UINT nIndex, BINKEYEX *pBINK) {
/* HMODULE pIDgen = LoadLibraryExW(pPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (pIDgen == NULL)
return;
return;*/
BYTE *pBuffer = NULL;
ULONG32 nLength = extractBINKResource(pIDgen, &pBuffer);
BYTE *pMemory = NULL;
ULONG32 nLength = extractBINKResource(NULL, IDR_BINK1 + nIndex, &pMemory);
if (nLength == 0) {
return;
}
BINKEY pBINK = { 0 };
decodeBINKResource(pMemory, nLength, pBINK);
decodeBINKResource(pBuffer, nLength, &pBINK);
pBINK->n = generatorOrderArr[nIndex];
pBINK->k = privateKeyArr[nIndex];
FreeLibrary(pIDgen);
// FreeLibrary(pIDgen);
return;
}

View File

@ -18,6 +18,7 @@
#pragma warning(disable: 6387)
// Arithmetic macros
#define PK_LENGTH 25
#define NULL_TERMINATOR 1
@ -27,9 +28,14 @@
#define FIELD_BITS_2003 512
#define FIELD_BYTES_2003 (FIELD_BITS_2003 / 8)
#define FIELD_BITS_MAX FIELD_BITS_2003
#define FIELD_BYTES_MAX FIELD_BYTES_2003
#define SHA_MSG_LENGTH_XP (4 + 2 * FIELD_BYTES)
#define SHA_MSG_LENGTH_2003 (3 + 2 * FIELD_BYTES_2003)
#define FIELD_LENGTH_MAX (FIELD_BYTES_MAX * 2 + NULL_TERMINATOR)
#define NEXTSNBITS(field, n, offset) (((QWORD)(field) >> (offset)) & ((1ULL << (n)) - 1))
#define FIRSTNBITS(field, n) NEXTSNBITS((field), (n), 0)
@ -37,8 +43,10 @@
#define LOBYTES(field, bytes) FIRSTNBITS((QWORD)(field), ((bytes) * 8))
#define BYDWORD(n) (DWORD)(*((n) + 0) | *((n) + 1) << 8 | *((n) + 2) << 16 | *((n) + 3) << 24)
#define BYDWORDBE(n) (DWORD)(*((n) + 3) | *((n) + 2) << 8 | *((n) + 1) << 16 | *((n) + 0) << 24)
#define BITMASK(n) ((1ULL << (n)) - 1)
// Control macros
#define IDC_BUTTON1 1000
#define IDC_BUTTON2 1001
#define IDC_BUTTON3 1002
@ -67,17 +75,70 @@
#define IDC_LABEL5 1109
#define IDC_LABEL6 1110
// Resource macros
#define BINK_RETAIL MAKEINTRESOURCEW(1)
#define BINK_OEM MAKEINTRESOURCEW(2)
#define RT_BINK TEXT("BINK")
// Type definitions
typedef uint64_t QWORD;
extern char pCharset[];
// Structures
typedef struct _EC_BYTE_POINT {
CHAR x[FIELD_LENGTH_MAX]; // x-coordinate of the point on the elliptic curve.
CHAR y[FIELD_LENGTH_MAX]; // y-coordinate of the point on the elliptic curve.
} EC_BYTE_POINT;
typedef struct _BINKHDR {
// Original BINK header.
ULONG32 dwSize;
ULONG32 dwHeaderLength;
ULONG32 dwChecksum;
ULONG32 dwVersion;
ULONG32 dwKeySizeInDWORDs;
ULONG32 dwHashLength;
ULONG32 dwSignatureLength;
// Extended BINK header. (Windows Server 2003+)
ULONG32 dwAuthCodeLength;
ULONG32 dwProductIDLength;
} BINKHDR, *PBINKHDR;
typedef struct _BINKDATA {
CHAR p[FIELD_LENGTH_MAX]; // Finite Field order p.
CHAR a[FIELD_LENGTH_MAX]; // Elliptic Curve parameter a.
CHAR b[FIELD_LENGTH_MAX]; // Elliptic Curve parameter b.
EC_BYTE_POINT G; // Base point (Generator) G.
EC_BYTE_POINT K; // Public key K.
} BINKDATA, *PBINKDATA;
typedef struct _BINKEY {
BINKHDR header;
BINKDATA data;
} BINKEY, *PBINKEY;
typedef struct _BINKEYEX {
// ID of the BINK. (Separate from the BINKEY structure per spec)
ULONG32 dwID;
// BINKEY structure.
BINKEY binKey;
// Calculated values.
EC_BYTE_POINT I; // Inverse of the public key K.
QWORD n; // Order of the generator G.
QWORD k; // Private Key k.
} BINKEYEX, *PBINKEYEX;
extern BINKEYEX pBINKPreset;
extern CHAR pCharset[];
extern const char pXP[];
extern const long aXP;
extern const long bXP;
// xp.cpp
VOID unpackXP(
QWORD(&pRaw)[2],
QWORD (&pRaw)[2],
BOOL &pUpgrade,
DWORD &pChannelID,
DWORD &pSequence,
@ -106,7 +167,8 @@ VOID generateXPKey(
);
BOOL keyXP(
CHAR(&pKey)[PK_LENGTH + NULL_TERMINATOR],
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
@ -152,6 +214,7 @@ VOID generateServerKey(
BOOL keyServer(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
@ -166,15 +229,13 @@ void stopAudio();
bool playAudio(HINSTANCE hInstance, WCHAR *lpName, UINT bFlags);
EC_GROUP *initializeEllipticCurve(
const char *pSel,
long aSel,
long bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
BIGNUM *genOrderSel,
BIGNUM *privateKeySel,
CONST CHAR *pSel,
CONST CHAR *aSel,
CONST CHAR *bSel,
CONST CHAR *generatorXSel,
CONST CHAR *generatorYSel,
CONST CHAR *publicKeyXSel,
CONST CHAR *publicKeyYSel,
EC_POINT **genPoint,
EC_POINT **pubPoint
);
@ -195,6 +256,7 @@ bool InitializeWindow(HINSTANCE hInstance);
// bink.cpp
void base(WCHAR *pPath);
VOID InitializePreset(UINT nIndex, BINKEYEX *pBINK);
UINT countResources(WCHAR *pName);
#endif //KEYGEN_HEADER_H

View File

@ -87,7 +87,7 @@ void formatXP(BOOL bUpgrade, WCHAR *pBSection, WCHAR *pCSection, WCHAR *pText) {
DWORD nChannelID = wcstoul(pBSection, nullptr, 10),
nSequence = wcstoul(pCSection, nullptr, 10);
BOOL bValid = keyXP(pKey, nChannelID, nSequence, bUpgrade);
BOOL bValid = keyXP(pKey, pBINKPreset, nChannelID, nSequence, bUpgrade);
QWORD pRaw[2]{},
pSignature;
@ -131,7 +131,7 @@ void formatServer(BOOL bUpgrade, WCHAR *pBSection, WCHAR *pAuthSection, WCHAR *p
DWORD nChannelID = wcstoul(pBSection, nullptr, 10);
DWORD nAuthInfo = wcstoul(pAuthSection, nullptr, 0) % 0x400;
BOOL bValid = keyServer(pKey, nChannelID, nAuthInfo, bUpgrade);
BOOL bValid = keyServer(pKey, pBINKPreset, nChannelID, nAuthInfo, bUpgrade);
QWORD pRaw[2]{},
pSignature;

View File

@ -61,12 +61,15 @@
#include "header.h"
char pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
BINKEYEX pBINKPreset;
CHAR pCharset[] = "BCDFGHJKMPQRTVWXY2346789";
INT wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ WCHAR *pCmdLine, _In_ INT nCmdShow) {
srand(GetTickCount64());
//base(L"D:\\Desktop\\ECC Research\\pIDgen\\pidgenxp.dll");
InitializePreset(2, &pBINKPreset);
return InitializeWindow(hInstance);
// don't forget to free bink presets (I Forgor)
}

23
src/presets.cpp Normal file
View File

@ -0,0 +1,23 @@
#include "presets.h"
const unsigned long long generatorOrderArr[] = {
71314261946000873,
65153636961774397,
61760995553426173,
62443961168019161,
5532044755580494717,
4755964586330124773,
4710798293276956193,
5152953887135671777,
};
const unsigned long long privateKeyArr[] = {
42187888123314505,
52329725233299758,
24306963676698312,
32781177223842894,
2739897280441110808,
174180799641457829,
11731326262766101,
1583498175279647618,
};

27
src/presets.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
enum VERSIONS {
W98SE,
W98SEOEM,
WXP,
WXPOEM,
WSERVER2003,
WXP64,
WXP64OEM,
WCOUNT
};
extern const wchar_t *pPresets[256];
extern const char *p[256];
extern const char *a;
extern const char *b;
extern const char *gx[256];
extern const char *gy[256];
extern const char *kx[256];
extern const char *ky[256];
extern const unsigned long long generatorOrderArr[];
extern const unsigned long long privateKeyArr[];

View File

@ -10,6 +10,15 @@
#define IDB_BITMAP4 106
#define IDB_BITMAP5 107
#define IDR_BINK1 1001
#define IDR_BINK2 1002
#define IDR_BINK3 1003
#define IDR_BINK4 1004
#define IDR_BINK5 1005
#define IDR_BINK6 1006
#define IDR_BINK7 1007
#define IDR_BINK8 1008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED

Binary file not shown.

View File

@ -4,66 +4,6 @@
#include "header.h"
/* Windows Server 2003 */
const char pSv[] = "C9AE7AED19F6A7E100AADE98134111AD8118E59B8264734327940064BC675A0C682E19C89695FBFA3A4653E47D47FD7592258C7E3C3C61BBEA07FE5A7E842379";
const long aSv = 1;
const long bSv = 0;
// Base point G (Generator)
const char genXSv[] = "85ACEC9F9F9B456A78E43C3637DC88D21F977A9EC15E5225BD5060CE5B892F24FEDEE574BF5801F06BC232EEF2161074496613698D88FAC4B397CE3B475406A7";
const char genYSv[] = "66B7D1983F5D4FE43E8B4F1E28685DE0E22BBE6576A1A6B86C67533BF72FD3D082DBA281A556A16E593DB522942C8DD7120BA50C9413DF944E7258BDDF30B3C4";
// Inverse of the public key
const char pubXSv[] = "90BF6BD980C536A8DB93B52AA9AEBA640BABF1D31BEC7AA345BB7510194A9B07379F552DA7B4A3EF81A9B87E0B85B5118E1E20A098641EE4CCF2045558C98C0E";
const char pubYSv[] = "6B87D1E658D03868362945CDD582E2CF33EE4BA06369E0EFE9E4851F6DCBEC7F15081E250D171EA0CC4CB06435BCFCFEA8F438C9766743A06CBD06E7EFB4C3AE";
// Order of G <- from MSKey 4-in-1
const char genOrderSv[] = "4CC5C56529F0237D";
// Computed private key
const char privateKeySv[] = "2606120F59C05118";
/* Windows XP x64
Public key (-K) = (1989960177638374390878377737764297057685259206834686428253479199374616869742150776410973898745805799780071536831208959469038333664656928533078897351495263; 2680493145252003995204016438404731303203625133293449171132691660710342616258476835192643732221910418645447349019141673820306444587247165566828458285756618)
Order of base point G (n) = 4710798293276956193
Private key (k) = 4699066967014190092 for INVERSE. 11731326262766101
const char pSv[] = "D4B49D04A01EF209121C370DCF0D6292569EC65B8F147A8C62319B6B90DEA2D1CD45199B93582732BFEE27F40BF62D7EB2559BCD08041E301E0D14037A25D989";
const long aSv = 1;
const long bSv = 0;
const char genXSv[] = "828A23E65A03F2CE12342DC2B3AA4089C1447DD5C4DC36C0470885A4662F10187037F72B2216C3F671B434267A329BD3363BB27055F0EBBA8A0ABEF451D3F6A3";
const char genYSv[] = "23B0823295C9CB669E1643B298624083F68C58F14FEEC55D0B247EF37B353A1066F502D7BC71050056C7D006156A26CC9222F5135FB8B255D7773AE0CDCA31E2";
const char pubXSv[] = "25FEB90513F63C0833F1096369149E65C9359F4BCC8DE9A8F647030F96485BC71929594FF369DB967910B8F0A59BC7C30CF0D38311486293BA0B2952EE648E5F";
const char pubYSv[] = "A186A2C2913E5584F05E97D3CD49E354E6C41BE329877D7FCC7B2BF877A0B00C9298901D305D7FF012FF7902B4202D4ED64D6A90C6AD05960253BAB8F69D68BF";
// Order of G <- CALCULATED ON MY i7-12700K in 20 seconds
const char genOrderSv[] = "41601E16BF4A1621";
// Computed private key <- CALCULATED ON MY i7-12700K in 5 minutes 40 seconds
const char privateKeySv[] = "29AD943EA2EA15"; */
/* Windows XP x64 OEM
const char pSv[] = "A6FEDE9568C7863685F783F864A5943D34DED45EC460EEB2EC0455B01BC3C4D21FE081E479F2338BAAF7B10903AC89D23774938F41FDBFB6F16A615ECE5A04A1";
const long aSv = 1;
const long bSv = 0;
const char genXSv[] = "3CCFE20244697894A5CF8F8A57F335462C8C7C4935E171A373C2C1BA85C304D121A48931A99E4DD911945B410E10DEF21C00B2ED33FEF4E8F6FCBE16014E0AA8";
const char genYSv[] = "7D3F4583D6A45EF6547532B2AE6AC83281317A212223A47ADA92FB48DF055A225DD3E8DF17850EBFAD744780C8166B14F0A39C96B3D216E2247A89518985F6F8";
const char pubXSv[] = "19D3C8A75DACEAB3CE42970BCF3097F712FD3F6D3B171BE55D7AEF6210C48194480E998AFAC181935DCB9E66BD23769AF5E7ABB8ED2A7E5FAABD4FD1F8D24F7C";
const char pubYSv[] = "47A138CDB3C51BEB5443A00FD24734C6DE5DCE6DBA3B2EC337984C09B1CB108E45E8B50F78AEE5FBCA068C0B285576AC26099BD4D52AE2AF9F32A30A340705AF";
// Order of G <- CALCULATED ON MY i7-12700K in 2 hours (single threaded).
const char genOrderSv[] = "4782F84242B0A5E1";
// Computed private key <- CALCULATED ON MY i7-12700K in 5 minutes 40 seconds
const char privateKeySv[] = "15F9B7336005CB82";// or "3189410EE2AADA5F";
*/
/* Unpacks the Windows Server 2003-like Product Key. */
VOID unpackServer(
QWORD (&pRaw)[2],
@ -219,6 +159,30 @@ BOOL verifyServerKey(
// Truncate the hash to 31 bits.
DWORD compHash = BYDWORD(msgDigest) & BITMASK(31);
#ifdef _DEBUG
printf(
"Validating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n AuthInfo: 0x%03lX\n\n Hash: 0x%08lX\n Computed Hash: 0x%08lX\n Signature: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pAuthInfo,
pHash,
compHash,
BN_bn2hex(s)
);
printf(
" K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n",
BN_bn2hex(x),
BN_bn2hex(y)
);
printf(
" compHash %s pHash (%s)\n\n\n",
compHash == pHash ? "==" : "!=",
compHash == pHash ? "VALID" : "INVALID"
);
#endif
BN_free(s);
BN_free(e);
BN_free(x);
@ -386,6 +350,27 @@ VOID generateServerKey(
// Pack product key.
packServer(pRaw, pUpgrade, pChannelID, pHash, pSignature, pAuthInfo);
#ifdef _DEBUG
printf(
"Generating a Server 2003-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n AuthInfo: 0x%03lX\n\n Generator Order: 0x%s\n Private Key: 0x%s\n Seed: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pAuthInfo,
BN_bn2hex(genOrder),
BN_bn2hex(privateKey),
BN_bn2hex(c)
);
printf(
" R(x; y) = {\n 0x%s,\n 0x%s\n }\n\n Signature bits: %02d (%s)\n BN_mod_sqrt(Intermediate): %s\n\n\n",
BN_bn2hex(x),
BN_bn2hex(y),
BN_num_bits(s),
BN_num_bits(s) <= 62 ? "GOOD" : "BAD",
noSquare ? "False" : "True"
);
#endif
EC_POINT_free(r);
} while (pSignature > BITMASK(62) || noSquare);
// ↑ ↑ ↑
@ -406,6 +391,7 @@ VOID generateServerKey(
BOOL keyServer(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nAuthInfo,
BOOL bUpgrade
@ -414,23 +400,29 @@ BOOL keyServer(
if (nChannelID >= 1'000)
return false;
if (pBINK.n == 0 ||
pBINK.k == 0) {
#ifdef _DEBUG
printf("!! NOT IMPLEMENTED !!\n\n");
#endif
return false;
}
BIGNUM *privateKey = BN_new();
BIGNUM *genOrder = BN_new();
BN_hex2bn(&privateKey, privateKeySv);
BN_hex2bn(&genOrder, genOrderSv);
BN_set_word(privateKey, pBINK.k);
BN_set_word(genOrder, pBINK.n);
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve = initializeEllipticCurve(
pSv,
aSv,
bSv,
genXSv,
genYSv,
pubXSv,
pubYSv,
genOrder,
privateKey,
pBINK.binKey.data.p,
pBINK.binKey.data.a,
pBINK.binKey.data.b,
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
&genPoint,
&pubPoint
);
@ -441,9 +433,23 @@ BOOL keyServer(
nAuthInfo &= 0x3FF;
}
do {
generateServerKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nAuthInfo, bUpgrade, pKey);
} while (!verifyServerKey(eCurve, genPoint, pubPoint, pKey));
#ifdef _DEBUG
printf(
"Created elliptic curve:\n\n E = EllipticCurve(\n GF(0x%s),\n [0, 0, 0, %d, %d]\n ) => y^2 = x^3 + %dx + %d;\n\n G(x; y) = {\n 0x%s,\n 0x%s\n }\n\n K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n AuthInfo: 0x%03lX\n\n\n",
pBINK.binKey.data.p,
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
nAuthInfo
);
#endif
return true;
generateServerKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nAuthInfo, bUpgrade, pKey);
return verifyServerKey(eCurve, genPoint, pubPoint, pKey);
}

View File

@ -43,57 +43,54 @@ bool playAudio(HINSTANCE hInstance, WCHAR *lpName, UINT bFlags) {
/* Initializes the elliptic curve. */
EC_GROUP *initializeEllipticCurve(
const char *pSel,
long aSel,
long bSel,
const char *generatorXSel,
const char *generatorYSel,
const char *publicKeyXSel,
const char *publicKeyYSel,
BIGNUM *genOrderSel,
BIGNUM *privateKeySel,
CONST CHAR *pSel,
CONST CHAR *aSel,
CONST CHAR *bSel,
CONST CHAR *generatorXSel,
CONST CHAR *generatorYSel,
CONST CHAR *publicKeyXSel,
CONST CHAR *publicKeyYSel,
EC_POINT **genPoint,
EC_POINT **pubPoint
) {
// Initialize BIGNUM and BIGNUMCTX structures.
// BIGNUM - Large numbers
// BIGNUMCTX - Context large numbers (temporary)
// BN_CTX - Context variables (allow concurrency)
BIGNUM *a, *b, *p, *generatorX, *generatorY, *publicKeyX, *publicKeyY;
BN_CTX *context;
// Microsoft Product Key identification program uses a public key stored in pidgen.dll's BINK resource,
// which is an Elliptic Curve Cryptography (ECC) public key. It can be decomposed into a following mathematical task:
// We're presented with an elliptic curve, a multivariable function y(x; p; a; b), where
// y^2 % p = x^3 + ax + b % p.
// We're presented with an elliptic curve, a multivariable function F(y; x; p; a; b), where
// y^2 = x^3 + ax + b (mod p).
a = BN_new();
b = BN_new();
p = BN_new();
// Public key will consist of the resulting (x; y) values.
// K(x; y) is the resulting point.
publicKeyX = BN_new();
publicKeyY = BN_new();
// G(x; y) is a generator function, its return value represents a point on the elliptic curve.
// G(x; y) is the base point.
generatorX = BN_new();
generatorY = BN_new();
// Context variable
// Context variable.
context = BN_CTX_new();
/* Public data */
// Initialize public data from the BINK resource.
BN_hex2bn(&p, pSel);
BN_set_word(a, aSel);
BN_set_word(b, bSel);
BN_hex2bn(&a, aSel);
BN_hex2bn(&b, bSel);
BN_hex2bn(&generatorX, generatorXSel);
BN_hex2bn(&generatorY, generatorYSel);
BN_hex2bn(&publicKeyX, publicKeyXSel);
BN_hex2bn(&publicKeyY, publicKeyYSel);
/* Elliptical Curve calculations. */
// The group is defined via Fp = all integers [0; p - 1], where p is prime.
// The function EC_POINT_set_affine_coordinates() sets the x and y coordinates for the point p defined over the curve given in group.
// Elliptic Curve calculations.
// The abelian group is defined via Galois field Fp - all integers [0; p - 1], where p is prime.
EC_GROUP *eCurve = EC_GROUP_new_curve_GFp(p, a, b, context);
// Create new point for the generator on the elliptic curve and set its coordinates to (genX; genY).
@ -108,7 +105,7 @@ EC_GROUP *initializeEllipticCurve(
assert(EC_POINT_is_on_curve(eCurve, *genPoint, context) == 1);
assert(EC_POINT_is_on_curve(eCurve, *pubPoint, context) == 1);
// Cleanup
// Cleanup.
BN_CTX_free(context);
return eCurve;

View File

@ -13,18 +13,28 @@
HWND hMainWindow;
const WCHAR *pAboutLink = L"https://github.com/Endermanch/XPKeygen",
CONST WCHAR *pAboutLink = L"https://github.com/Endermanch/XPKeygen",
*pWebsite = L"https://malwarewatch.org",
*pVersion = L"2.5",
*pTitle = L"Windows XP Pro SP3 // Server 2003 SP0 x86 VLK - Enderman[ch]",
*pGroupTitle = L"Windows XP Pro SP3 // Server 2003 SP0 x86 VLK",
*pRBText = L"z22 / MSKey / Endermanch ◄ 14/06/2023";
*pVersion = L"2.7",
*pTitle = L"Windows 98 - Windows Server 2003 / SP2 x64 VLK - Enderman[ch]",
*pGroupTitle = L"Windows 98 - Windows Server 2003 / SP2 x64 VLK",
*pRBText = L"z22 / MSKey / Endermanch ◄ 25/06/2023",
*pPresets[256] = {
L"Windows 98",
L"Windows 98 (OEM)",
L"Windows XP VLK",
L"Windows XP VLK (OEM)",
L"Windows Server 2003 VLK",
L"Windows Server 2003 VLK (OEM)",
L"Windows XP x64 Edition VLK",
L"Windows XP x64 Edition VLK (OEM)",
};
bool bServer = false,
BOOL bServer = false,
bUpgrade = false,
bMusic = true;
const int w = 615,
CONST INT w = 615,
h = 545,
x = (GetSystemMetrics(SM_CXSCREEN) - w) / 2,
y = (GetSystemMetrics(SM_CYSCREEN) - h) / 2;
@ -543,27 +553,27 @@ LRESULT CALLBACK WNDProc(HWND hWindow, UINT uMessage, WPARAM wParam, LPARAM lPar
case IDC_COMBO1:
switch (HIWORD(wParam)) {
case CBN_SELCHANGE:
int nSelect = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
case CBN_SELCHANGE: {
UINT nPresetSelect = SendMessageW((HWND)lParam, CB_GETCURSEL, 0, 0);
switch (nSelect) {
case 0:
InitializePreset(nPresetSelect, &pBINKPreset);
if (pBINKPreset.binKey.header.dwVersion == 19980206) {
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT2), true);
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT3), false);
bServer = false;
break;
case 1:
}
else {
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT2), false);
EnableWindow(GetDlgItem(hMainWindow, IDC_INPUT3), true);
bServer = true;
break;
}
break;
}
}
break;
@ -867,10 +877,11 @@ bool InitializeWindow(HINSTANCE hInstance) {
SendMessageW(hComboBox, WM_SETFONT, (WPARAM)hLabelFont, 0);
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)L"Windows XP (SP0 - SP3)");
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)L"Windows Server 2003 (SP0)");
for (int i = 0; i < countResources(RT_BINK); i++) {
SendMessageW(hComboBox, CB_ADDSTRING, 0, (LPARAM)pPresets[i]);
}
SendMessageW(hComboBox, CB_SETCURSEL, 0, 0);
SendMessageW(hComboBox, CB_SETCURSEL, 2, 0);
HWND hUpgrade = CreateWindowExW(
WS_EX_WINDOWEDGE,
@ -1040,7 +1051,8 @@ bool InitializeWindow(HINSTANCE hInstance) {
HWND hAuthInfoLabel = CreateWindowExW(
0,
L"Static", L"AuthInfo:",
L"Static",
L"AuthInfo:",
WS_CHILD | WS_VISIBLE,
290, 220 + 1,
70, 16,

View File

@ -4,46 +4,6 @@
#include "header.h"
/* Windows XP */
const char pXP[] = "92ddcf14cb9e71f4489a2e9ba350ae29454d98cb93bdbcc07d62b502ea12238ee904a8b20d017197aae0c103b32713a9";
const long aXP = 1;
const long bXP = 0;
// Base point G (Generator)
const char genXXP[] = "46E3775ECE21B0898D39BEA57050D422A0AF989E497962BAEE2CB17E0A28D5360D5476B8DC966443E37A14F1AEF37742";
const char genYXP[] = "7C8E741D2C34F4478E325469CD491603D807222C9C4AC09DDB2B31B3CE3F7CC191B3580079932BC6BEF70BE27604F65E";
// The public key
const char pubXXP[] = "5D8DBE75198015EC41C45AAB6143542EB098F6A5CC9CE4178A1B8A1E7ABBB5BC64DF64FAF6177DC1B0988AB00BA94BF8";
const char pubYXP[] = "23A2909A0B4803C89F910C7191758B48746CEA4D5FF07667444ACDB9512080DBCA55E6EBF30433672B894F44ACE92BFA";
// The order of G was computed in 18 hours using a Pentium III 450
const char genOrderXP[] = "DB6B4C58EFBAFD";
// The private key was computed in 10 hours using a Pentium III 450
const char privateKeyXP[] = "565B0DFF8496C8";
/* Windows 98
const char pXP[] = "ec224ff2613a9fe1411b51e89634643f79a272402ee146b012a3f71098c7e75df4bf8b3713c4f0ce56691ce56b9b5029";
const long aXP = 1;
const long bXP = 0;
// Base point G (Generator)
const char genXXP[] = "b5e1957b19951b5523204a62fd83ab22056f59a13bf8aaaf16ac10b7540f8ea92ba28dbfa68996fa12510c024f912340";
const char genYXP[] = "a84fbc02f311b1fd4521773e01821bd047f067c496ad54ce1504315cb88667d69130caa25efb2cb1e479ed50efb40d6b";
// The public key
const char pubXXP[] = "26ea9efe57ab6da485225a13ed66533c143f81b7b9528e38c8568bb726a8f0f5607da0e8d85aebf2e1425758b409e811";
const char pubYXP[] = "1a7c4cebe5f3919e96876a447a813efcd920979e9610d2b2146a04fab1041b31ae65e24efa3e0b0d61622483655716c2";
// The order of G was computed in 18 hours using a Pentium III 450
const char genOrderXP[] = "E778E33AEE6B3D";
// The private key was computed in 10 hours using a Pentium III 450
const char privateKeyXP[] = "B9E99B9BB9812E"; // "677A485D4BE4A0";*/
/* Unpacks a Windows XP-like Product Key. */
VOID unpackXP(
QWORD (&pRaw)[2],
@ -172,6 +132,30 @@ BOOL verifyXPKey(
// Truncate the hash to 28 bits.
DWORD compHash = BYDWORD(msgDigest) >> 4 & BITMASK(28);
#ifdef _DEBUG
printf(
"Validating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n Sequence: %d\n\n Hash: 0x%08lX\n Computed Hash: 0x%08lX\n Signature: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pSequence,
pHash,
compHash,
BN_bn2hex(s)
);
printf(
" K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n",
BN_bn2hex(x),
BN_bn2hex(y)
);
printf(
" compHash %s pHash (%s)\n\n\n",
compHash == pHash ? "==" : "!=",
compHash == pHash ? "VALID" : "INVALID"
);
#endif
BN_free(e);
BN_free(s);
BN_free(x);
@ -277,6 +261,26 @@ VOID generateXPKey(
// Pack product key.
packXP(pRaw, pUpgrade, pChannelID, pSequence, pHash, pSignature);
#ifdef _DEBUG
printf(
"Generating an XP-like key using following values:\n\n Upgrade: %s\n Channel ID: %d\n Sequence: %d\n\n Generator Order: 0x%s\n Private Key: 0x%s\n Seed: 0x%s\n\n",
pUpgrade ? "True" : "False",
pChannelID,
pSequence,
BN_bn2hex(genOrder),
BN_bn2hex(privateKey),
BN_bn2hex(c)
);
printf(
" R(x; y) = {\n 0x%s,\n 0x%s\n }\n\nSignature bits: %02d (%s)\n\n\n",
BN_bn2hex(x),
BN_bn2hex(y),
BN_num_bits(s),
BN_num_bits(s) <= 55 ? "GOOD" : "BAD"
);
#endif
EC_POINT_free(r);
} while (pSignature > BITMASK(55));
// ↑ ↑ ↑
@ -296,6 +300,7 @@ VOID generateXPKey(
BOOL keyXP(
CHAR (&pKey)[PK_LENGTH + NULL_TERMINATOR],
BINKEYEX &pBINK,
DWORD nChannelID,
DWORD nSequence,
BOOL bUpgrade
@ -304,30 +309,49 @@ BOOL keyXP(
if (nChannelID >= 1'000 || nSequence >= 1'000'000)
return false;
if (pBINK.n == 0 ||
pBINK.k == 0) {
#ifdef _DEBUG
printf("!! NOT IMPLEMENTED !!\n\n");
#endif
return false;
}
BIGNUM *privateKey = BN_new();
BIGNUM *genOrder = BN_new();
BN_hex2bn(&privateKey, privateKeyXP);
BN_hex2bn(&genOrder, genOrderXP);
BN_set_word(privateKey, pBINK.k);
BN_set_word(genOrder, pBINK.n);
EC_POINT *genPoint, *pubPoint;
EC_GROUP *eCurve = initializeEllipticCurve(
pXP,
aXP,
bXP,
genXXP,
genYXP,
pubXXP,
pubYXP,
genOrder,
privateKey,
pBINK.binKey.data.p,
pBINK.binKey.data.a,
pBINK.binKey.data.b,
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y,
&genPoint,
&pubPoint
);
do {
generateXPKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nSequence, bUpgrade, pKey);
} while (!verifyXPKey(eCurve, genPoint, pubPoint, pKey));
#ifdef _DEBUG
printf(
"Created elliptic curve:\n\n E = EllipticCurve(\n GF(0x%s),\n [0, 0, 0, %d, %d]\n ) => y^2 = x^3 + %dx + %d;\n\n G(x; y) = {\n 0x%s,\n 0x%s\n }\n\n K(x; y) = {\n 0x%s,\n 0x%s\n }\n\n\n",
pBINK.binKey.data.p,
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
atoi(pBINK.binKey.data.a),
atoi(pBINK.binKey.data.b),
pBINK.binKey.data.G.x,
pBINK.binKey.data.G.y,
pBINK.binKey.data.K.x,
pBINK.binKey.data.K.y
);
#endif
return true;
generateXPKey(eCurve, genPoint, genOrder, privateKey, nChannelID, nSequence, bUpgrade, pKey);
return verifyXPKey(eCurve, genPoint, pubPoint, pKey);
}

16
utilities/BitCounter.py Normal file
View File

@ -0,0 +1,16 @@
import math
def count_bits(number):
return round(math.log2(number)) + 1
if __name__ == "__main__":
number = int(input('Input a number: '))
print(count_bits(number))
number *= 2
number_bytes = int.to_bytes(number, 49, byteorder='big')
print(f"0x{number_bytes.hex().upper()}")

31
utilities/KeyDecoder.py Normal file
View File

@ -0,0 +1,31 @@
import math
def count(b):
p = 0
for i in range(25):
p += pow(24, 24 - i) * b[i]
return p
if __name__ == '__main__':
charset = "BCDFGHJKMPQRTVWXY2346789"
key1 = "JCF8T-2MG8G-Q6BBK-MQKGT-X3GBB"
key2 = "FFFFF-GGGGG-HHHHH-JJJJJ-KKKKK"
key3 = "99999-99999-99999-99999-99999"
b = []
for x in key2:
if x != '-':
b.append(charset.index(x))
result = count(b)
print(f'Byte array: {b}; Length: {len(b)}\n{hex(result).upper()}')
data = result.to_bytes(15, byteorder='little')
hex_string = "".join("%02X " % b for b in data)
print(hex_string)