I am utilising the checkm8 exploit on my old iPad, trying to write my own implementation using the libusb-wrapper library python-libusb.
When I send a control transfer with a request of 4 (DFU_CLRSTATUS), the program just hangs there and never executes the next line of code. I've tried the following control transfers but they all produce the same result.
device._controlTransfer(0x21, 0x4, 0, 0, 0, 0, 0)
device.controlRead(0x21, 0x4, 0, 0, 0, 0)
device.controlWrite(0x21, 0x4, 0, 0, 0, 0)
This is the code leading up to the problematic block - I wonder if it's the asynchronous transfer that causes the issue?
stall(device)
for i in range(config.hole): // config.hole = 6
no_leak(device)
usb_req_leak(device)
no_leak(device)
dfu.release_device(device)
device = dfu.acquire_device()
async_ctrl_transfer(device, 0x21, 1, 0, 0, b'A' * 0x800, 0.0001)
Here is the functions that can be seen in the code:
def ctrl_transfer(
device: usb1.USBDeviceHandle,
bmRequestType: int,
bRequest: int,
wValue: int,
wIndex: int,
data_or_wLength: int = None,
timeout: float = None):
print(f"type of data_or_wLength: {type(data_or_wLength)}")
if type(data_or_wLength) is not int:
print(type(data_or_wLength))
r = device.controlWrite(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
else:
r = device.controlRead(bmRequestType, bRequest, wValue, wIndex, data_or_wLength, timeout)
def async_ctrl_transfer(
device: usb1.USBDeviceHandle,
bm_request_type: int,
b_request: int,
w_value: int,
w_index: int,
data: bytes,
timeout: float,
) -> None:
global request, transfer_ptr, never_free_device
request_timeout = int(timeout) if timeout >= 1 else 0
start = time.time()
never_free_device = device
request = array.array(
"B",
struct.pack("<BBHHH", bm_request_type, b_request, w_value, w_index, len(data))
+ data,
)
transfer_ptr = device.getTransfer(len(request))
transfer_ptr.setControl(bm_request_type, b_request, w_value, w_index, data)
transfer_ptr.submit()
while time.time() - start < timeout / 1000.0:
pass
transfer_ptr.cancel()
def stall(device: usb1.USBDeviceHandle): async_ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, b'A' * 0x10, 0.00001)
def leak(device: usb1.USBDeviceHandle): ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC0, 1)
def no_leak(device: usb1.USBDeviceHandle): ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0xC1, 1)
def usb_req_stall(device: usb1.USBDeviceHandle): ctrl_transfer(device, 0x2, 3, 0x0, 0x80, 0x0, 10)
def usb_req_leak(device: usb1.USBDeviceHandle): ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x40, 1)
def usb_req_no_leak(device: usb1.USBDeviceHandle): ctrl_transfer(device, 0x80, 6, 0x304, 0x40A, 0x41, 1)
If there is anyone who has a good knowledge with USB or iDevices, I would be more than grateful if you could offer me some guidance on how to fix this problem. Thanks for any help!
Related
I'm trying to fetch information from a hex editor. But ReadWriteMemory gives me an error about "<class 'OverflowError'>: int too long to convert"
Here is my code:
from ReadWriteMemory import ReadWriteMemory
base_address = 0x7FF6D60A0000
static_address_offset = 0x0074DE40
pointer_static_address = base_address + static_address_offset
offsets = [0x08, 0x08, 0xB0, 0x08, 0x278, 0x10, 0xD0]
rmw = ReadWriteMemory()
process = rmw.get_process_by_name('010Editor.exe')
process.open()
pointer = process.get_pointer(pointer_static_address, offsets=offsets)
pointer_value = process.read(pointer)
print(pointer_value)
How can I solve this?
I fixed it using 'pymem', So it appears that ReadWriteMemory can't handle 64bit applications.
from pymem import *
from pymem.process import *
pm = Pymem('010Editor.exe')
def GetByteNumber():
def GetPtrAddr(base, offsets):
addr = pm.read_longlong(base)
for i in offsets:
if i != offsets[-1]:
addr = pm.read_longlong(addr + i)
return addr + offsets[-1]
return pm.read_int(GetPtrAddr(pm.base_address + 0x0074DE40, offsets=[0x8, 0x8, 0x60, 0x8, 0x10, 0xB0, 0xD0]))
I got my hands on a Lego Dimensions pad which is in fact a triple NFC reader. Found some code on github to start playing with it with a raspberry pi. I've got it so far that it sends a webhook to my Home Assistant to turn on a light when placing a minifigure on the pad. Where I got stuck and my python programming skills fall short is to also send a webhook when the tag is removed. Can anyone point me in the right direction?
Thx!
#!/usr/bin/python
import usb.core
import usb.util
from time import sleep
import requests
TOYPAD_INIT = [0x55, 0x0f, 0xb0, 0x01, 0x28, 0x63, 0x29, 0x20, 0x4c, 0x45, 0x47, 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
# Colors
OFF = [0,0,0]
RED = [255,0,0]
GREEN = [0,255,0]
BLUE = [0,0,255]
YELLOW = [255,255,0]
PURPLE = [128,0,128]
# Pad number
ALL_PADS = 0
CENTER_PAD = 1
LEFT_PAD = 2
RIGHT_PAD = 3
# Actions
TAG_INSERTED = 0
TAG_REMOVED = 1
# UIDs can be retrieved with Android App (most probably in hexadecimal)
uidBatman = [4, 117, 251, 42, 41, 73, 128] # Batman Lego
uidLucy = [4, 66, 84, 114, 82, 66, 129] # Lucy Lego
uidGandalf = [4, 133, 184, 90, 181, 73, 128] # Gandalf
# Webhook var
auth_token='[Token]'
hed = {'Authorization': 'Bearer ' + auth_token}
dataon = {"state": "on"}
dataoff = {"state": "off"}
def init_usb():
global dev
dev = usb.core.find(idVendor=0x0e6f, idProduct=0x0241)
if dev is None:
print("Device not found")
else:
if dev.is_kernel_driver_active(0):
dev.detach_kernel_driver(0)
print usb.util.get_string(dev, dev.iProduct)
dev.set_configuration()
dev.write(1,TOYPAD_INIT)
return dev
def send_command(dev,command):
# calculate checksum
checksum = 0
for word in command:
checksum = checksum + word
if checksum >= 256:
checksum -= 256
message = command+[checksum]
# pad message
while(len(message) < 32):
message.append(0x00)
# send message
dev.write(1, message)
return
def switch_pad(pad, colour):
send_command(dev,[0x55, 0x06, 0xc0, 0x02, pad, colour[0], colour[1], colour[2],])
return
def main():
init_usb()
if dev != None :
while True:
try:
in_packet = dev.read(0x81, 32, timeout = 10)
bytelist = list(in_packet)
if not bytelist:
pass
elif bytelist[0] != 0x56: # NFC packets start with 0x56
pass
else:
pad_num = bytelist[2]
uid_bytes = bytelist[6:13]
action = bytelist[5]
if action == TAG_INSERTED :
print uid_bytes
if (uid_bytes == uidBatman) :
switch_pad(pad_num, RED)
url = '[URL]'
response = requests.post(url, json=dataon, headers=hed)
print(response)
print(response.json())
elif (uid_bytes == uidLucy) :
switch_pad(pad_num, PURPLE)
url = '[URL]'
response = requests.post(url, json=data, headers=hed)
print(response)
print(response.json())
elif (uid_bytes == uidGandalf) :
switch_pad(pad_num, YELLOW)
url = '[URL]'
response = requests.post(url, json=data, headers=hed)
print(response)
print(response.json())
else:
# some other tag
switch_pad(pad_num, GREEN)
else:
# some tag removed
switch_pad(pad_num, OFF)
except usb.USBError, err:
pass
switch_pad(ALL_PADS,OFF)
return
if __name__ == '__main__':
main()
I wrote this and it keeps giving me errors:
import usb.util
from time import sleep
TOYPAD_INIT = [0x55, 0x0f, 0xb0, 0x01, 0x28, 0x63, 0x29, 0x20, 0x4c, 0x45, 0x47, 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
OFF = [0,0,0]
RED = [255,0,0]
GREEN = [0,255,0]
BLUE = [0,0,255]
ALL_PADS = 0
CENTER_PAD = 1
LEFT_PAD = 2
RIGHT_PAD = 3
# Actions
TAG_INSERTED = 0
TAG_REMOVED = 1
# UIDs can be retrieved with Android App (most probably in hexadecimal)
uidDarthVader = (4, 161, 158, 210, 227, 64 , 128) # Darth Vader from Disney Infinity 3.0
def init_usb():
global dev
dev = usb.core.find(idVendor=0x0e6f, idProduct=0x0241)
if dev is None:
print('Device not found')
else:
if dev.is_kernel_driver_active(0):
dev.detach_kernel_driver(0)
print(usb.util.get_string(dev, dev.iProduct))
dev.set_configuration()
dev.write(1,TOYPAD_INIT)
return dev
def send_command(dev,command):
# calculate checksum
checksum = 0
for word in command:
checksum = checksum + word
if checksum >= 256:
checksum -= 256
message = command+[checksum]
# pad message
while(len(message) < 32):
message.append(0x00)
# send message
dev.write(1, message)
return
def switch_pad(pad, colour):
send_command(dev,[0x55, 0x06, 0xc0, 0x02, pad, colour[0], colour[1], colour[2],])
return
def uid_compare(uid1, uid2):
match = True
for i in range(0,7):
if (uid1[i] != uid2[i]) :
match = False
return match
def main():
init_usb()
if dev != None :
while True:
try:
in_packet = dev.read(0x81, 32, timeout = 10)
bytelist = list(in_packet)
if not bytelist:
pass
elif bytelist[0] != 0x56: # NFC packets start with 0x56
pass
else:
pad_num = bytelist[2]
uid_bytes = bytelist[6:13]
match = uid_compare(uid_bytes, uidDarthVader)
action = bytelist[5]
if action == TAG_INSERTED :
if match:
# Darth Vader
switch_pad(pad_num, RED)
else:
# some other tag
switch_pad(pad_num, GREEN)
else:
# some tag removed
switch_pad(pad_num, OFF)
except(usb.USBError, err):
pass
switch_pad(ALL_PADS,OFF)
return
if __name__ == '__main__':
main()
and get one of two errors:
NameError: name 'err' is not defined
or
except usb.USBError, err:
^
SyntaxError: invalid syntax
why is that? My goal is to use this for a piece of tech i'm developing. i have tried looking on the web found nothing and tried reformatting the code still didn't work, finally i tried to use the code formatting assistant and it still didn't help.
Your error is a result of the variable err being undefined.
Here I can replicate the error:
In [7]: try:
...: raise SyntaxError
...: except(SyntaxError, err):
...: print("Error message")
...:
---------------------------------------------------------------------------
SyntaxError Traceback (most recent call last)
<ipython-input-7-7c18a68f8815> in <module>
1 try:
----> 2 raise SyntaxError
3 except(SyntaxError, err):
SyntaxError: None
During handling of the above exception, another exception occurred:
NameError Traceback (most recent call last)
<ipython-input-7-7c18a68f8815> in <module>
1 try:
2 raise SyntaxError
----> 3 except(SyntaxError, err):
4 print("Error message")
5
NameError: name 'err' is not defined
Instead, try removing the err, your except line should read
except(SyntaxError):
You should also know that the github repo where you got the code that you copy-pasted is in python 2, so that is likely why you are seeing this error.
Here is a link to the source, I've taken the liberty of fixing the syntax highlighting.
I'm trying to encrypt a string in Swift 3, and my encryption is giving different output every time. Why is that? (I have tried similar encryption in python, and the encrypted output is always the same).
Here is my Swift 3 aesEncrypt function:
func aesEncrypt(key:String, iv:Array<Any>, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = sha256(string:key),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCEncrypt)
let algorithm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algorithm,
options,
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
// ADDED PRINT STATEMENTS
print("keyData")
print(keyData)
print("\(keyData as NSData)")
print("iv")
print(iv)
var hex_iv = toHexString(arr: iv as! [UInt8])
print(hex_iv)
print("data")
print(data)
print("\(data as NSData)")
print("encryption: cryptdata")
print(cryptData)
print("encryption: num bytes encrypted")
print(numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
}
else {
return nil
}
}
return nil
}
When I try to run the following code with initial_string = "hello", I get different encrypted output strings every time.
let iv [UInt8](repeating: 0, count: 16)
let key = "sample_key"
let initial_string = "hello"
let encryptedString = initial_string.aesEncrypt(key: key, iv: iv)
print("Encrypted string")
print(encryptedString)
sample output from running code with "hello" string first time:
keyData
32 bytes
<d5a78c66 e9b3ed40 b3a92480 c732527f 1a919fdc f68957d2 b7e9218f 6221085d>
iv
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
data
5 bytes
<68656c6c 6f>
encryption: cryptdata
<b17d67fc 26e3f316 6a2bdfbf 9d387c2d 00000000 00>
encryption: num bytes encrypted
16
Encrypted string
Optional("sX1n/Cbj8xZqK9+/nTh8LQ==")
sample output from running code with "hello" string second time:
keyData
32 bytes
<d5a78c66 e9b3ed40 b3a92480 c732527f 1a919fdc f68957d2 b7e9218f 6221085d>
iv
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
data
5 bytes
<68656c6c 6f>
encryption: cryptdata
<01b9f69b 45deb31d eda46c2d dc9ad9e8 00000000 00>
encryption: num bytes encrypted
16
Encrypted string
Optional("Abn2m0Xesx3tpGwt3JrZ6A==")
Can you tell me why the output is different every time for the same key, iv, and string? Thanks!
Disclaimer: I can't run the question code. Among other things it is not complete, the extension declaration is missing. Also it seems to be Swift 2 code, this needs to be at least updated to Swift 3.
encryption: cryptdata
<01b9f69b 45deb31d eda46c2d dc9ad9e8 00000000 00>
Is completely wrong, it is even the wrong length Encrypted data will be a multiple of the block size.
With PKCS#7 padding and CBC mode the encrypted result should be: C99A30D8DA44968418E8B66F42790216. See Cyyptomathic AES CALCULATOR. Note the 0b0b0b0b0b0b0b0b0b0b0b is the PKCS#7 padding.
Here is an example in Swift 3, this is not production code, it is missing error handling at a minimum.
func SHA256(string:String) -> Data {
let data = string.data(using:.utf8)!
var hashData = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
_ = hashData.withUnsafeMutableBytes {digestBytes in
data.withUnsafeBytes {messageBytes in
CC_SHA256(messageBytes, CC_LONG(data.count), digestBytes)
}
}
return hashData
}
func aesCBCEncrypt(data:Data, keyData:Data, ivData:Data) -> Data {
let cryptLength = size_t(kCCBlockSizeAES128 + data.count + kCCBlockSizeAES128)
var cryptData = Data(count:cryptLength)
var numBytesEncrypted :size_t = 0
let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
ivData.withUnsafeBytes {ivBytes in
CCCrypt(CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
CCOptions(kCCOptionPKCS7Padding),
keyBytes, keyData.count,
ivBytes,
dataBytes, data.count,
cryptBytes, cryptLength,
&numBytesEncrypted)
}}}}
cryptData.count = (cryptStatus == kCCSuccess) ? numBytesEncrypted : 0
return cryptData;
}
let keyString = "sample_key"
let keyData = SHA256(string:keyString)
print("keyString: \(keyString)")
print("keyData: \(hexEncode(keyData))")
let clearData = hexDecode("68656c6c6f")
// let keyData = hexDecode("d5a78c66e9b3ed40b3a92480c732527f1a919fdcf68957d2b7e9218f6221085d")
let ivData = hexDecode("00000000000000000000000000000000")
print("clearData: \(hexEncode(clearData))")
print("keyData: \(hexEncode(keyData))")
print("ivData: \(hexEncode(ivData))")
let cryptData = aesCBCEncrypt(data:clearData, keyData:keyData, ivData:ivData)
print("cryptData: \(hexEncode(cryptData))")
Output:
keyString: sample_key
keyData: d5a78c66e9b3ed40b3a92480c732527f1a919fdcf68957d2b7e9218f6221085d
clearData: 68656c6c6f
keyData: d5a78c66e9b3ed40b3a92480c732527f1a919fdcf68957d2b7e9218f6221085d
ivData: 00000000000000000000000000000000
cryptData: c99a30d8da44968418e8b66f42790216
you see that IV? that is initialization vector, that functions as a counter to make you encryption different each time, making it more secure and hard to break. so basically your code is working fine, but to decrypt it correctly, the receiver can not act only by having Key , but needs IV also
In the following you see a snippet of my Python program that I wrote to send APDU commands to smart cards. I used PySCard library in this program.
First Program :
for LOAD_KEY in validLoadCommands:
data,sw1,sw2 =connection.transmit(LOAD_KEY)
temp = LOAD_KEY
x= temp[3]
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=hex(LOAD_KEY[j])
print ' >>>',' Load Command :',
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=str(LOAD_KEY[j])
if len(LOAD_KEY[j])==3:
LOAD_KEY[j]=LOAD_KEY[j][0:2]+'0'+LOAD_KEY[j][2]
print LOAD_KEY[j],
print
for j in range(0,len(data)):
data[j]=hex(data[j])
print ' <<<',' Data :',
for j in range(0,len(data)):
data[j]=str(data[j])
if len(data[j])==3:
data[j]=data[j][0:2]+'0'+data[j][2]
print data[j],
print '--',hex(sw1),hex(sw2)
if (temp[2] == 0x00 or temp[2] == 0x20):
keyType = 0x60
else:
keyType = 0x61
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,temp[3]]
print 'AUTH Command: ', AUTH
data,sw1,sw2 =connection.transmit(AUTH)
print data, sw1, sw2
And its output :
Auth Command: [255, 134, 0, 0, 5, 1, 0, 4, 97, '0x0e']
Traceback (most recent call last):
File "C:\Users\Erb4h1m\Desktop\Faraadis Alborz Card Reader\CRT-603-CZ1_Read1Block.py", line 199, in <module>
data,sw1,sw2 =connection.transmit(AUTH)
File "D:\Software\Python27\lib\site-packages\smartcard\CardConnectionDecorator.py", line 82, in transmit
return self.component.transmit(bytes, protocol)
File "D:\Software\Python27\lib\site-packages\smartcard\CardConnection.py", line 140, in transmit
data, sw1, sw2 = self.doTransmit(bytes, protocol)
File "D:\Software\Python27\lib\site-packages\smartcard\pcsc\PCSCCardConnection.py", line 173, in doTransmit
hresult, response = SCardTransmit(self.hcard, pcscprotocolheader, bytes)
File "D:\Software\Python27\lib\site-packages\smartcard\scard\scard.py", line 1329, in SCardTransmit
return _scard.SCardTransmit(*args)
TypeError: Expected a list of bytes.
And when I replace temp[3] with x:
for LOAD_KEY in validLoadCommands:
data,sw1,sw2 =connection.transmit(LOAD_KEY)
temp = LOAD_KEY
x= temp[3]
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=hex(LOAD_KEY[j])
print ' >>>',' Load Command :',
for j in range(0,len(LOAD_KEY)):
LOAD_KEY[j]=str(LOAD_KEY[j])
if len(LOAD_KEY[j])==3:
LOAD_KEY[j]=LOAD_KEY[j][0:2]+'0'+LOAD_KEY[j][2]
print LOAD_KEY[j],
print
for j in range(0,len(data)):
data[j]=hex(data[j])
print ' <<<',' Data :',
for j in range(0,len(data)):
data[j]=str(data[j])
if len(data[j])==3:
data[j]=data[j][0:2]+'0'+data[j][2]
print data[j],
print '--',hex(sw1),hex(sw2)
if (temp[2] == 0x00 or temp[2] == 0x20):
keyType = 0x60
else:
keyType = 0x61
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType, x]
print 'AUTH Command: ', AUTH
data,sw1,sw2 =connection.transmit(AUTH)
print data, sw1, sw2
Then the output is:
AUTH: [255, 134, 0, 0, 5, 1, 0, 4, 97, 14]
[] 144 0
As you see above, in the second case I DON'T receive any error, while there is no difference between first program and second program! I only replaced
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,temp[3]]
with:
AUTH = [0xFF, 0x86, 0x00, 0x00, 0x05, 0x01, 0x00, blockNum, keyType,x]
and x is initialized with temp[3] in the top of program. neither x nor temp[3] didn't changed between the line of initialization and the line of error.
What is going here?
Your temp variable reference LOAD_KEY (Line 3: temp = LOAD_KEY)
When x= temp[3] get called, it's the value of LOAD_KEY at index 3 right after your connection.transmit that is set.
When you are sending temp[3] for your AUTH, LOAD_KEY have changed and so does temp[3]. So it's not anymore the same value as x.
connection.transmit => LOAD_KEY is set => temp => [3] => x
*** LOAD_KEY changes ***
x => old value of temp[3] aka LOAD_KEY[3]
temp[3] => whatever your code have put in it
Edit: short example
>>> LOAD_KEY = ['one', 'two', 'three', 'four']
>>> temp = LOAD_KEY
>>> x = temp[3]
>>> LOAD_KEY[3] = 'new value'
>>>
>>> LOAD_KEY[3]
'new value'
>>> temp[3]
'new value'
>>> x
'four'
In you first example, temp[3] is a string ('0x0e').
In your second example, x is an integer (14).
This is because you're converting the integer values of the LOAD_KEY list to an hexadecimal string with the following line:
LOAD_KEY[j] = hex(LOAD_KEY[j])
In order to convert a string in hexadecimal representation to an integer, use the second argument of the built-in type int to set the base to 16:
>>> int('0x0e', 16)
14