summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorawuctl2022-08-23 16:48:54 +0000
committerawuctl2022-08-23 16:48:54 +0000
commit840fb76d797319ca0542dccc92a08feb1e9a8264 (patch)
treea22723328b0a0de267898a86ac6dd55bd6f42b82
downloadhwid-stuff-840fb76d797319ca0542dccc92a08feb1e9a8264.zip
initial commit
-rw-r--r--.gitignore7
-rw-r--r--Makefile7
-rw-r--r--README.md35
-rw-r--r--hwid_dec.c108
-rwxr-xr-xhwid_extract.py50
-rwxr-xr-xticket_decode.py57
6 files changed, 264 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d01231
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+*
+!*.c
+!*.py
+!Makefile
+!README.md
+!LICENSE
+!.gitignore \ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..62ac64b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+GCCOPT=-O0 -Wall -pedantic
+GCC=gcc
+
+all: hwid_dec
+
+hwid_dec: hwid_dec.c
+ $(GCC) $(GCCOPT) $< -o $@ \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..52c914b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+# HWID Stuff
+
+Here are some basic example utilities for GenuineAuthorization tickets and HWID block blobs.
+
+If you'd like to learn more about the things those scripts work with, go to [massgravel/activation](https://github.com/massgravel/activation).
+
+# Info
+
+## `hwid_extract.py`
+
+This scripts extracts the HWID block blob from a GenuineAuthorization ticket into a file:
+
+```sh
+# Writes to file
+python hwid_extract.py GenuineTicket.xml hwid.bin
+
+# Writes to stdout
+python hwid_extract.py GenuineTicket.xml
+```
+
+## `hwid_dec.c`
+
+This is a program that prints out all the individual fields in the HWID block blob. Build with `make`.
+
+```sh
+hwid_dec hwid.bin
+```
+
+## `ticket_decode.py`
+
+This is a script that prints out meaningful individual fields in a ticket.
+
+```sh
+python ticket_decode.py GenuineTicket.xml
+``` \ No newline at end of file
diff --git a/hwid_dec.c b/hwid_dec.c
new file mode 100644
index 0000000..c426133
--- /dev/null
+++ b/hwid_dec.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+struct __attribute__((packed)) HWID {
+ uint16_t size;
+ uint16_t version;
+ uint16_t instances[9];
+ uint16_t dock_or_PCMCIA;
+ uint16_t hashRAM;
+ uint16_t hashBIOS;
+ uint16_t instanceHashes[];
+};
+
+struct __attribute__((packed)) TIMEWEIGHT {
+ uint8_t num_weights;
+ struct __attribute__((packed)) Weight {
+ uint8_t type;
+ uint16_t weight;
+ } weight[];
+};
+
+const char *CLASS_NAMES[] = {
+ "CDROM",
+ "Hard Disk Controllers",
+ "Hard Disk Drives",
+ "Displays",
+ "SCSI Adapters",
+ "PCMCIA",
+ "Audio Adapters",
+ "Dock",
+ "Network Interface Cards",
+ "CPUs",
+ "Memory",
+ "UNUSED",
+ "BIOS",
+ "UNUSED",
+ "Mobile Broadband",
+ "Bluetooth Interfaces"
+};
+
+const char *HWID_NAMES[] = {
+ "CDROM / Mobile Broadband",
+ "Hard Disk Controllers",
+ "Hard Disk Drives",
+ "Displays",
+ "SCSI Adapters / Bluetooth Controllers",
+ "Audio Adapters",
+ "Unused",
+ "Network Interface Cards",
+ "CPUs"
+};
+
+void print_block(uint8_t *hw_block) {
+ uint32_t size = *(uint32_t *)hw_block;
+ uint16_t unknown = *(uint16_t *)(hw_block + 4);
+ unsigned instance_count = 0;
+
+ puts("Block Information:");
+ printf("Size : [%08x]\n", size);
+ printf("Unknown : [%08x]\n", unknown);
+ puts("");
+
+ struct HWID *hwid = (struct HWID *)(hw_block + 6);
+ puts("HWID Information:");
+ printf("Size : [%04x]\n", hwid->size);
+ printf("Version : [%04x]\n", hwid->version);
+ for(size_t i = 0; i < 9; i++) {
+ instance_count += hwid->instances[i];
+ printf("Inst. (%02zx) : [%04x] -> %s\n", i, hwid->instances[i], HWID_NAMES[i]);
+ }
+ printf("Dock/PCMCIA : [%04x]\n", hwid->dock_or_PCMCIA);
+ printf("RAM hash : [%02x]\n", hwid->hashRAM);
+ printf("SMBIOS hash : [%04x]\n", hwid->hashBIOS);
+ for(size_t i = 0; i < instance_count; i++) {
+ printf("Hash (%02zx) : [%04x] %s\n", i, hwid->instanceHashes[i], (hwid->instanceHashes[i] & 1) == 1 ? "[[Non-Removable]]" : "");
+ }
+ puts("");
+
+ struct TIMEWEIGHT *tw = (struct TIMEWEIGHT *) ((hw_block + 6) + hwid->size);
+ puts("Timeweight Information:");
+ printf("Weights : [%02x]\n", tw->num_weights);
+
+ for(size_t i = 0; i < tw->num_weights; i++) {
+ printf("Weight (%02x) : [%04x] -> %s\n", tw->weight[i].type, tw->weight[i].weight, CLASS_NAMES[tw->weight[i].type]);
+ }
+
+}
+
+int main(int argc, char *argv[]) {
+
+ if(argc != 2) {
+ puts("Invalid parameters.\nUsages:\n\thwid file");
+ exit(1);
+ }
+
+ FILE *fd = fopen(argv[1], "r");
+ fseek(fd, 0, SEEK_END);
+ long fsize = ftell(fd);
+ rewind(fd);
+
+ uint8_t *hw_block = malloc(fsize);
+ fread(hw_block, 1, fsize, fd);
+
+ print_block(hw_block);
+
+ return 0;
+} \ No newline at end of file
diff --git a/hwid_extract.py b/hwid_extract.py
new file mode 100755
index 0000000..f3f5433
--- /dev/null
+++ b/hwid_extract.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+from functools import reduce
+import xml.etree.ElementTree as ET
+
+from base64 import b64decode
+
+class Ticket:
+ @staticmethod
+ def get_properties(genAuth: ET.Element) -> str:
+ properties = genAuth.find('./{*}genuineProperties/{*}properties')
+ return properties.text
+
+ @staticmethod
+ def split_keyval(x: str) -> dict:
+ parameters = {}
+
+ for params in x.split(';'):
+ if not params or params == '\x00':
+ break
+ key_val = params.split('=')
+ parameters[key_val[0]] = key_val[1]
+ return parameters
+
+ @staticmethod
+ def get_hwid(genAuth: ET.Element) -> str:
+ props = Ticket.split_keyval(Ticket.get_properties(genAuth))
+ params = Ticket.split_keyval(b64decode(props['SessionId'] + '===').decode('utf-16'))
+
+ return params['Hwid']
+
+if __name__ == '__main__':
+ import argparse
+
+ main_parser = argparse.ArgumentParser(
+ 'hwid_extract',
+ description='Extract the binary hardware id from ticket'
+ )
+ main_parser.add_argument('input', type=argparse.FileType('rb'))
+ main_parser.add_argument('output', type=argparse.FileType('wb'), nargs='?')
+ args = main_parser.parse_args()
+
+ ticket = ET.parse(args.input).getroot()
+ hwid = Ticket.get_hwid(ticket)
+
+ hwid_block = b64decode(hwid + '===')
+ if args.output is None:
+ print(hwid_block)
+ else:
+ args.output.write(hwid_block) \ No newline at end of file
diff --git a/ticket_decode.py b/ticket_decode.py
new file mode 100755
index 0000000..a15fa14
--- /dev/null
+++ b/ticket_decode.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+from functools import reduce
+import xml.etree.ElementTree as ET
+
+from base64 import b64decode
+
+# Microsoft really hates padding base64
+# appending "===" is just so that b64decode
+# doesn't complain about it.
+# It's neither valid padding nor magic.
+
+class Ticket:
+ @staticmethod
+ def get_properties(genAuth: ET.Element) -> str:
+ properties = genAuth.find('./{*}genuineProperties/{*}properties')
+ return properties.text
+
+ @staticmethod
+ def split_keyval(x: str) -> dict:
+ parameters = {}
+
+ for params in x.split(';'):
+ if not params or params == '\x00':
+ break
+ key_val = params.split('=')
+ parameters[key_val[0]] = key_val[1]
+ return parameters
+
+ def __init__(self, genuine_authorization: ET.Element):
+ self.gen_auth = genuine_authorization
+ self.gen_props = genuine_authorization.find('./{*}genuineProperties')
+
+ props = self.gen_props.find('./{*}properties').text
+ self.props = self.split_keyval(props)
+ self.props['SessionId'] = self.split_keyval(b64decode(self.props['SessionId'] + '===').decode('utf-16'))
+
+if __name__ == '__main__':
+ import argparse
+
+ main_parser = argparse.ArgumentParser(
+ 'ticket_decode',
+ description='Print out contents of a GenuineAuthorization ticket'
+ )
+ main_parser.add_argument('input', type=argparse.FileType('r'))
+ args = main_parser.parse_args()
+
+ ticket = Ticket(ET.parse(args.input).getroot())
+
+ # Print out stuff
+
+ for prop in ticket.props:
+ if prop == 'SessionId':
+ for sess_prop in ticket.props['SessionId']:
+ print(sess_prop, ticket.props['SessionId'][sess_prop], sep=': ')
+ continue
+ print(prop, ticket.props[prop], sep=': ') \ No newline at end of file