Σε διάφορα forums, σε threads που έχουν να κάνουν με backup, χρήστες των windows έχουν κάνει σχόλια του στυλ: "Δεν μπορεί να είναι τόσο δύσκολο, εγώ για να πάρω backup απλά τοποθετώ τον εξωτερικό δίσκο και πατάω το κουμπάκι που λέει One Touch Backup".
Καθώς δεν υπάρχει κανένας σοβαρός τεχνικός λόγος γιατί να μην μπορεί αυτό να δουλέψει και στο Linux, αποφάσισα να ρίξω μια ματιά στους εξωτερικούς δίσκους μου για να δω τι θα χρειαζόταν ώστε να υποστηριχθεί το "κουμπί" που συμπεριλαμβάνουν.
Καταρχήν πρέπει να πούμε ότι οι συσκευές Maxtor OneTouch ήδη υποστηρίζονται στο Linux (συμπεριλαμβανομένου του button) μέσω ενός επιπλέον driver (onetouch). Αυτό συμβαίνει γιατί οι συσκευές αυτές έχουν υλοποιήσει το button με το σωστό τεχνικά τρόπο, δηλαδή μέσω ενός ξεχωριστού USB HID interface. To interface αυτό ο onetouch driver το "εξάγει" απλά ως ένα input device το οποίο μπορεί να χρησιμοποιηθεί από οποιαδήποτε εφαρμογή θέλουμε (π.χ., gnome shortcuts ).
Οι δικές μου συσκευές ("no-name") που περιλαμβάνουν one touch backup button, περιέχουν ελεγκτές της εταιρείας JMicron, συγκεκριμμένα JMicron 20336 (SATA port replicator to USB 2.0 adaptor) και JMicron 20338 (SATA/IDE to USB 2.0 Combo adaptor).
Σε αυτό το post θα ασχοληθούμε με τον JM20338 αλλά και ο JM20336 είναι πολύ παρόμοιος.
Η πρώτη ιδέα ήταν να δω μήπως η συσκευή υλοποιεί το interface για το κουμπί όπως ο onetouch, πράγμα που θα μου επέτρεπε να την υποστηρίξω απλά προσθέτοντας το USB ID της στον onetouch driver (152d:2338 είναι το VendorID:ProductID της συσκευής):
lsusb -vvv -d 152d:2338
Όπως βλέπουμε υπάρχει μόνο ένα interface, τύπου USB Mass Storage. Άρα θα αναγκαστούμε να ρίξουμε μια πιο προσεκτική ματιά στο πώς οδηγεί τη συσκευή το συνοδευτικό της software στα windows για να καταλάβουμε τι γίνεται ...
Συνήθως οι συσκευές τύπου mass storage είναι οι πιο βολικές USB συσκευές από πλευράς συμβατότητας με εικονικές μηχανές, οπότε το πρώτο που σκεφτόμαστε είναι να χρησιμοποιήσουμε virtualization για το reverse engineering της συσκευής μας. Έτσι δε χρειαζόμαστε πανάκριβους hardware usb analyzers, ούτε reboots, ούτε (μερικές φορές αναξιόπιστους) filter drivers για τα windows.
Μια και το USB support (ειδικά ο ehci controller) του Qemu αυτή τη στιγμή είναι υπό πυρετώδη ανάπτυξη και ως εκ τούτου παρουσιάζει προβληματάκια, μπορούμε να καταφύγουμε στο virtualbox για να μας βοηθήσει. Για το tracing θα χρησιμοποιήσουμε το υποσύστημα usbmon του πυρήνα του Linux.
Η διαδικασία περιγράφεται αναλυτικά στο http://polytechnitis.blogspot.com/2011/05/usb-reverse-engineering-virtualbox.html οπότε δε θα την επαναλάβω.
Παρατηρώντας ότι μόλις ξεκινούσε το πρόγραμμα PC Clone Ex, ξεκινούσε μεγάλη "δραστηριότητα" στο USB bus μέχρι να πατηθεί το κουμπί του backup, είναι λογικό να υποθέσουμε ότι η εφαρμογή κάνει polling για την κατάσταση του κουμπιού (πατημένο ή όχι). Άρα περιμένουμε να δούμε ένα επαναλαμβανόμενο "Data In" transaction στο log του usbmon, του οποίου το output να αλλάζει ανάλογα με το αν το κουμπί είναι πατημένο ή όχι.
Πράγματι, μετά από μια περίοδο αρχικοποίησης της συσκευής, βασικών transaction του στυλ SCSI INQUIRY / Read Capacity κλπ, παρατηρούμε ότι επαναλαμβάνεται συνεχώς το παρακάτω:
Επιπλέον παρατηρήθηκε ότι η τιμή που διαβάζει το transaction αυτό από τη συσκευή είναι 9600 αν το κουμπί είναι πατημένο και 9700 αν όχι. Εδώ είμαστε λοιπόν :)
Ας αναλύσουμε λίγο περισσότερο το παραπάνω transaction για όσους δεν έχουν ξαναδεί usbmon / usb mass storage logs. Οι 2 πρώτες στήλες του log δε μας ενδιαφέρουν στη συγκεκριμένη περίπτωση κι έτσι έχουν αφαιρεθεί.
Η πρώτη στήλη που βλέπουμε έχει το σύμβολο 'S' που σημαίνει submit to device ή το 'C' που σημαίνει callback. Επίσης το Bo σημαίνει "Bulk OUT" (bulk είναι ένας από τους τύπους μεταφοράς usb δεδομένων) και Bi σημαίνει "Bulk IN" ενώ ακολουθεί το Bus number (2) και Port number (8).
Το 0 ή -115 είναι το status code και ακολουθεί ο αριθμός των bytes που στέλνεται στη συσκευή ή ζητείται από τη συσκευή.
Αυτό που γίνεται λοιπόν είναι ότι ο driver στέλνει αυτά τα 31 bytes στη συσκευή, το callback του λέει ότι όντως στάλθηκαν εντάξει, μετά ζητά 2 bytes και του επιστρέφεται το 00 97 (πρέπει να θυμόμαστε ότι ο USB είναι little endian) ή το 00 96 αν το κουμπί είναι πατημένο, κάτι που δε φαίνεται παραπάνω. Τέλος, ο driver ζητά ένα πακέτο ως 512 bytes και του επιστρέφονται τα 13 bytes που βλέπουμε.
Η πρώτη ιδέα με βάση τα παραπάνω για να υποστηρίξουμε αυτή τη λειτουργικότητα στο Linux θα ήταν να γράψουμε ένα userspace USB driver (μπορούμε ακόμα και σε python) ο οποίος θα αναλάβει να ανάπαράγει ακριβώς το παραπάνω transaction. Δυστυχώς όμως αυτό είναι μη πρακτικό. Ο λόγος είναι ότι στο Linux κάθε driver έχει την "αποκλειστική κυριαρχία" ενός usb interface. Το οποίο σημαίνει ότι αν γράφαμε το δικό μας usb driver θα έπρεπε να "εκτοπίσουμε" τον mass-storage driver του Linux από το interface οπότε θα μπορούσαμε να χρησιμοποιήσουμε τη συσκευή μας ως "κουμπί" αλλά όχι πια ως δίσκο (!!) (αν δε θέλουμε να ξαναγράψουμε ουσιαστικά τον mass storage driver σε userspace). Total fail :P
Για να λύσουμε το πρόβλημα, θα πρέπει να κατανοήσουμε το transaction μας λίγο καλύτερα. Όπως είδαμε από το lsusb output, το interface μας είναι τύπου "bulk-only transfer". Τι σημαίνει όμως αυτό; Η απάντηση βρίσκεται εδώ, στο specification του Bulk Only Transfer, το οποίο μάλιστα είναι αρκετά ευανάγνωστο. Ουσιαστικά μας λέει πώς μεταφέρουμε SCSI commands πάνω από USB Bulk transfers.
Το ενδιαφέρον κομμάτι είναι το παρακάτω σχήμα, που μας δείχνει τη "ροή" ενός command πάνω από B.O.T:
Πρέπει να συμπληρώσουμε ότι το CBW (Command Block Wrapper) είναι ακριβώς 31 bytes ενώ το CSW (Command Status Wrapper) είναι ακριβώς 13! Συμπεραίνουμε λοιπόν ότι αυτό που βλέπουμε να επαναλαμβάνεται συνέχεια στα logs είναι απλά ένα SCSI Data-In command!
(Αυτός ο τρόπος λειτουργίας παρεμπιπτόντως θυμίζει λίγο τους SCSI scanners που επίσης χρησιμοποιούσαν αυτού του στυλ το polling πάνω από SCSI commands για τα buttons τους.)
Το ωραίο λοιπόν στην υπόθεση λοιπόν, είναι ότι αρκεί να αλληλεπιδράσουμε με τη συσκευή σε επίπεδο SCSI και μπορούμε να αφήσουμε τον usb mass-storage driver του Linux απείραχτο :)
Με βάση αυτά που ξέρουμε τώρα, ας αναλύσουμε λίγο το log μας ώστε να το καταλάβουμε περισσότερο. Στο σύνδεσμο https://wiki.kubuntu.org/Kernel/Debugging/USB αναλύεται πολύ ωραία η δομή ενός SCSI/Mass storage πακέτου. Με βάση αυτά που βλέπουμε εκεί, αφενός μπορούμε να καταλάβουμε ότι το ενδιαφέρον στο status μας είναι τα μηδενικά (που σημαίνει success), ενώ το CBW μας αναλύεται ως εξής:
Βρήκαμε λοιπόν ότι αρκεί να στέλνουμε το συγκεκριμμένο non-standard SCSI command στη συσκευή περιοδικά για να διαβάσουμε την κατάσταση του button (μας νοιάζει μόνο το τελευταίο bit από τα 16 που θα πάρουμε).
Πώς τώρα στέλνουμε το command μας; Εδώ έρχεται να μας βοηθήσει ο πυρήνας 2.6, ο οποίος υποστηρίζει το SG_IO ioctl το οποίο κάνει ακριβώς ότι θέλουμε :)
Ο παρακάτω κώδικας σε ψευδο-C δείχνει χονδρικά τι χρειάζεται να κάνουμε:
Καθώς δεν υπάρχει κανένας σοβαρός τεχνικός λόγος γιατί να μην μπορεί αυτό να δουλέψει και στο Linux, αποφάσισα να ρίξω μια ματιά στους εξωτερικούς δίσκους μου για να δω τι θα χρειαζόταν ώστε να υποστηριχθεί το "κουμπί" που συμπεριλαμβάνουν.
Καταρχήν πρέπει να πούμε ότι οι συσκευές Maxtor OneTouch ήδη υποστηρίζονται στο Linux (συμπεριλαμβανομένου του button) μέσω ενός επιπλέον driver (onetouch). Αυτό συμβαίνει γιατί οι συσκευές αυτές έχουν υλοποιήσει το button με το σωστό τεχνικά τρόπο, δηλαδή μέσω ενός ξεχωριστού USB HID interface. To interface αυτό ο onetouch driver το "εξάγει" απλά ως ένα input device το οποίο μπορεί να χρησιμοποιηθεί από οποιαδήποτε εφαρμογή θέλουμε (π.χ., gnome shortcuts ).
Οι δικές μου συσκευές ("no-name") που περιλαμβάνουν one touch backup button, περιέχουν ελεγκτές της εταιρείας JMicron, συγκεκριμμένα JMicron 20336 (SATA port replicator to USB 2.0 adaptor) και JMicron 20338 (SATA/IDE to USB 2.0 Combo adaptor).
Σε αυτό το post θα ασχοληθούμε με τον JM20338 αλλά και ο JM20336 είναι πολύ παρόμοιος.
Η πρώτη ιδέα ήταν να δω μήπως η συσκευή υλοποιεί το interface για το κουμπί όπως ο onetouch, πράγμα που θα μου επέτρεπε να την υποστηρίξω απλά προσθέτοντας το USB ID της στον onetouch driver (152d:2338 είναι το VendorID:ProductID της συσκευής):
lsusb -vvv -d 152d:2338
Bus 002 Device 008: ID 152d:2338 JMicron Technology Corp. / JMicron USA Technology Corp. JM20337 Hi-Speed USB to SATA & PATA Combo Bridge Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x152d JMicron Technology Corp. / JMicron USA Technology Corp. idProduct 0x2338 JM20337 Hi-Speed USB to SATA & PATA Combo Bridge bcdDevice 1.00 iManufacturer 1 JMicron iProduct 2 USB to ATA/ATAPI Bridge iSerial 5 376871830782 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 32 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 4 USB Mass Storage bmAttributes 0xc0 Self Powered MaxPower 2mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 6 MSC Bulk-Only Transfer Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1 Device Status: 0x5301 Self Powered
Όπως βλέπουμε υπάρχει μόνο ένα interface, τύπου USB Mass Storage. Άρα θα αναγκαστούμε να ρίξουμε μια πιο προσεκτική ματιά στο πώς οδηγεί τη συσκευή το συνοδευτικό της software στα windows για να καταλάβουμε τι γίνεται ...
Συνήθως οι συσκευές τύπου mass storage είναι οι πιο βολικές USB συσκευές από πλευράς συμβατότητας με εικονικές μηχανές, οπότε το πρώτο που σκεφτόμαστε είναι να χρησιμοποιήσουμε virtualization για το reverse engineering της συσκευής μας. Έτσι δε χρειαζόμαστε πανάκριβους hardware usb analyzers, ούτε reboots, ούτε (μερικές φορές αναξιόπιστους) filter drivers για τα windows.
Μια και το USB support (ειδικά ο ehci controller) του Qemu αυτή τη στιγμή είναι υπό πυρετώδη ανάπτυξη και ως εκ τούτου παρουσιάζει προβληματάκια, μπορούμε να καταφύγουμε στο virtualbox για να μας βοηθήσει. Για το tracing θα χρησιμοποιήσουμε το υποσύστημα usbmon του πυρήνα του Linux.
Η διαδικασία περιγράφεται αναλυτικά στο http://polytechnitis.blogspot.com/2011/05/usb-reverse-engineering-virtualbox.html οπότε δε θα την επαναλάβω.
Παρατηρώντας ότι μόλις ξεκινούσε το πρόγραμμα PC Clone Ex, ξεκινούσε μεγάλη "δραστηριότητα" στο USB bus μέχρι να πατηθεί το κουμπί του backup, είναι λογικό να υποθέσουμε ότι η εφαρμογή κάνει polling για την κατάσταση του κουμπιού (πατημένο ή όχι). Άρα περιμένουμε να δούμε ένα επαναλαμβανόμενο "Data In" transaction στο log του usbmon, του οποίου το output να αλλάζει ανάλογα με το αν το κουμπί είναι πατημένο ή όχι.
Πράγματι, μετά από μια περίοδο αρχικοποίησης της συσκευής, βασικών transaction του στυλ SCSI INQUIRY / Read Capacity κλπ, παρατηρούμε ότι επαναλαμβάνεται συνεχώς το παρακάτω:
S Bo:2:008:2 -115 31 = 55534243 309ac081 02000000 80000cdf 10000002 00000000 0000ff00 000000 C Bo:2:008:2 0 31 > S Bi:2:008:1 -115 2 < C Bi:2:008:1 0 2 = 9700 S Bi:2:008:1 -115 512 < C Bi:2:008:1 0 13 = 55534253 309ac081 00000000 00
Επιπλέον παρατηρήθηκε ότι η τιμή που διαβάζει το transaction αυτό από τη συσκευή είναι 9600 αν το κουμπί είναι πατημένο και 9700 αν όχι. Εδώ είμαστε λοιπόν :)
Ας αναλύσουμε λίγο περισσότερο το παραπάνω transaction για όσους δεν έχουν ξαναδεί usbmon / usb mass storage logs. Οι 2 πρώτες στήλες του log δε μας ενδιαφέρουν στη συγκεκριμένη περίπτωση κι έτσι έχουν αφαιρεθεί.
Η πρώτη στήλη που βλέπουμε έχει το σύμβολο 'S' που σημαίνει submit to device ή το 'C' που σημαίνει callback. Επίσης το Bo σημαίνει "Bulk OUT" (bulk είναι ένας από τους τύπους μεταφοράς usb δεδομένων) και Bi σημαίνει "Bulk IN" ενώ ακολουθεί το Bus number (2) και Port number (8).
Το 0 ή -115 είναι το status code και ακολουθεί ο αριθμός των bytes που στέλνεται στη συσκευή ή ζητείται από τη συσκευή.
Αυτό που γίνεται λοιπόν είναι ότι ο driver στέλνει αυτά τα 31 bytes στη συσκευή, το callback του λέει ότι όντως στάλθηκαν εντάξει, μετά ζητά 2 bytes και του επιστρέφεται το 00 97 (πρέπει να θυμόμαστε ότι ο USB είναι little endian) ή το 00 96 αν το κουμπί είναι πατημένο, κάτι που δε φαίνεται παραπάνω. Τέλος, ο driver ζητά ένα πακέτο ως 512 bytes και του επιστρέφονται τα 13 bytes που βλέπουμε.
Η πρώτη ιδέα με βάση τα παραπάνω για να υποστηρίξουμε αυτή τη λειτουργικότητα στο Linux θα ήταν να γράψουμε ένα userspace USB driver (μπορούμε ακόμα και σε python) ο οποίος θα αναλάβει να ανάπαράγει ακριβώς το παραπάνω transaction. Δυστυχώς όμως αυτό είναι μη πρακτικό. Ο λόγος είναι ότι στο Linux κάθε driver έχει την "αποκλειστική κυριαρχία" ενός usb interface. Το οποίο σημαίνει ότι αν γράφαμε το δικό μας usb driver θα έπρεπε να "εκτοπίσουμε" τον mass-storage driver του Linux από το interface οπότε θα μπορούσαμε να χρησιμοποιήσουμε τη συσκευή μας ως "κουμπί" αλλά όχι πια ως δίσκο (!!) (αν δε θέλουμε να ξαναγράψουμε ουσιαστικά τον mass storage driver σε userspace). Total fail :P
Για να λύσουμε το πρόβλημα, θα πρέπει να κατανοήσουμε το transaction μας λίγο καλύτερα. Όπως είδαμε από το lsusb output, το interface μας είναι τύπου "bulk-only transfer". Τι σημαίνει όμως αυτό; Η απάντηση βρίσκεται εδώ, στο specification του Bulk Only Transfer, το οποίο μάλιστα είναι αρκετά ευανάγνωστο. Ουσιαστικά μας λέει πώς μεταφέρουμε SCSI commands πάνω από USB Bulk transfers.
Το ενδιαφέρον κομμάτι είναι το παρακάτω σχήμα, που μας δείχνει τη "ροή" ενός command πάνω από B.O.T:
Πρέπει να συμπληρώσουμε ότι το CBW (Command Block Wrapper) είναι ακριβώς 31 bytes ενώ το CSW (Command Status Wrapper) είναι ακριβώς 13! Συμπεραίνουμε λοιπόν ότι αυτό που βλέπουμε να επαναλαμβάνεται συνέχεια στα logs είναι απλά ένα SCSI Data-In command!
(Αυτός ο τρόπος λειτουργίας παρεμπιπτόντως θυμίζει λίγο τους SCSI scanners που επίσης χρησιμοποιούσαν αυτού του στυλ το polling πάνω από SCSI commands για τα buttons τους.)
Το ωραίο λοιπόν στην υπόθεση λοιπόν, είναι ότι αρκεί να αλληλεπιδράσουμε με τη συσκευή σε επίπεδο SCSI και μπορούμε να αφήσουμε τον usb mass-storage driver του Linux απείραχτο :)
Με βάση αυτά που ξέρουμε τώρα, ας αναλύσουμε λίγο το log μας ώστε να το καταλάβουμε περισσότερο. Στο σύνδεσμο https://wiki.kubuntu.org/Kernel/Debugging/USB αναλύεται πολύ ωραία η δομή ενός SCSI/Mass storage πακέτου. Με βάση αυτά που βλέπουμε εκεί, αφενός μπορούμε να καταλάβουμε ότι το ενδιαφέρον στο status μας είναι τα μηδενικά (που σημαίνει success), ενώ το CBW μας αναλύεται ως εξής:
02000000 => BufferLen = 2 (είπαμε, little endian) 80 => Flags = SG_DXFER_FROM_DEV; 00 0c => CommandLength = 12 df 10000002 00000000 0000ff => Αυτό είναι το SCSI Command Descriptor Block (CDB) 00000000 => 4 byte padding ως τα 16 (standard CDB size).
Βρήκαμε λοιπόν ότι αρκεί να στέλνουμε το συγκεκριμμένο non-standard SCSI command στη συσκευή περιοδικά για να διαβάσουμε την κατάσταση του button (μας νοιάζει μόνο το τελευταίο bit από τα 16 που θα πάρουμε).
Πώς τώρα στέλνουμε το command μας; Εδώ έρχεται να μας βοηθήσει ο πυρήνας 2.6, ο οποίος υποστηρίζει το SG_IO ioctl το οποίο κάνει ακριβώς ότι θέλουμε :)
Ο παρακάτω κώδικας σε ψευδο-C δείχνει χονδρικά τι χρειάζεται να κάνουμε:
int main(int argc, char **argv) { int fd, rc; struct sg_io_hdr sg_io; uint8_t sense[32]; uint8_t data[2]; uint8_t cdb[16] = { 0xdf, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00}; fd = open (argv[1], O_RDWR); // set sense, data, sg_io to zero sg_io.interface_id = 'S'; sg_io.cmdp = cdb; sg_io.cmd_len = 12; sg_io.dxferp = data; sg_io.dxfer_len = 2; sg_io.dxfer_direction = SG_DXFER_FROM_DEV; sg_io.sbp = sense; sg_io.mx_sb_len = sizeof(sense); sg_io.timeout = 5000; // 5 seconds rc = ioctl (fd, SG_IO, &sg_io); if ((data[1] & 0x01) == 0) //print "button is pressed"; else //print "button is NOT pressed"; return rc; }
Το device που θα περάσουμε ως όρισμα στη main() μας μπορεί να είναι το
sdX που θα φτιαχτεί για το δίσκο που αντιστοιχεί στο mass-storage device
(e.g., sdb) ή το αντίστοιχο sgX (scsi generic device), το ioctl θα δουλέψει
εξίσου καλά και στις 2 συσκευές.
Για να δοκιμάσουμε τη θεωρία μας, μπορούμε να μεταγλωττίσουμε ένα εκτελέσιμο
που να στέλνει ένα ioctl στη συσκευή και να παρατηρήσουμε το "διάλογο" μεταξύ
του εκτελέσιμου αυτού και της συσκευής μέσω του usbmon (π.χ., για να βεβαιωθούμε
ότι δεν έχουμε μπερδευτεί πουθενά σχετικά με το τι είναι big endian και τι little
endian).
Για ένα "πρωτόγονο" τρόπο να μετατρέψουμε μετά το εκτελέσιμο αυτό σε κάτι που κάνει
polling (αν υποθέσουμε ότι ονομάσαμε το εκτελέσιμό μας jbutton) μπορούμε να τρέξουμε
απλά
watch jbutton
Αυτό θα έχει ως συνέπεια να πρέπει να κρατήσουμε για 2s πατημένο κάθε φορά το κουμπί προκειμένου να δούμε αλλαγή, αλλά για δοκιμή αυτό δε μας πειράζει. Όταν βεβαιωθούμε ότι το πρόγραμμα δουλεύει σωστά και βλέπουμε το σωστό μήνυμα κάθε φορά ανάλογα με το αν το κουμπί είναι πατημένο ή όχι, η δουλειά του reverse engineering έχει ολοκληρωθεί και μπορούμε να προχωρήσουμε στην υλοποίηση της εφαρμογής μας για τη διαχείριση αυτού του είδους των συσκευών και την επίτευξη One Touch Backup :)
Σε αυτό το post είδαμε τα βήματα που μας έφτασαν από την πλήρη άγνοια για το πώς δουλεύει μία USB συσκευή, μέχρι του σημείου να μπορούμε να την οδηγήσουμε με λίγες γραμμές userspace κώδικα C για το Linux.
Ελπίζω να έγινε κατανοητό ότι το reverse engineering αυτού του είδους σίγουρα δεν είναι και ό,τι πιο εύκολο αλλά δεν είναι και πυρηνική επιστήμη, ειδικά για σχετικά απλές ως προς τη λειτουργία τους συσκευές.
Καλά Reversing :)
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου