mirror of
https://github.com/massgravel/keyhole.git
synced 2024-11-22 21:39:49 +00:00
Add files via upload
This commit is contained in:
commit
0aebfd413f
166
device_ticket.bat
Normal file
166
device_ticket.bat
Normal file
@ -0,0 +1,166 @@
|
||||
<# :
|
||||
@REM BSD 3-Clause License
|
||||
@REM
|
||||
@REM Copyright(c) 2023, echnobas
|
||||
@REM All rights reserved.
|
||||
@REM
|
||||
@REM Redistribution and use in source and binary forms, with or without
|
||||
@REM modification, are permitted provided that the following conditions are met:
|
||||
@REM
|
||||
@REM 1. Redistributions of source code must retain the above copynotice, this
|
||||
@REM list of conditions and the following disclaimer.
|
||||
@REM
|
||||
@REM 2. Redistributions in binary form must reproduce the above copynotice,
|
||||
@REM this list of conditions and the following disclaimer in the documentation
|
||||
@REM and/or other materials provided with the distribution.
|
||||
@REM
|
||||
@REM 3. Neither the name of the copyholder nor the names of its
|
||||
@REM contributors may be used to endorse or promote products derived from
|
||||
@REM this software without specific prior written permission.
|
||||
@REM
|
||||
@REM THIS SOFTWARE IS PROVIDED BY THE COPYHOLDERS AND CONTRIBUTORS "AS IS"
|
||||
@REM AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
@REM IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
@REM DISCLAIMED. IN NO EVENT SHALL THE COPYHOLDER OR CONTRIBUTORS BE LIABLE
|
||||
@REM FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
@REM DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
@REM SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
@REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
@REM OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
@REM OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@echo off &chcp 850 >nul &pushd "%~dp0"
|
||||
fltmc >nul 2>&1 || (
|
||||
powershell Start-Process -FilePath "%~f0" -ArgumentList "%cd%" -verb runas >NUL 2>&1
|
||||
exit /b
|
||||
)
|
||||
set "psScript=%~f0"
|
||||
powershell -nop -c "& ([ScriptBlock]::Create((Get-Content """$env:psScript""" -Raw)))" & exit /b
|
||||
: #>
|
||||
###################################### SUBLICENSE BEGIN ######################################
|
||||
# BSD 3-Clause License
|
||||
#
|
||||
# Copyright(c) 2019, Tobias Heilig
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copynotice, this
|
||||
# list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copynotice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyholder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYHOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYHOLDER OR CONTRIBUTORS BE LIABLE
|
||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
try {
|
||||
& {
|
||||
$ErrorActionPreference = 'Stop'
|
||||
[void] [impsys.win32]
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
namespace impsys {
|
||||
public class win32 {
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern bool CloseHandle(
|
||||
IntPtr hHandle);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError=true)]
|
||||
public static extern IntPtr OpenProcess(
|
||||
uint processAccess,
|
||||
bool bInheritHandle,
|
||||
int processId);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool OpenProcessToken(
|
||||
IntPtr ProcessHandle,
|
||||
uint DesiredAccess,
|
||||
out IntPtr TokenHandle);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool DuplicateTokenEx(
|
||||
IntPtr hExistingToken,
|
||||
uint dwDesiredAccess,
|
||||
IntPtr lpTokenAttributes,
|
||||
uint ImpersonationLevel,
|
||||
uint TokenType,
|
||||
out IntPtr phNewToken);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool ImpersonateLoggedOnUser(
|
||||
IntPtr hToken);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError=true)]
|
||||
public static extern bool RevertToSelf();
|
||||
}
|
||||
}
|
||||
"@
|
||||
}
|
||||
|
||||
$winlogonPid = Get-Process -Name "winlogon" | Select-Object -First 1 -ExpandProperty Id
|
||||
|
||||
if (($processHandle = [impsys.win32]::OpenProcess(
|
||||
0x400,
|
||||
$true,
|
||||
[Int32]$winlogonPid)) -eq [IntPtr]::Zero) {
|
||||
$err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
Write-Error "$([ComponentModel.Win32Exception]$err)"
|
||||
Exit $err
|
||||
}
|
||||
|
||||
$tokenHandle = [IntPtr]::Zero
|
||||
if (-not [impsys.win32]::OpenProcessToken(
|
||||
$processHandle,
|
||||
0x0E,
|
||||
[ref]$tokenHandle)) {
|
||||
$err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
Write-Error "$([ComponentModel.Win32Exception]$err)"
|
||||
Exit $err
|
||||
}
|
||||
|
||||
$dupTokenHandle = [IntPtr]::Zero
|
||||
if (-not [impsys.win32]::DuplicateTokenEx(
|
||||
$tokenHandle,
|
||||
0x02000000,
|
||||
[IntPtr]::Zero,
|
||||
0x02,
|
||||
0x01,
|
||||
[ref]$dupTokenHandle)) {
|
||||
$err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
Write-Error "$([ComponentModel.Win32Exception]$err)"
|
||||
Exit $err
|
||||
}
|
||||
|
||||
if (-not [impsys.win32]::ImpersonateLoggedOnUser(
|
||||
$dupTokenHandle)) {
|
||||
$err = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
|
||||
Write-Error "$([ComponentModel.Win32Exception]$err)"
|
||||
Exit $err
|
||||
}
|
||||
###################################### SUBLICENSE END ######################################
|
||||
|
||||
Add-Type -AssemblyName System.Security
|
||||
$key = "registry::HKEY_USERS\S-1-5-19\Software\Microsoft\IdentityCRL\Immersive\production\Token\{D6D5A677-0872-4AB0-9442-BB792FCE85C5}"
|
||||
$ticket = (Get-ItemProperty -Path $key)."DeviceTicket"
|
||||
$raw = ([Text.Encoding]::Unicode).GetString([Security.Cryptography.ProtectedData]::Unprotect($ticket[4..$ticket.length], $Null, [Security.Cryptography.DataProtectionScope]::LocalMachine)) -replace "^.*?t\=" -replace "\&p\=.*"
|
||||
|
||||
Set-Content -NoNewline -Path dev_tik.txt -Value "$raw"
|
70
kh_editlic.py
Normal file
70
kh_editlic.py
Normal file
@ -0,0 +1,70 @@
|
||||
import sys
|
||||
import random
|
||||
import struct
|
||||
import time
|
||||
import binascii
|
||||
import hashlib
|
||||
|
||||
tlv_types = {
|
||||
"SignedBlock": 0x14,
|
||||
"DeviceLicenseExpirationTime": 0x1f,
|
||||
"PollingTime": 0xd3,
|
||||
"LicenseExpirationTime": 0x20,
|
||||
"ClepSignState": 0x12d,
|
||||
"LicenseDeviceId": 0xd2,
|
||||
"UnkBlock1": 0xd1,
|
||||
"LicenseId": 0xcb,
|
||||
"HardwareId": 0xd0,
|
||||
"UnkBlock2": 0xcf,
|
||||
"UplinkKeyId": 0x18,
|
||||
"UnkBlock3": 0x0,
|
||||
"UnkBlock4": 0x12e,
|
||||
"UnkBlock5": 0xd5,
|
||||
"PackageFullName": 0xce,
|
||||
"LicenseInformation": 0xc9,
|
||||
"PackedContentKeys": 0xca,
|
||||
"EncryptedDeviceKey": 0x1,
|
||||
"DeviceLicenseDeviceId": 0x2,
|
||||
"LicenseEntryIds": 0xcd,
|
||||
"LicensePolicies": 0xd4,
|
||||
"KeyholderPublicSigningKey": 0xdc,
|
||||
"KeyholderPolicies": 0xdd,
|
||||
"KeyholderKeyLicenseId": 0xde,
|
||||
"SignatureBlock": 0xcc,
|
||||
};
|
||||
|
||||
def encode_tlvblock(type, data):
|
||||
return struct.pack("<II", tlv_types[type], len(data)) + data
|
||||
|
||||
extradata = None
|
||||
|
||||
lic_file = sys.argv[1]
|
||||
new_pfn = sys.argv[2].lower()
|
||||
out_lic = sys.argv[3]
|
||||
|
||||
if len(sys.argv) >= 5:
|
||||
extra_file = sys.argv[4]
|
||||
|
||||
with open(extra_file, "rb") as f:
|
||||
extradata = f.read()
|
||||
|
||||
with open(lic_file, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
data += encode_tlvblock("PackageFullName", new_pfn.encode("utf-16-le") + b"\x00\x00")
|
||||
|
||||
basic_pol = 0x0a
|
||||
if "addon" in new_pfn:
|
||||
basic_pol = 0x00
|
||||
|
||||
lic_info = struct.pack("<HHIBB", 5, 1, int(time.time()), basic_pol, 1)
|
||||
data += encode_tlvblock("LicenseInformation", lic_info)
|
||||
data += encode_tlvblock("LicenseId", random.randbytes(16))
|
||||
data += encode_tlvblock("LicenseEntryIds", b"\x01\x00" + hashlib.sha256(new_pfn.encode("utf-16-le")).digest())
|
||||
data += encode_tlvblock("LicenseExpirationTime", b"\x00\x00\x00\x00")
|
||||
|
||||
if extradata:
|
||||
data += extradata
|
||||
|
||||
with open(out_lic, "wb") as f:
|
||||
f.write(data)
|
125
resignlic.py
Normal file
125
resignlic.py
Normal file
@ -0,0 +1,125 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from xml.etree import ElementTree as ET
|
||||
from base64 import b64decode, b64encode
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.Signature import PKCS1_v1_5
|
||||
from ecdsa import SigningKey
|
||||
from copy import copy
|
||||
import argparse, re
|
||||
|
||||
# TODO: Implement SPLicenseBlock parser
|
||||
|
||||
CLIPUP_ECC_KEY_PEM = """-----BEGIN PRIVATE KEY-----
|
||||
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgPJp69Tr9nAvAHi3B
|
||||
2dr5jenY4MkTwy4L/ahplSNxvgahRANCAATC/nluDYXrQHgi9STrd2kEhS4cKfTD
|
||||
URm5vYGwUG1Jxva69OJEUiF2sfMhYGnCDYHrLM5ndcA0s43ie1+z3y1t
|
||||
-----END PRIVATE KEY-----"""
|
||||
|
||||
clipup_eckey = SigningKey.from_pem(CLIPUP_ECC_KEY_PEM, hashfunc=SHA256.new)
|
||||
|
||||
def xml_open(xmlf):
|
||||
with open(xmlf) as f:
|
||||
cont = f.read()
|
||||
|
||||
return BeautifulSoup(cont, "xml")
|
||||
|
||||
def xml_save(xml, path):
|
||||
with open(path, "wb") as f:
|
||||
f.write(canonicb(xml))
|
||||
|
||||
def iso_date(t):
|
||||
return datetime.fromtimestamp(t).isoformat() + "Z"
|
||||
|
||||
def sha256(s):
|
||||
return SHA256.new(s).digest()
|
||||
|
||||
def b64sencode(s):
|
||||
return b64encode(s).decode()
|
||||
|
||||
def b64ssencode(s):
|
||||
return b64sencode(s.encode())
|
||||
|
||||
def b64sdecode(s):
|
||||
return b64decode(s).decode()
|
||||
|
||||
def hashb64(s):
|
||||
return b64sencode(sha256(s))
|
||||
|
||||
def canonicb(x):
|
||||
return ET.canonicalize(str(x), strip_text=True).encode()
|
||||
|
||||
def decode_tsl(tsl, log=False):
|
||||
if tsl.SPLicenseBlock:
|
||||
licblock = b64decode(tsl.SPLicenseBlock.text)
|
||||
else:
|
||||
licblock = None
|
||||
|
||||
pubkey = clipup_eckey.get_verifying_key()
|
||||
|
||||
sig_inf = tsl.SignedInfo
|
||||
sig_inf.attrs["xmlns"] = "http://www.w3.org/2000/09/xmldsig#"
|
||||
sig_val = b64decode(tsl.SignatureValue.text)
|
||||
sig_data = canonicb(sig_inf)
|
||||
|
||||
try:
|
||||
valid = pubkey.verify(sig_val, sig_data)
|
||||
except:
|
||||
valid = False
|
||||
|
||||
if log:
|
||||
print("TSL Information:")
|
||||
print(f"Valid: {valid}")
|
||||
|
||||
return licblock, valid
|
||||
|
||||
def resign_lic(tsl, licblock=None):
|
||||
sig_tag = copy(tsl.License.Signature)
|
||||
tsl.License.Signature.decompose()
|
||||
|
||||
if licblock:
|
||||
if tsl.License.SPLicenseBlock is None:
|
||||
tsl.License.append(tsl.new_tag("SPLicenseBlock"))
|
||||
|
||||
tsl.SPLicenseBlock.string = b64sencode(licblock)
|
||||
|
||||
|
||||
hash = hashb64(canonicb(tsl))
|
||||
sig_tag.SignedInfo.DigestValue.string = hash
|
||||
|
||||
sig_tag.SignedInfo.attrs["xmlns"] = "http://www.w3.org/2000/09/xmldsig#"
|
||||
sig = b64sencode(clipup_eckey.sign_deterministic(canonicb(sig_tag.SignedInfo)))
|
||||
del sig_tag.SignedInfo.attrs["xmlns"]
|
||||
|
||||
sig_tag.SignatureValue.string = sig
|
||||
|
||||
tsl.License.append(sig_tag)
|
||||
|
||||
return tsl
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("mode", help="Mode: encode, decode")
|
||||
parser.add_argument("license", nargs="?", default="", help="Data/path")
|
||||
parser.add_argument("licblock", help="Type: tslraw, tslconv, ticket")
|
||||
parser.add_argument("--output", "-o", help="Output path", default="edit.xml")
|
||||
args = parser.parse_args()
|
||||
|
||||
licblock = None
|
||||
|
||||
tsl = xml_open(args.license)
|
||||
|
||||
if args.mode == "encode":
|
||||
with open(args.licblock, "rb") as f:
|
||||
licblock = f.read()
|
||||
|
||||
tsl = resign_lic(tsl, licblock)
|
||||
xml_save(tsl, args.output)
|
||||
elif args.mode == "decode":
|
||||
licblock_out, valid = decode_tsl(tsl, log=False)
|
||||
|
||||
if licblock_out and args.licblock:
|
||||
with open(args.licblock, "wb") as f:
|
||||
f.write(licblock_out)
|
142
splicenseblock.hexpat
Normal file
142
splicenseblock.hexpat
Normal file
@ -0,0 +1,142 @@
|
||||
#include <std/mem.pat>
|
||||
|
||||
struct UTF16CStr {
|
||||
char16 data[while(std::mem::read_unsigned($, 2) != 0x0)];
|
||||
char16 terminator[[hidden]];
|
||||
};
|
||||
|
||||
enum LicenseType : u16 {
|
||||
Unknown = 0,
|
||||
App = 1,
|
||||
Lease = 2,
|
||||
Device = 3,
|
||||
Dev = 4,
|
||||
Lob = 5,
|
||||
Upgrade = 6,
|
||||
};
|
||||
|
||||
bitfield BasicPolicies {
|
||||
lease_required : 1;
|
||||
is_primary : 1;
|
||||
expired : 1;
|
||||
is_device_locked : 1;
|
||||
padding : 12;
|
||||
};
|
||||
|
||||
struct LicenseInformation {
|
||||
u16 version;
|
||||
LicenseType type;
|
||||
s32 issued;
|
||||
BasicPolicies policies;
|
||||
};
|
||||
|
||||
// SHA256 of PFN (lowercase)
|
||||
struct LicenseEntryId {
|
||||
u8 data[32];
|
||||
};
|
||||
|
||||
enum PolicyType : u8 {
|
||||
NONE = 0x01,
|
||||
STRING = 0x11,
|
||||
BINARY = 0x31,
|
||||
DWORD = 0x41,
|
||||
MULTI_SZ = 0x71
|
||||
};
|
||||
|
||||
struct Policy {
|
||||
u16 something1[[hidden]];
|
||||
u16 something2[[hidden]];
|
||||
u8 pad0[[hidden]];
|
||||
PolicyType type;
|
||||
u16 pad1[[hidden]];
|
||||
u16 priority;
|
||||
u16 name_sz;
|
||||
u16 data_sz;
|
||||
char16 name[name_sz / 2];
|
||||
|
||||
u32 end = $ + data_sz;
|
||||
match (type) {
|
||||
(PolicyType::STRING): {
|
||||
UTF16CStr data;
|
||||
}
|
||||
(PolicyType::DWORD): {
|
||||
u32 data;
|
||||
}
|
||||
(PolicyType::MULTI_SZ): {
|
||||
UTF16CStr data[];
|
||||
}
|
||||
(_): {
|
||||
u8 data[while($ < end)];
|
||||
}
|
||||
}
|
||||
u16 terminator[[hidden]];
|
||||
};
|
||||
|
||||
enum BlockType : u32 {
|
||||
SignedBlock = 0x14,
|
||||
DeviceLicenseExpirationTime = 0x1f,
|
||||
PollingTime = 0xd3,
|
||||
LicenseExpirationTime = 0x20,
|
||||
ClepSignState = 0x12d,
|
||||
LicenseDeviceId = 0xd2,
|
||||
UnkBlock1 = 0xd1,
|
||||
LicenseId = 0xcb,
|
||||
HardwareId = 0xd0,
|
||||
UnkBlock2 = 0xcf,
|
||||
UplinkKeyId = 0x18,
|
||||
UnkBlock3 = 0x0,
|
||||
UnkBlock4 = 0x12e,
|
||||
UnkBlock5 = 0xd5,
|
||||
PackageFullName = 0xce,
|
||||
LicenseInformation = 0xc9,
|
||||
PackedContentKeys = 0xca,
|
||||
EncryptedDeviceKey = 0x1,
|
||||
DeviceLicenseDeviceId = 0x2,
|
||||
LicenseEntryIds = 0xcd,
|
||||
LicensePolicies = 0xd4,
|
||||
KeyholderPublicSigningKey = 0xdc,
|
||||
KeyholderPolicies = 0xdd,
|
||||
KeyholderKeyLicenseId = 0xde,
|
||||
SignatureBlock = 0xcc,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
struct TLVBlock {
|
||||
BlockType type;
|
||||
u32 size;
|
||||
|
||||
u32 end = $ + size;
|
||||
match (type) {
|
||||
(BlockType::SignedBlock): {
|
||||
TLVBlock block[while($ < end)];
|
||||
}
|
||||
(BlockType::DeviceLicenseExpirationTime | BlockType::PollingTime | BlockType::LicenseExpirationTime): {
|
||||
s32 time;
|
||||
}
|
||||
(BlockType::PackageFullName): {
|
||||
UTF16CStr name;
|
||||
}
|
||||
(BlockType::LicenseInformation): {
|
||||
LicenseInformation information;
|
||||
}
|
||||
(BlockType::LicenseEntryIds): {
|
||||
u16 count[[hidden]];
|
||||
LicenseEntryId ids[count];
|
||||
}
|
||||
(BlockType::LicensePolicies): {
|
||||
Policy policies[while($ < end)];
|
||||
}
|
||||
(BlockType::SignatureBlock): {
|
||||
u16 something0[[hidden]];
|
||||
u16 origin;
|
||||
u8 data[while($ < end)];
|
||||
}
|
||||
(_): { u8 data[size]; }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
TLVBlock blocks[while($ < std::mem::size())] @ 0;
|
Loading…
Reference in New Issue
Block a user