#!/usr/bin/perl use strict; use warnings; require 5.018; use IO::File; sub usage() { print(STDERR "Usage: scanwindrv SileadTouch.sys\n"); print(STDERR "Scans a Windows driver for sections that look like a firmware image and\n"); print(STDERR "writes each into sequentially numbered files: firmware_01.fw firmware_02.fw ...\n"); -1; } my $drvfile = $ARGV[0] or exit usage; my $driver = ''; do { my $in = IO::File->new($drvfile, 'r') or die "Can't open $drvfile: $!"; $in->binmode(); local $/; $driver = <$in>; defined $driver or die "Can't read firmware: $!"; $in->close(); }; my $candidate = 0; # find candidates for (my $offset = 0; $offset + 8 <= length($driver); $offset++) { my ($cmd, $page) = unpack('(LL)<', substr($driver, $offset, 8)); if ($cmd == 0x000000f0 && ($page & 0xffffff00) == 0x00000000) { printf(STDERR "Found possible candidate at offset 0x%08x\n", $offset); # possible candidate, start copying pages my $firmware = ''; my $size; FIRMWARE: for ($size = 0; $offset + $size + 129 * 8 <= length($driver);) { #printf(STDERR "offset=0x%08x size=%u[0x%08x]\n", $offset, $size, $size); my ($cmd, $page) = unpack('(LL)<', substr($driver, $offset + $size, 8)); #printf(STDERR "Page header at 0x%08x: [0x%02x, 0x%08x]\n", $offset + $size, $cmd, $page); # if this doesn't look like a page register - page pair, we're done if ($cmd != 0x000000f0 || ($page & 0xffffff00) != 0x00000000) { last FIRMWARE; } for (my $index = 0; $index + 4 <= 128; $index += 4) { my ($idx, $dat) = unpack('(LL)<', substr($driver, $offset + $size + 8 + $index * 2, 8)); #printf(STDERR "Data at 0x%08x: [0x%02x, 0x%02x]\n", $offset + $size + 8 + $index * 2, $idx, $dat); # if the index is not sequential, this is probably not part of the fw and we're done if ($idx != $index) { #printf(STDERR "Expected index 0x%02x, got 0x%02x\n", $index, $idx); last FIRMWARE; } } # one page complete, copy substr($firmware, $size, 33 * 8) = substr($driver, $offset + $size, 33 * 8); $size += 33 * 8; } # check if we have enough data if (length($firmware) > 8) { my $fwname = sprintf("firmware_%02u.fw", $candidate); printf(STDERR "Writing firmware to %s, size = %u bytes\n", $fwname, length($firmware)); my $out = IO::File->new($fwname, 'w', 0666) or die "Can't open $fwname: $!"; $out->binmode(); print($out $firmware); $out->close(); $candidate++; } else { printf(STDERR "Not a firmware, ignoring\n"); } # skip ahead $offset += $size; } } =cut export F=SileadTouch.sys cat $F \ | hexdump -e '1/1 "0x%8.8_ax "' -e '1/1 "%8._ad "' -e '8/1 "%02X ""\n"""' \ | grep -i -E "F0 00 00 00 02 00 00 00|7C 00 00 00 .. .. .. .." \ | grep "F0 00 00 00 02 00 00 00" -B1 \ ; \ echo -- \ ; \ cat $F \ | hexdump -e '1/1 "0x%8.8_ax "' -e '1/1 "%8._ad "' -e '8/1 "%02X ""\n"""' \ | grep -i -E "F0 00 00 00 02 00 00 00|7C 00 00 00 .. .. .. .." \ | tail -n2 cat <