Skip to content

Instantly share code, notes, and snippets.

@ShikiSuen
Created December 8, 2023 12:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ShikiSuen/6a27466ab18e9a8c9b3b4b325286f6e5 to your computer and use it in GitHub Desktop.
Save ShikiSuen/6a27466ab18e9a8c9b3b4b325286f6e5 to your computer and use it in GitHub Desktop.
"identifierForVendor" for macOS
// (c) 2023 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
/// A Swift script to check whether a non-system process is abusing the SecureEventInput.
import IOKit
import Foundation
// MARK: - macOS Support
#if canImport(AppKit)
import IOKit
// macOS 没有 UIDevice,咱们弄个冒牌的。
struct UIDevice {
static let current = UIDevice()
var identifierForVendor: UUID? {
guard let rawData = copy_mac_address() as? Data else { return nil }
var rawStr = rawData.hexadecimalString
guard !rawStr.isEmpty else { return nil}
while rawStr.count < 32 {
rawStr = rawStr + rawStr
}
var slot1 = ""
var slot2 = ""
var slot3 = ""
var slot4 = ""
var slot5 = ""
while slot1.count < 8, let firstChar = rawStr.first {
slot1.append(firstChar.description)
rawStr.removeFirst(1)
}
while slot2.count < 4, let firstChar = rawStr.first {
slot2.append(firstChar.description)
rawStr.removeFirst(1)
}
while slot3.count < 4, let firstChar = rawStr.first {
slot3.append(firstChar.description)
rawStr.removeFirst(1)
}
while slot4.count < 4, let firstChar = rawStr.first {
slot4.append(firstChar.description)
rawStr.removeFirst(1)
}
while slot5.count < 12, let firstChar = rawStr.first {
slot5.append(firstChar.description)
rawStr.removeFirst(1)
}
return UUID.init(uuidString: "\(slot1)-\(slot2)-\(slot3)-\(slot4)-\(slot5)")
}
}
// Returns an object with a +1 retain count; the caller needs to release.
// ref: https://developer.apple.com/documentation/appstorereceipts/validating_receipts_on_the_device#//apple_ref/doc/uid/TP40010573-CH1-SW14
private func io_service(named name: String, wantBuiltIn: Bool) -> io_service_t? {
let default_port: UInt32 = kIOMainPortDefault
var iterator = io_iterator_t()
defer {
if iterator != IO_OBJECT_NULL {
IOObjectRelease(iterator)
}
}
guard let matchingDict = IOBSDNameMatching(default_port, 0, name),
IOServiceGetMatchingServices(default_port,
matchingDict as CFDictionary,
&iterator) == KERN_SUCCESS,
iterator != IO_OBJECT_NULL
else {
return nil
}
var candidate = IOIteratorNext(iterator)
while candidate != IO_OBJECT_NULL {
if let cftype = IORegistryEntryCreateCFProperty(candidate,
"IOBuiltin" as CFString,
kCFAllocatorDefault,
0) {
let isBuiltIn = cftype.takeRetainedValue() as! CFBoolean
if wantBuiltIn == CFBooleanGetValue(isBuiltIn) {
return candidate
}
}
IOObjectRelease(candidate)
candidate = IOIteratorNext(iterator)
}
return nil
}
// ref: https://developer.apple.com/documentation/appstorereceipts/validating_receipts_on_the_device#//apple_ref/doc/uid/TP40010573-CH1-SW14
private func copy_mac_address() -> CFData? {
// Prefer built-in network interfaces.
// For example, an external Ethernet adaptor can displace
// the built-in Wi-Fi as en0.
guard let service = io_service(named: "en0", wantBuiltIn: true)
?? io_service(named: "en1", wantBuiltIn: true)
?? io_service(named: "en0", wantBuiltIn: false)
else { return nil }
defer { IOObjectRelease(service) }
if let cftype = IORegistryEntrySearchCFProperty(
service,
kIOServicePlane,
"IOMACAddress" as CFString,
kCFAllocatorDefault,
IOOptionBits(kIORegistryIterateRecursively | kIORegistryIterateParents)) {
return (cftype as! CFData)
}
return nil
}
// ref: https://stackoverflow.com/a/7520655/4162914
private extension Data {
var hexadecimalString: String {
let charA: UInt8 = 0x61
let char0: UInt8 = 0x30
func byteToChar(_ b: UInt8) -> Character {
Character(UnicodeScalar(b > 9 ? charA + b - 10 : char0 + b))
}
let hexChars = flatMap {[
byteToChar(($0 >> 4) & 0xF),
byteToChar($0 & 0xF)
]}
return String(hexChars)
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment