Created
July 8, 2015 08:23
-
-
Save shuffle2/9b9e9cc093060be975f9 to your computer and use it in GitHub Desktop.
powersaves-amiibo-frida stuffs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Input MD5 : BB4E83D7A77AADD7F62728314EF09461 | |
File Name : C:\Program Files (x86)\Powersaves For AMIIBO\Powersaves For AMIIBO.exe | |
0x108fd0 : schannel_recv -> log buffer on end | |
0x1090d0 : schannel_recv end | |
0x108d10 : schannel_send -> log buffer on start | |
0xce61 : deals with https "Token" | |
0xceab : deals with https "Vuid" | |
0x9366 : the usb initialization func | |
0xe0fd0 : libusb_open_device_with_vid_pid -> return 0xdeadbeef | |
0xe14d0 : libusb_claim_interface -> return 0 | |
0xe1590 : libusb_release_interface -> nop | |
0xe1310 : libusb_close -> nop | |
0xe2460 : libusb_bulk_transfer | |
0xe2480 : libusb_interrupt_transfer | |
.restart | |
bp psfa+0x936b "r @eax=0xdeadbeef; gc" | |
bp psfa+0x9376 "r @eip=@eip+5; gc" | |
bp psfa+0x93c3 "r @eip=@eip+0x1e; gc" | |
g | |
''' | |
import frida | |
import time | |
def create_script(session, name): | |
return session.create_script(name = name, source = open('./' + name + '.js', 'r').read()) | |
pid = frida.spawn(['..\psfa.exe']) | |
session = frida.attach(pid) | |
print('attached to pid %i' % (pid)) | |
ssl_log = create_script(session, 'schannel-logger') | |
ssl_log.load() | |
usb_sim = create_script(session, 'usb-sim') | |
usb_sim.load() | |
frida.resume(pid) | |
while True: | |
time.sleep(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
base = Module.findBaseAddress('psfa.exe'); | |
/* | |
static ssize_t | |
schannel_send(struct connectdata *conn, int sockindex, | |
const void *buf, size_t len, CURLcode *err) | |
*/ | |
schannel_send_addr = base.add(0x108d10); | |
schannel_recv_addr = base.add(0x108fd0); | |
Interceptor.attach(schannel_send_addr, { | |
onEnter: function(args) { | |
var buf = args[2]; | |
var len = args[3]; | |
console.log('schannel_send{buf:' + buf.toString(16) + ', len: ' + len.toString(16) + '}'); | |
try { | |
console.log(Memory.readCString(buf, len.toInt32())); | |
var f = new File('schannel-send.' + buf.toString(16) + '.bin', 'wb'); | |
f.write(Memory.readByteArray(buf, len.toInt32())); | |
f.flush(); | |
//f.close(); // does not work for some reason | |
} catch (e) { | |
console.log(e); | |
} | |
} | |
}); | |
Interceptor.attach(schannel_recv_addr, { | |
onEnter: function(args) { | |
this.buf = args[2]; | |
this.len = args[3]; | |
console.log('schannel_recv{buf:' + this.buf.toString(16) + ', len: ' + this.len.toString(16) + '}'); | |
}, | |
onLeave: function(retval) { | |
try { | |
console.log(Memory.readCString(this.buf, this.len.toInt32())); | |
} catch (e) { | |
console.log(e); | |
} | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
0xe0fd0 : libusb_open_device_with_vid_pid -> return 0xdeadbeef | |
0xe14d0 : libusb_claim_interface -> return 0 | |
0xe1590 : libusb_release_interface -> nop | |
0xe1310 : libusb_close -> nop | |
0xe2460 : libusb_bulk_transfer -> simulate | |
0xe2480 : libusb_interrupt_transfer -> simulate | |
*/ | |
base = Module.findBaseAddress('psfa.exe'); | |
libusb_open_device_with_vid_pid_addr = base.add(0xe0fd0) | |
libusb_claim_interface_addr = base.add(0xe14d0); | |
libusb_release_interface_addr = base.add(0xe1590); | |
libusb_close_addr = base.add(0xe1310); | |
do_sync_bulk_transfer_addr = base.add(0xe2310); | |
use_real_device = false; | |
if (!use_real_device) { | |
Interceptor.replace(libusb_open_device_with_vid_pid_addr, new NativeCallback(function() { | |
//console.log('libusb_open_device_with_vid_pid'); | |
return 0xdeadbeef; | |
}, 'int', ['pointer', 'uint32'], 'thiscall')); // not actual signature, but the compiler was fucky | |
Interceptor.replace(libusb_claim_interface_addr, new NativeCallback(function() { | |
console.log('libusb_claim_interface'); | |
return 0; | |
}, 'int', [])); // luckily sig doesn't matter (fucked by LTCG) | |
Interceptor.replace(libusb_release_interface_addr, new NativeCallback(function(interface_number) { | |
console.log('libusb_release_interface'); | |
return 0; | |
}, 'int', ['int'], 'stdcall'));// device handle in edi | |
Interceptor.replace(libusb_close_addr, new NativeCallback(function(dev_handle) { | |
//console.log('libusb_close'); | |
}, 'void', ['pointer'], 'stdcall')); | |
// simply patch out the desc.bcdDevice check | |
var descriptor_check_addr = base.add(0x93c3); | |
var skip_descriptor_check = [ | |
0x59, // pop ecx | |
0xE9, 0x19, 0x00, 0x00, 0x00 // jmp +0x1d | |
]; | |
Memory.protect(descriptor_check_addr, skip_descriptor_check.length, 'rwx'); | |
Memory.writeByteArray(descriptor_check_addr, skip_descriptor_check); | |
} | |
function b2h_byte(value) { | |
var str = value.toString(16); | |
return '00'.substring(str.length) + str; | |
} | |
function b2h(arr) { | |
var str = ''; | |
for (var i = 0; i < arr.length; i++) { | |
str += ' ' + b2h_byte(arr[i]); | |
} | |
return str; | |
} | |
/* | |
It only uses endpoint 1, with bulk for OUT and interrupt for IN transfers and constant buffer sizes | |
*/ | |
var xfer_cmd = 0; | |
var xfer_page = 0; | |
var do_sync_bulk_transfer = new NativeFunction(do_sync_bulk_transfer_addr, | |
'int', ['pointer', 'uchar', 'pointer', 'pointer', 'uchar']); | |
Interceptor.replace(do_sync_bulk_transfer_addr, | |
new NativeCallback(function(dev_handle, endpoint, buffer, transferred, type) { | |
var is_interrupt = type == 3; | |
// the compiler has been smart enough to lower the constants length and timeout into the implementation | |
var length = 0x40; | |
if (is_interrupt) { | |
var data = []; | |
for (var i = 0; i < length; i++) { | |
//data.push(Math.random() * 0xff); | |
data.push(0); | |
} | |
switch (xfer_cmd) { | |
case 2: | |
// This gets a string identifier: | |
// 4e 46 43 2d 50 6f 72 74 61 6c - "NFC-Portal" | |
// Result isn't checked | |
break; | |
case 0x90: | |
// This appears to get some model/unique ID info or something. | |
// 01 ff ff 16 a3 66 30 43 62 6c 23 bd 69 5d c3 33 f0 2d 3f | |
// Result isn't checked. | |
data = [0, 0]; | |
for (var i = 0; i < 0x13; i++) { | |
data.push(Math.random() * 0xff); | |
} | |
break; | |
case 0x80: | |
// decrypt Vuid via "SAM12" | |
// Result checked by server | |
if (use_real_device) { | |
do_sync_bulk_transfer(dev_handle, endpoint, buffer, transferred, type); | |
console.log('DEC(Vuid): ' + Memory.readCString(buffer.add(2), 16)); | |
} else { | |
data = [0, 0]; | |
for (var i = 0; i < 0x10; i++) { | |
data.push(Math.random() * 0xff); | |
} | |
} | |
break; | |
case 0x11: | |
case 0x10: | |
case 0x12: | |
case 0x20: | |
break; | |
case 0x1c: // read page | |
data = [0, 0]; | |
for (var i = 0; i < 0x10; i++) { | |
data.push(Math.random() * 0xff); | |
} | |
break; | |
case 0x1d: // write page | |
break; | |
} | |
if (!use_real_device || xfer_cmd != 0x80) { | |
Memory.writeByteArray(buffer, data); | |
} | |
} else if (use_real_device) { | |
switch (Memory.readU8(buffer)) { | |
case 0x80: | |
// Need to forward the bulk xfers so the real device knows what's coming! | |
do_sync_bulk_transfer(dev_handle, endpoint, buffer, transferred, type); | |
break; | |
} | |
} | |
var buf = Memory.readByteArray(buffer, length); | |
if (!is_interrupt) { | |
xfer_cmd = buf[0]; | |
} | |
var msg = is_interrupt ? '<-' : '->'; | |
msg += b2h(buf); | |
console.log(msg); | |
Memory.writeU32(transferred, length + (is_interrupt ? 0 : 1)); | |
return 0; | |
}, 'int', ['pointer', 'uchar', 'pointer', 'pointer', 'uchar']) | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment