uunicorn / python-validity

Validity fingerprint sensor prototype
MIT License
941 stars 80 forks source link

Working with 06cb:009a Synaptics, Inc. #3

Open javierfileiv opened 4 years ago

javierfileiv commented 4 years ago

Hi there, I'm trying to make work this fp.

I saw that there are blobs_90.py are blobs_97.py . Are these binary blobs taken from the firmware extracted from the windows installer?

How can I know which one is init_hardcoded , init_hardcoded_clean_slate, etc ?

Thanks for your reply

uunicorn commented 4 years ago

Are these binary blobs taken from the firmware extracted from the windows installer?

I'm quite confident these blobs are pieces of code which Windows driver dynamically uploads and executes on the device. They are hard-coded inside the driver .dll.

How can I know which one is init_hardcoded , init_hardcoded_clean_slate, etc ?

You can use this project https://github.com/uunicorn/synaWudfBioUsb-sandbox to snoop on Windows driver to see which blobs are loaded into your device and when.

storm1ng commented 4 years ago

The firmware's name for 009a is 6_07f_lenovo_mis_qm.xpfwext (extracted from nz3gf07w.exe.

I will try and extract the blobs. Let's see how it goes.

javierfileiv commented 4 years ago

Thanks @mjenny , could you please share after the extract? :)

storm1ng commented 4 years ago

@javierfileiv sure, if I'm able to extract them. :) I'm currently in the process of compiling wine.

uunicorn commented 4 years ago

I can assist you in finding the blobs if you can manage to get synaWudfBioUsb-sandbox running. In addition to the firmware file itself, you will also need to extract synawudfbiousb.dll from your Windows diver. If all good, wine64 a.exe will spit tons of output. Redirect it to a file and upload somewhere so I can have a look. Good luck.

storm1ng commented 4 years ago

@uunicorn I already have the DLL and the firmware extracted. I will let you know as soon as I have wine up and running.

I am currently compiling wine inside a VM running on my Lenovo X1 Extreme. Not sure if that will be sufficient. If not I will install Arch Linux or Linux Mint for a faster install. 😄

storm1ng commented 4 years ago

Hm... I should have tried to passthrough the fingerprint reader earlier. I guess Intel Secure Guard Extension is a problem or the fact that I have enabled WSL2 and have to go through Hyper-V.

storm1ng commented 4 years ago

@uunicorn do I have to put the firmware file somewhere to run a.exe?

uunicorn commented 4 years ago

Both .xpfwext and .dll should be placed in the same directory with a.exe.

I'm no expert, but if you're running a host on Windows, it may be hard to pass the reader USB device to a Linux guest. Windows diver may have claimed the same device and could interfere with a communication. But yeah, IDK, I never tried that.

storm1ng commented 4 years ago

@uunicorn I installed Linux Mint for now. Will do everything over again. Am I still supposed to compile wine myself (regarding hacks)?

uunicorn commented 4 years ago

Yes. Hacks have a bunch of printfs sprinkled all over the crypto routines. Those are actually used to dump all the communication between a device and a driver. Including the missing blobs. Hacks also include a fake winusb.dll implementation which lets synawudfbiousb.dll talk to a real USB device. Vanilla wine does not have this DLL.

Which reminds me that you'd probably want to change this line before building Wine: https://github.com/uunicorn/wine/blob/7ed3db9743a525228fb6306ab0d8d0f8b4163e00/dlls/winusb/winusb.c#L16

storm1ng commented 4 years ago

I'm currently back to building wine with the aforementioned changes.

storm1ng commented 4 years ago

@uunicorn I successfully built wine and it worked fine so far. However, I don't have a wine64 executable. And when running WINEARCH=~/.wine-fingerprint wine a.exe I get a wine: Bad EXE format for Z:\home\mjenny\wine\a.exe..

I assume that a.exe which I downloaded directly from your repo (I didn't build it myseld) is using 64-bit, right (a.exe: PE32+ executable (console) x86-64, for MS Window)?

Do I have to build wine differently?

storm1ng commented 4 years ago

Nvm, I missed --enable-win64...

storm1ng commented 4 years ago

Ok, I have everything running.

@uunicorn how do I know that a.exe was successfully run? I am now getting a Program Error during execution. There seems to be an Unhandled page fault:

USB >>>>>>>>>> In DllMain reason=1
USB >>>>>>>>>> WinUsb_Initialize
wine: Unhandled page fault on read access to 0x00000040 at address 0x7f1005121a44 (thread 0009), starting debugger...
storm1ng commented 4 years ago

@uunicorn here is the link to the logfile: logfile.txt

uunicorn commented 4 years ago

@mjenny it looks like it crashed because it failed to find your USB device.

Can you check that the device vendor and the product id in /dlls/winusb/winusb.c are actually matching your hardware?

By default it is

#define MY_VENDOR   0x138a
#define MY_PRODUCT  0x0097

which corresponds to 0097 device. If you have a 009a, you should probably change MY_PRODUCT to 0x009a, but it would be best if you can double check with lsusb:

$ lsusb 
...
Bus 001 Device 005: ID 138a:0097 Validity Sensors, Inc. <---- my device
...
$ 

how do I know that a.exe was successfully run?

a.exe should let you enroll a finger.

storm1ng commented 4 years ago

I should have known it better... I was thinking about changing #define MY_VENDOR to 06cb which is what my lsusb is printing:

...
Bus 001 Device 003: ID 06cb:009a Synaptics, Inc.
...

I'll rebuild wine then and let you know how it goes.

storm1ng commented 4 years ago

@uunicorn It looks better know. Do I have to run wine64 as root to be able to access the USB device?

0009:trace:reg:NtQueryValueKey (0x60,L"SignatureKeyPair",2,0x332d20,256)
USB >>>>>>>>>> In DllMain reason=1
USB >>>>>>>>>> WinUsb_Initialize
!!!!!!!!!!!! Found device 06cb:009a
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/001/003: Permission denied
libusb: error [_get_usbfs_fd] libusb requires write access to USB device nodes.
Failed 'libusb_open(dev_list[i], &info->dev)': -3 - LIBUSB_ERROR_ACCESS
0010:trace:reg:open_key ((nil),L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName",20019,0x7df700)
0010:trace:reg:open_key <- 0xb8
0010:trace:reg:open_key (0xb8,L"ActiveComputerName",20019,0x7df708)
0010:trace:reg:open_key <- 0x15c
0010:trace:reg:NtQueryValueKey (0x15c,L"ComputerName",2,0x7df750,44)
0010:trace:reg:open_key ((nil),L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName",20019,0x7df700)
0010:trace:reg:open_key <- 0x168
0010:trace:reg:open_key (0x168,L"ActiveComputerName",20019,0x7df708)
0010:trace:reg:open_key <- 0x15c
0010:trace:reg:NtQueryValueKey (0x15c,L"ComputerName",2,0x7df750,44)
002e:trace:reg:RegDeleteTreeW (0x24, L"Winedevice1")
002e:trace:reg:open_key (0x24,L"Winedevice1",20019,0x1c7fa98)
002e:trace:reg:open_key <- (nil)
0010:trace:reg:RegDeleteTreeW (0x24, L"Winedevice2")
0010:trace:reg:open_key (0x24,L"Winedevice2",20019,0x7dfaa8)
0010:trace:reg:open_key <- (nil)
uunicorn commented 4 years ago

I've got a custom udev rule:

/etc/udev/rules.d/10-fpreader.rules:ATTRS{idVendor}=="138a", ATTRS{idProduct}=="0097", OWNER="unicorn"

But you can chown it manually. It's gonna be reset after reboot or when device re-connects.

storm1ng commented 4 years ago

@uunicorn I chowned the device and the logfile.txt looks promissing: logfile.txt However, I still was not able to enroll a finger.

>>>>>>>>>>> xfer Failed - LIBUSB_ERROR_NO_DEVICE
uunicorn commented 4 years ago

That could mean that device just finished pairing and has restarted. Chown again and give it another go. It may take a couple of tries.

uunicorn commented 4 years ago

Or may be not. I can't see it's sending any firmware. But the last message the host sent to a device was a "reboot" command (which caused USB device to disconnect):

USB a03700 >>>>>>>>>> WinUsb_WritePipe PipeID=1
>>> 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
rc=0 send=98

You may need to put the firmware file in some other place, where the driver is looking for it. Not sure where though.

storm1ng commented 4 years ago

I couldn't find anything in regards to that inside synaWudfBioUsbLenovoMiSSGXProd.inf (which is the only inf file I could find): synaWudfBioUsbLenovoMiSSGXProd.inf

uunicorn commented 4 years ago

What do you mean? Here it is:

[DestinationDirs]
...
WinBioSensorAdapterCopy=11, WinBioPlugins; copy to \Windows\System32\WinBioPlugins
FWextCopy=11
...
[FWextCopy]
6_07f_lenovo_mis_qm.xpfwext
...

Try copying it to \Windows\System32\WinBioPlugins in your Wine prefix. E.g ~/.wine/driver_c/Windows/System32/WinBioPlugins/ You may need to create WinBioPlugins directory.

storm1ng commented 4 years ago

Dang, I missed that completely... It is now using the firmware file from what I can tel. However, the result is the same, no matter how many times I try. The pairing is working fine and it will be recognized as new USB device for which my user is still the owner. ls -la /dev/bus/usb/001 Before the run:

total 0
drwxr-xr-x 2 root   root     160 Jun 22 06:53 .
drwxr-xr-x 6 root   root     120 Jun 22 05:56 ..
crw-rw-r-- 1 root   root 189,  0 Jun 22 05:56 001
crw-rw-r-- 1 root   root 189,  1 Jun 22 05:56 002
crw-rw-r-- 1 root   root 189,  3 Jun 22 05:56 004
crw-rw-r-- 1 root   root 189,  4 Jun 22 05:56 005
crw-rw-r-- 1 root   root 189,  5 Jun 22 05:56 006
crw-rw-r-- 1 mjenny root 189, 16 Jun 22 06:53 017

After the run:

total 0
drwxr-xr-x 2 root   root     160 Jun 22 06:54 .
drwxr-xr-x 6 root   root     120 Jun 22 05:56 ..
crw-rw-r-- 1 root   root 189,  0 Jun 22 05:56 001
crw-rw-r-- 1 root   root 189,  1 Jun 22 05:56 002
crw-rw-r-- 1 root   root 189,  3 Jun 22 05:56 004
crw-rw-r-- 1 root   root 189,  4 Jun 22 05:56 005
crw-rw-r-- 1 root   root 189,  5 Jun 22 05:56 006
crw-rw-r-- 1 mjenny root 189, 16 Jun 22 06:54 018

logfile.txt I'll continue to try.

storm1ng commented 4 years ago

Do you think that the new device number is the issue and that xfer can no longer find the device?

uunicorn commented 4 years ago

No, host is requesting device to reboot before it disconnects. USB comms are fine. By the looks of it, the device was not partitioned properly yet. I'll have a closer look in a while, thanks for trying - some of the blobs are already in the output. Did you capture the output from all your attempts?

storm1ng commented 4 years ago

No, but I can create a few more and upload them if it helps.

uunicorn commented 4 years ago

Can you use factory-reset.py and try again? Try to log everything when running a.exe, as the device has a state and running it twice in a row may give different results.

storm1ng commented 4 years ago

Ok, I will try that. I moved the already uploaded logfile.txt on my server: logfile.txt

uunicorn commented 4 years ago

Looking at the logs, I'm pretty sure it's having troubles sending the firmware. Likely it still can't find the firmware file. Where have you copied it to?

storm1ng commented 4 years ago

I have copied it to ~/.wine-fingerprint/drive_c/windows/system32/WinBioPlugins/6_07f_lenovo_mis_qm.xpfwext

When I run factory-reset.py I receive the following error:

~/python-validity$ python3 factory-reset.py 
Traceback (most recent call last):
  File "factory-reset.py", line 5, in <module>
    usb.open()
  File "/home/mjenny/python-validity/proto9x/usb.py", line 28, in open
    self.dev.default_timeout = 15000
AttributeError: 'NoneType' object has no attribute 'default_timeout'
uunicorn commented 4 years ago

Try also copying it to ~/.wine-fingerprint/drive_c/windows/system32/ ~/.wine-fingerprint -- that is what your WINEPREFIX env variable is pointing at, right?

storm1ng commented 4 years ago

BTW: my env.sh file looks like this:

#!/bin/bash

export WINEPATH=/usr/lib/gcc/x86_64-w64-mingw32/9.3-win32
export WINEPREFIX=~/.wine-fingerprint
export WINEDEBUG=trace+rsaenh,trace+reg,trace
storm1ng commented 4 years ago

It worked!! Can I Ctrl-C after an enrolment?

uunicorn commented 4 years ago

Yay. I think so. So, I guess copying it to system32 helped. Send some logs :)

storm1ng commented 4 years ago

Just to be sure, will the logfile.txt contain any fingerprint data if I touched the sensor?

storm1ng commented 4 years ago

This is a log file with the fingerprint reader lit up (without me touching it): logfile7.txt

uunicorn commented 4 years ago

Yes it will, but if 009a is similar to 0097, your biometric data will be encrypted. But everything up to the actual scanning should be enough for now. Thanks!

storm1ng commented 4 years ago

This is with one enrolment (not my finger but it recognized the enrolment :smile: ): logfile6.txt

uunicorn commented 4 years ago

It would be nice if you can do a factory reset and start over, making sure that you log the output for each run. Some of the blobs only appear in case of a clean slate. Can you check that your USB vendor/product is present in proto*/usb.py before running the factory-reset.py?

storm1ng commented 4 years ago

I should have come up with this myself, sorry. :smile: Normally I am developing Java and React stuff.

I still get an error regarding the blobs.py:

Traceback (most recent call last):
  File "factory-reset.py", line 6, in <module>
    factory_reset()
  File "/home/mjenny/python-validity/proto9x/sensor.py", line 283, in factory_reset
    assert_status(usb.cmd(reset_blob))
  File "/home/mjenny/python-validity/proto9x/usb.py", line 57, in cmd
    out = out()
  File "/home/mjenny/python-validity/proto9x/blobs.py", line 27, in <lambda>
    globals()[p] = lambda bname=p: __load_blob(bname)
  File "/home/mjenny/python-validity/proto9x/blobs.py", line 22, in __load_blob
    globals()[blob] = getattr(blobs, blob)
UnboundLocalError: local variable 'blobs' referenced before assignment

I know that I'll have to edit blobs.py as well but therefore I would need the corresponding blobs inside blobs_9a.py, right?

storm1ng commented 4 years ago

I already extended blobs.py:

    if usb.usb_dev().idVendor == 0x138a:
        if usb.usb_dev().idProduct == 0x0090:
            from . import blobs_90 as blobs
        elif usb.usb_dev().idProduct == 0x0097:
            from . import blobs_97 as blobs

    if usb.usb_dev().idVendor == 0x06cb:
        if usb.usb_dev().idProduct == 0x009a:
            from . import blobs_9a as blobs

Could you already retrieve the blobs needed for the factory reset?

uunicorn commented 4 years ago

You're right. We just had this blob after the first attempt. But I get 404 for that log file now and I haven't saved it. It's the one which has:

USB a03700 >>>>>>>>>> WinUsb_WritePipe PipeID=1
>>> 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
rc=0 send=98

(this is a factory reset command)

storm1ng commented 4 years ago

Hm.... that's unfortunate, I have accidentally overwritten it...

Can I factory reset through the BIOS?

uunicorn commented 4 years ago

Sure, if you don;t mind rebooting

storm1ng commented 4 years ago

Ok, I have some more logfiles after the reset in the BIOS: logfile8.txt (without proper firmware) logfile9.txt (with proper fimware but error before enrolment) logfile10.txt (with proper firmware and enrolment

I guess the most interesting one will be logfile9.txt.

uunicorn commented 4 years ago

There is one more thing which is the identification. For that a.exe needs to be recompiled.

storm1ng commented 4 years ago

Sure, let me know what to change and I'll recompile a.exe.