initial commit

This commit is contained in:
awuctl 2022-08-23 18:48:54 +02:00
commit 840fb76d79
6 changed files with 264 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
*
!*.c
!*.py
!Makefile
!README.md
!LICENSE
!.gitignore

7
Makefile Normal file
View File

@ -0,0 +1,7 @@
GCCOPT=-O0 -Wall -pedantic
GCC=gcc
all: hwid_dec
hwid_dec: hwid_dec.c
$(GCC) $(GCCOPT) $< -o $@

35
README.md Normal file
View File

@ -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
```

108
hwid_dec.c Normal file
View File

@ -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;
}

50
hwid_extract.py Executable file
View File

@ -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)

57
ticket_decode.py Executable file
View File

@ -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=': ')