Research-Stack/5-Applications/scripts/chipsbank_investigator.py

147 lines
5.6 KiB
Python

import usb.core
import usb.util
import struct
import time
# Chipsbank / ITE CBM2199
# VID: 0x048d, PID: 0x1234
VID = 0x048d
PID = 0x1234
class ChipsbankBOT:
def __init__(self, vid, pid):
self.dev = usb.core.find(idVendor=vid, idProduct=pid)
if self.dev is None:
raise ValueError("Device not found")
# Detach kernel driver if necessary (Linux)
if self.dev.is_kernel_driver_active(0):
try:
self.dev.detach_kernel_driver(0)
print("[*] Detached kernel driver")
except usb.core.USBError as e:
print(f"[!] Could not detach driver: {e}")
# Set configuration
try:
self.dev.set_configuration()
except usb.core.USBError as e:
print(f"[!] Could not set configuration: {e}")
cfg = self.dev.get_active_configuration()
intf = cfg[(0,0)]
# Find Bulk endpoints
self.ep_out = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT)
self.ep_in = usb.util.find_descriptor(intf, custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN)
if not self.ep_out or not self.ep_in:
raise ValueError("Endpoints not found")
self.tag = 0xDEADBEEF
def send_cbw(self, cmd, data_len, direction_in=True):
"""Constructs and sends a 31-byte Command Block Wrapper."""
self.tag += 1
flags = 0x80 if direction_in else 0x00
# Signature 'USBC', Tag, DataLen, Flags, LUN, CmdLen, CmdBlock(16 bytes)
cbw = struct.pack("<4sIIBB B 16s", b"USBC", self.tag, data_len, flags, 0, len(cmd), cmd.ljust(16, b'\x00'))
self.ep_out.write(cbw)
return self.tag
def receive_csw(self, expected_tag):
"""Reads the 13-byte Command Status Wrapper."""
try:
data = self.ep_in.read(13, timeout=2000)
if len(data) < 13:
print(f"[!] CSW truncated: {len(data)} bytes")
return -1
# Signature 'USBS', Tag, Residue, Status
sig, tag, residue, status = struct.unpack("<4sIIB", data)
if sig != b"USBS":
print(f"[!] CSW Invalid Signature: {sig}")
if tag != expected_tag:
print(f"[!] CSW Tag Mismatch: {tag} (Expected {expected_tag})")
return status
except usb.core.USBError as e:
print(f"[!] CSW Read Error: {e}")
return -1
def execute_command(self, cmd, data_len, direction_in=True):
"""Full BOT transaction: CBW -> Data -> CSW."""
try:
tag = self.send_cbw(cmd, data_len, direction_in)
payload = None
if data_len > 0:
if direction_in:
payload = self.ep_in.read(data_len, timeout=2000)
else:
# For OUT commands, you would send data here
pass
status = self.receive_csw(tag)
return status, payload
except usb.core.USBError as e:
print(f"[!] Command Execution Error: {e}")
# Try to clear stall
try:
self.dev.clear_halt(self.ep_in.bEndpointAddress)
self.dev.clear_halt(self.ep_out.bEndpointAddress)
except: pass
return -1, None
def scsi_inquiry(self):
"""Standard SCSI Inquiry (0x12)."""
print("[*] Sending SCSI Inquiry...")
cmd = struct.pack("B B B B B B", 0x12, 0, 0, 0, 36, 0)
status, data = self.execute_command(cmd, 36)
if status == 0 and data:
data_bytes = data.tobytes() if hasattr(data, 'tobytes') else bytes(data)
vendor = data_bytes[8:16].decode('ascii', 'ignore').strip()
product = data_bytes[16:32].decode('ascii', 'ignore').strip()
rev = data_bytes[32:36].decode('ascii', 'ignore').strip()
print(f" [+] Success! Vendor: {vendor}, Product: {product}, Rev: {rev}")
return data
def probe_vendor_command(self, opcode, sub, desc):
print(f"[*] Probing Vendor Command: {desc} ({hex(opcode)} {hex(sub)})...")
# Chipsbank style: [Opcode, Sub, ...]
cmd = struct.pack("B B 14x", opcode, sub)
status, data = self.execute_command(cmd, 36) # Try 36 bytes for info
if status == 0 and data:
data_bytes = data.tobytes() if hasattr(data, 'tobytes') else bytes(data)
print(f" [+] Success! Data: {data_bytes.hex().upper()}")
# Try to decode as ASCII
try:
print(f" [+] ASCII: {data_bytes.decode('ascii', 'ignore')}")
except: pass
else:
print(f" [-] Command rejected or failed (Status: {status})")
if __name__ == "__main__":
try:
bot = ChipsbankBOT(VID, PID)
bot.scsi_inquiry()
# Test common vendor entrance points
# Chipsbank: 0xEF, 0xF0, 0xF1, 0x06
# ITE: 0x8A, 0xBE, 0xFE
probes = [
(0xEF, 0xF1, "Chipsbank Get Info"),
(0xEF, 0x06, "Chipsbank Read FID"),
(0xF0, 0x01, "Chipsbank Alt Get Info"),
(0x8A, 0x01, "ITE Get Info"),
(0xBE, 0x01, "ITE Read FID"),
(0xFE, 0x00, "Generic Vendor Inquiry")
]
for op, sub, desc in probes:
bot.probe_vendor_command(op, sub, desc)
time.sleep(0.5)
except Exception as e:
print(f"Error: {e}")
finally:
print("[*] Re-attaching kernel driver...")
# Re-attach logic would go here if needed, but dev.reset() is easier