Skip to content

Instantly share code, notes, and snippets.

@mrdekk
Created December 25, 2019 06:17
Show Gist options
  • Save mrdekk/28893926c41d7222046a2223b313a15a to your computer and use it in GitHub Desktop.
Save mrdekk/28893926c41d7222046a2223b313a15a to your computer and use it in GitHub Desktop.
print all available framebuffers
// Created by mrdekk on 24/12/2019.
//
// Original PHP code was taken here https://www.tonymacx86.com/threads/apple-intel-amd-ati-framebuffers.112299/post-1640375 and attributed to 'Pavo'
import Foundation
import Cocoa
let portMapping: [String: String] = [
"02000000": "LVDS",
"04000000": "DVI-D",
"08000000": "SVIDEO",
"10000000": "VGA",
"00020000": "DVI-SL",
"00040000": "DP",
"00080000": "HDMI",
"00100000": "UNKNOWN"
]
do {
let contents = try FileManager.default.contentsOfDirectory(atPath: "/System/Library/Extensions")
for kext in contents {
guard (kext.hasPrefix("AMD") || kext.hasPrefix("ATI")) else {
continue
}
guard kext.hasSuffix("Controller.kext") else {
continue
}
print("KEXT: \(kext)")
let kb: String? = {
do {
let path = "/System/Library/Extensions/\(kext)/Contents/MacOS"
let pathFiles = try FileManager.default.contentsOfDirectory(atPath: path)
if !pathFiles.isEmpty {
return "\(path)/\(pathFiles[0])"
}
} catch {
}
return nil
}()
guard let kextBinary = kb else {
continue
}
print(" binary: \(kextBinary)")
let task = Process()
let pipe = Pipe()
task.launchPath = "/usr/bin/otool"
task.arguments = ["-Xvt", kextBinary]
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let result = String(data: data, encoding: .utf8)
task.waitUntilExit()
guard let lines = result?.split(whereSeparator: { $0.isNewline }) else {
continue
}
var i = 0
while (i < lines.count) {
let line = lines[i]
if !line.hasPrefix("__ZN") || !line.contains("Info10createInfo") {
i += 1
continue
}
guard
let lesser = line.range(of: "__ZN")?.upperBound,
let upper = line.range(of: "Info10createInfo")?.lowerBound
else {
i += 1
continue
}
let framebufferName = String(line[lesser..<upper]).filter { $0.isLetter }
var addr: Int = -1
var ports: Int = -1
var ji: Int = -1
while i < lines.count && !lines[i].contains("ret") {
let lx = lines[i]
if lx.contains("leaq") {
let adri = lx.index(lx.startIndex, offsetBy: 8 /*6*/)
if let strpos = lx.range(of: "(")?.lowerBound {
let adr = lx[adri..<strpos]
if let adrint = Int(adr, radix: 16) {
addr = adrint
}
}
} else if ports == -1 && lx.contains("movb\t$") {
if let adri = lx.range(of: "$")?.upperBound, let adrj = lx.range(of: ",")?.lowerBound {
let adr = lx[adri..<adrj].dropFirst(2)
if let adrint = Int(adr, radix: 16) {
ports = adrint
}
}
} else if lx.contains("jl") {
let adr = lx.dropFirst(4)
if let adrint = Int(adr, radix: 16) {
ji = adrint
print(" \(ji)")
}
} else if lx.contains("jmp") {
let adr = lx.dropFirst(5).dropFirst(2)
if let adrint = Int(adr, radix: 16) {
ji = adrint + 0x1A
}
}
i += 1
}
addr += ji
print(" \(framebufferName) (\(ports)) @ 0x\(String(addr, radix: 16))")
do {
let data = try Data(contentsOf: URL(fileURLWithPath: kextBinary))
for ip in 0..<ports {
let saddr = addr + ip * 24 + 8
let xdata = data.subdata(in: saddr..<(saddr + 24))
let hexed = xdata.map { String(format: "%02hhx", $0) }.joined()
let portstr = String(hexed[hexed.startIndex..<hexed.index(hexed.startIndex, offsetBy: 8)])
let port = portMapping[portstr] ?? "-"
print(" \(hexed) \(port)")
}
} catch {
print(" FAILED: \(error)")
}
}
}
} catch {
print(error)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment