So the party is over now... OMG [OFFTOPIC]i saw you in the other forum[OFFTOPIC] Is there any other wise brain to fulfil Bob65536's Dream(Confirmation ID generator) ?????
Thank you for the wonderful thread and info. I have created my own keys with some decode info. Thanks a lot for your hard work and time.
Most likely its random generation.... Phone conformation code generation will fail on "slmgr -ato" So this topic is completely useless ..... (Other than education purpose )
What a rude comment. As we only don´t know how to generate the secret hash this doesn´t mean this information is useless. Only fact so far: you cannot use it for a keygen, that´s all.
With this executable you can create product keys for SKU's that don't even exist... For example, put these keys into 'The Ultimate PID checker'; [REMOVED AS REQUESTED] [REMOVED AS REQUESTED] There is no installation media for these keys so I created my own with DISM to see if they could be activated with KMS and they couldn't (as expected). KMS Host knows no such SKU and does not respond to activation request.
anyway. keys should not be posted even if they are unusable. So please mask them asap. MDL gets problems if such posts are done (DMCA)
I have noticed that WMC Upgrade Keys get properly decoded, but if you enter the same groupid, keyid & secret the output is different. (Free) WMC keys are upgrade only, so you cannot use these keys on reinstall (ePid => RetailB Channel). Here is the fix: Before the hash is computed, the 15th byte is set to 0x2. Code: void SetInfo(const UINT32u groupid,const UINT32u keyid,const UINT64u secret,UINT128u& key3) { key3.u64[0]=0; key3.u64[1]=0; key3.u8[0]=groupid.u8[0]; key3.u8[1]=groupid.u8[1]; key3.u8[2]|=groupid.u8[2] & 0x0f; key3.u8[2]|=keyid.u8[0] << 4; key3.u8[3]=(keyid.u8[1] << 4) | (keyid.u8[0] >> 4); key3.u8[4]=(keyid.u8[2] << 4) | (keyid.u8[1] >> 4); key3.u8[5]=(keyid.u8[3] << 4) | (keyid.u8[2] >> 4); key3.u8[6]|=(keyid.u8[3] >> 4) & 0x3; key3.u8[6]|=secret.u8[0] << 2; key3.u8[7]=(secret.u8[1] << 2) | (secret.u8[0] >> 6); key3.u8[8]=(secret.u8[2] << 2) | (secret.u8[1] >> 6); key3.u8[9]=(secret.u8[3] << 2) | (secret.u8[2] >> 6); key3.u8[10]=(secret.u8[4] << 2) | (secret.u8[3] >> 6); key3.u8[11]=(secret.u8[5] << 2) | (secret.u8[4] >> 6); key3.u8[12]|=((secret.u8[6] << 2) | (secret.u8[5] >> 6)) & 0x7f; key3.u8[14]=0x2; }
Some things I'd like to comment: - Can someone PLEASE translate the KeyInfo code into VB or Java (preferably VB as java is more of a hobby for me)? I don't know the first thing about c++. - Where did Bob65536 go???
I implemented the keyinfo in java. I made some small fixes because java doesn't support unsigned data types. ProductKey.java Code: import java.nio.ByteBuffer; import java.nio.ByteOrder; /* ### Interface ### public class ProductKey : public enum Channel : RETAIL, RETAILB, OEM, VOLUME, public int getId(); public enum Group : OFFICE_2010, SERVER_2008_R2, SERVER_2012, public int getId(); private static class ProductKeyInfo : public int groupId, public int keyId, public long secret, public int hash; public static class Client : public static ProductKeyInfo validate(char[] key2), private static boolean checkHash(byte[] key0); public static class Server : public static String generate(int groupId, int keyId, long secret), private static byte[] RawProductKey(byte[] groupId, byte[] keyId, byte[] secret); */ public class ProductKey { // Channel public enum Channel { // Retail Channel RETAIL(0x0), // RetailB Channel (free WMC) RETAILB(0x1), // OEM Channel OEM(0x2), // Volume(GLVK,MAK) Channel VOLUME(0x3); // ChannelId private int id; // Constructor private Channel(int id){ this.id = id; } // Id Getter public int getId(){ return this.id; } } // Group public enum Group { // 96: Office 2010 OFFICE_2010(0x60), // 168: Win Server 2008 R2 (All) SERVER_2008_R2(0xa8), // 206: Server 2012 SERVER_2012(0xce); // GroupId private int id; // Constructor private Group(int id){ this.id = id; } // Id Getter public int getId(){ return this.id; } } // Product Key Struct private static class ProductKeyInfo { public int groupId, keyId, hash; public long secret; private ProductKeyInfo(int groupId, int keyId, long secret,int hash){ this.groupId = groupId; this.keyId = keyId; this.secret = secret; this.hash = hash; } } // Product Key Client public static class Client { // Validate Product Key public static ProductKeyInfo validate(char[] key2){ // Decode Base24 byte[] key0 = Base24.decode(Base24.decodeN(key2)); // Check Hash Signature int hash = checkHash(key0); if(hash == -1){ System.out.printf("Incorrect Hash!\n"); return null; } int groupId, keyId; long secret; // Get Info groupId = key0[0] & 0xff; groupId |= key0[1] << 8; groupId |= (key0[2] & 0xf) << 16; keyId = (key0[2] >> 4) & 0xf | (key0[3] << 4) & 0xf0; keyId |= ((key0[3] >> 4) & 0xf | (key0[4] << 4) & 0xf0) << 8; keyId |= ((key0[4] >> 4) & 0xf | (key0[5] << 4) & 0xf0) << 16; keyId |= ((key0[5] >> 4) & 0xf | (key0[6] << 4) & 0x30) << 24; secret = (key0[6] >> 2) & 0x3fL | (key0[7] << 6) & 0xc0L; secret |= ((key0[7] >> 2) & 0x3fL | (key0[8] << 6) & 0xc0L) << 8; secret |= ((key0[8] >> 2) & 0x3fL | (key0[9] << 6) & 0xc0L) << 16; secret |= ((key0[9] >> 2) & 0x3fL | (key0[10] << 6) & 0xc0L) << 24; secret |= ((key0[10] >> 2) & 0x3fL | (key0[11] << 6) & 0xc0L) << 32; secret |= ((key0[11] >> 2) & 0x3fL | (key0[12] << 6) & 0xc0L) << 40; secret |= ((key0[12] >> 2) & 0x1fL) << 48; return new ProductKeyInfo(groupId,keyId,secret,hash); } // Check Hash Signature private static int checkHash(byte[] key0){ int check = (key0[13] << 1) & 0xfe | (key0[12] >> 7) & 0x1; check |= (key0[14] << 9) & 0x200 | (key0[13] << 1) & 0x100; key0[12] &= 0x7f; key0[13] = 0; key0[14] &= 0xfe; if(check == Hash.get(key0)){ return check; } return -1; } } // Product Key Server public static class Server { // Generate Product Key public static String generate(int groupId, int keyId, long secret){ // GroupId Range if(groupId > 0xffffff){ System.out.printf("GroupId must be in the range 0-ffffff\n"); return null; } // KeyId Range if(keyId > 0x3b9ac9ff){ System.out.printf("KeyId must be in the range 0-3b9ac9ff\n"); return null; } // Secret Range if(secret > 0x1fffffffffffffL){ System.out.printf("Secret must be in the range 0-1fffffffffffff\n"); return null; } // Convert Integer to Byte Array byte[] bgroupId = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(groupId).array(); byte[] bkeyId = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(keyId).array(); byte[] bsecret = ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(secret).array(); // Raw Product Key byte[] key0 = RawProductKey(bgroupId,bkeyId,bsecret); // Print Raw Product Key for(int i = 0; i < 16; i++) System.out.printf("%x ",key0); System.out.println(); // Base24 encoded N Product Key return new String(Base24.encodeN(Base24.encode(key0))); } // Raw Product Key private static byte[] RawProductKey(byte[] groupId, byte[] keyId, byte[] secret){ byte[] key0 = new byte[16]; // GroupId key0[0] = groupId[0]; key0[1] = groupId[1]; key0[2] |= groupId[2] & 0xf; // KeyId key0[2] |= keyId[0] << 4; key0[3] |= (keyId[1] << 4) | (keyId[0] >> 4) & 0xf; key0[4] |= (keyId[2] << 4) | (keyId[1] >> 4) & 0xf; key0[5] |= (keyId[3] << 4) | (keyId[2] >> 4) & 0xf; key0[6] |= (keyId[3] >> 4) & 0x3; // Secret key0[6] |= secret[0] << 2; key0[7] |= (secret[1] << 2) | (secret[0] >> 6) & 0x3; key0[8] |= (secret[2] << 2) | (secret[1] >> 6) & 0x3; key0[9] |= (secret[3] << 2) | (secret[2] >> 6) & 0x3; key0[10] |= (secret[4] << 2) | (secret[3] >> 6) & 0x3; key0[11] |= (secret[5] << 2) | (secret[4] >> 6) & 0x3; key0[12] |= (secret[6] << 2) & 0x7f | (secret[5] >> 6) & 0x3; // Upgrade Key //key0[14] = 0x2; // Hash int check = Hash.get(key0); key0[12] |= check << 7; key0[13] |= check >> 1; key0[14] |= check >> 9; return key0; } } public static void DecodeIID(){ // IID Byte Array (136 => 1,3,6) byte[] iid = {0,0,0,0}; // Check Digits for(int i = 0; i < 54; i += 7){ if((iid + iid[i+2] + iid[i+4] + 2 * (iid[i+1] + iid[i+3] + iid[i+5])) % 7 != iid[i+6]){ System.out.printf("Incorrect Check Digits!\n"); return; } } // Decode IID Base10 byte[] ciid = Base24.decode10(iid); // Print for(int i = 0; i < ciid.length; i++) System.out.printf("%x ",ciid); System.out.println(); } // Main public static void main(String[] args){ String key = ProductKey.Server.generate(0,0,0); System.out.printf("%s\n",key); ProductKey.ProductKeyInfo pk = ProductKey.Client.validate(key.toCharArray()); System.out.printf("groupId: %x, keyId: %x, secret: %x, hash: %x\n",pk.groupId,pk.keyId,pk.secret,pk.hash); //DecodeIID(); } } Hash.java Code: public class Hash { // Hash Table private static final int[] hash_table = { 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4}; // Hash Function // Length: 10(bit) public static int get(byte[] key){ int hash = -1; int index; for(int i = 0; i < 16; i++){ index = ((hash >> 24) ^ key) & 0xff; hash = (hash << 8) ^ hash_table[index]; } return ~hash & 0x3ff; } } Base24.java Code: public class Base24 { // Library private static char[] lib = { 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'M', 'P', 'Q', 'R', 'T', 'V', 'W', 'X', 'Y', '2', '3', '4', '6', '7', '8', '9' }; // Encode Base24 public static char[] encode(byte[] key0){ char[] res = new char[25]; int rem, val; for(int i = 24; i >= 0; i--){ rem = 0; for(int j = 14; j >= 0; j--){ val = (rem << 8) | (key0[j] & 0xff); key0[j] = (byte)(val / 24); rem = val % 24; } res = (char)rem; } return res; } // N Product Key public static char[] encodeN(char[] key1){ char[] res = new char[29]; int N = key1[0] + key1[0] / 5; for(int i = 0, j = 1; i < 29; i++){ if(i == N){ res = 'N'; }else if((i + 1) % 6 == 0){ res = '-'; }else{ res = lib[key1[j++]]; } } return res; } // Decode Base24 public static byte[] decode(char[] key1){ byte[] res = new byte[16]; int val; for(int i = 0; i < 25; i++){ val = key1; for(int j = 0; j < 15; j++){ val += 24 * (res[j] & 0xff); res[j] = (byte)val; val >>= 8; } } return res; } // N Product Key public static char[] decodeN(char[] key2){ char[] res = new char[29]; for(int i = 0, j = 1; i < 29; i++){ if(key2 == 'N'){ res[0] = (char)(j - 1); }else if(key2 != '-'){ res[j++] = (char)indexOf(key2); } } return res; } // Decode InstallId Base10 public static byte[] decode10(byte[] key1){ byte[] res = new byte[24]; int val; for(int i = 0; i < 63; i++){ // Skip Check Digits if((i + 1) % 7 == 0) continue; val = key1; for(int j = 0; j < 18; j++){ val += 10 * (res[j] & 0xff); res[j] = (byte)val; val >>= 8; } } return res; } // Reverse Lib private static int indexOf(char value){ for(int i = 0; i < 24; i++){ if(value == lib){ return i; } } return -1; } }
I figured something out: it's possible to disassemble the 32-bit sppsvc.exe into ASM code with PE Explorer (or most 32-bit windows exe files and dlls). IDK if anyone still wants to continue Bob65536's quest for a confirmation ID generator or if this idea even helps, but i thought it might be a good idea to post it.
I did this in vb.net once. Isn't there an old thread on mdl about the pidgen module? Code: <DllImport("pidgenx.dll", CharSet:=CharSet.Auto)> _ Private Shared Function PidGenX(ByVal ProductKey As String, ByVal configFile As String, ByVal mpc As String, ByVal unknown As IntPtr, ByVal ProductId2 As IntPtr, ByVal ProductId3 As IntPtr, ByVal ProductId4 As IntPtr) As Int32 End Function Public Function pidgen(ByVal ProductKey As String, ByVal configFile As String, ByRef pid2() As Byte, ByRef pid3() As Byte, ByRef pid4() As Byte) As Integer Dim _pid2 As IntPtr = Marshal.AllocHGlobal(50) Dim _pid3 As IntPtr = Marshal.AllocHGlobal(164) Dim _pid4 As IntPtr = Marshal.AllocHGlobal(1272) For _i = 0 To 49 : Marshal.WriteByte(_pid2, _i, &H0) : Next For _i = 0 To 163 : Marshal.WriteByte(_pid3, _i, &H0) : Next For _i = 0 To 1271 : Marshal.WriteByte(_pid4, _i, &H0) : Next Marshal.WriteByte(_pid2, 0, &H32) Marshal.WriteByte(_pid3, 0, &HA4) Marshal.WriteByte(_pid4, 0, &HF8) Marshal.WriteByte(_pid4, 1, &H4) Dim _h As Integer = PidGenX(ProductKey, currentDir & "\" & pkeyconfigPath & "\" & configFile, "XXXXX", Nothing, _pid2, _pid3, _pid4) If _h = 0 Then For _i = 0 To 49 : pid2(_i) = Marshal.ReadByte(_pid2, _i) : Next For _i = 0 To 163 : pid3(_i) = Marshal.ReadByte(_pid3, _i) : Next For _i = 0 To 1271 : pid4(_i) = Marshal.ReadByte(_pid4, _i) : Next Return 1 Else Return 0 End If Marshal.FreeHGlobal(_pid2) Marshal.FreeHGlobal(_pid3) Marshal.FreeHGlobal(_pid4) End Function Note that the second argument for the PidGenX call has to be modified with the path to the right xlm-rs file. the function can be used to decode the product key from pid4. the _sa variable is the offset which should be 808 for windows. Code: Private Function GetPK(ByRef _pid4() As Byte, ByVal _sa As Integer) As String Dim _pk(24) As Char Dim _pkR As New StringBuilder _sa += _pk_ea Dim _xpk(14) As Integer Dim __A As Integer For _i = 0 To _pk_ea _xpk(_i) = _pid4(_sa - _i) Next For _i As Integer = 25 To 1 Step -1 __A = 0 For _i2 As Integer = 0 To _pk_ea __A = (__A * 256) Or _xpk(_i2) _xpk(_i2) = __A \ 24 __A = __A Mod 24 Next _pk(_i - 1) = _pk_digits(__A) Next Dim __i As Integer = 0 For _i = 0 To 4 For _i2 = 0 To 4 _pkR.Append(_pk(__i + _i2)) Next If _i <= 3 Then _pkR.Append("-") __i += 5 Next Return _pkR.ToString End Function