Skip to content

Instantly share code, notes, and snippets.

@IISResetMe
Forked from MHaggis/Scan-LOLDrivers.ps1
Created May 19, 2023 17:08
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save IISResetMe/1a8353ae57710868b31b0e8d41683b95 to your computer and use it in GitHub Desktop.
Save IISResetMe/1a8353ae57710868b31b0e8d41683b95 to your computer and use it in GitHub Desktop.
it works - but use with caution :) it's a bit noisy and I think it's broken
function Scan-LOLDrivers {
param(
[Parameter(Mandatory = $true)]
[string]$path
)
Add-Type -TypeDefinition @"
using System;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Text;
public class FileHashScanner {
public static string ComputeSha256(string path) {
try {
using (FileStream stream = File.OpenRead(path)) {
SHA256Managed sha = new SHA256Managed();
byte[] checksum = sha.ComputeHash(stream);
return BitConverter.ToString(checksum).Replace("-", String.Empty);
}
} catch (Exception) {
return null;
}
}
public static string GetAuthenticodeHash(string path) {
try {
X509Certificate2 cert = new X509Certificate2(path);
return BitConverter.ToString(cert.GetCertHash()).Replace("-", String.Empty);
} catch (Exception) {
return null;
}
}
}
"@
Write-Host "Downloading drivers.json..."
$driversJsonUrl = "https://www.loldrivers.io/api/drivers.json"
$driversJsonContent = Invoke-WebRequest -Uri $driversJsonUrl
$driverData = $driversJsonContent.Content | ConvertFrom-Json
Write-Host "Download complete."
Write-Host "Building correlation tables"
$fileHashes = @{}
$authenticodeHashes = @{}
foreach ($driverInfo in $driverData) {
foreach ($sample in $driverInfo.KnownVulnerableSamples) {
'MD5 SHA1 SHA256'.Split() | ForEach-Object {
$fileHashValue = $sample.$_
if ($fileHashValue) {
$fileHashes[$fileHashValue] = $driverInfo
}
$authCodeHashValue = $sample.Authentihash.$_
if ($authCodeHashValue) {
$authenticodeHashes[$authCodeHashValue] = $driverInfo
}
}
}
}
Write-Host "Done building correlation tables"
function Scan-Directory {
param([string]$directory)
Get-ChildItem -Path $directory -Recurse -File | ForEach-Object {
$filePath = $_.FullName
Write-Verbose "Computing hash for $filePath..."
$fileHash = [FileHashScanner]::ComputeSha256($filePath)
$fileAuthenticodeHash = [FileHashScanner]::GetAuthenticodeHash($filePath)
if ($fileHashes.ContainsKey($fileHash)) {
Write-Host "SHA256 hash match found: $filePath with hash $fileHash (matching $($fileHashes[$fileHash]))"
}
if ($fileAuthenticodeHash -and $authenticodeHashes.ContainsKey($fileAuthenticodeHash)) {
Write-Host "Authenticode hash match found: $filePath with hash $fileAuthenticodeHash (matches $($authenticodeHashes[$fileAuthenticodeHash]))"
}
}
}
Write-Host "Starting scan..."
Scan-Directory -directory $path
Write-Host "Scan complete."
}
@Korving-F
Copy link

The JSON conversion fails for me with the below error complaining about duplicate keys, resulting in an empty $driverData-object. (Seems this is a well known issue with this function: PowerShell/PowerShell#3705)

PS C:\Users\Laptop> $driverData = $driversJsonContent.Content | ConvertFrom-Json
ConvertFrom-Json : Cannot convert the JSON string because a dictionary that was converted from the string contains the duplicated keys 'init' and 'INIT'.
At line:1 char:45
+ $driverData = $driversJsonContent.Content | ConvertFrom-Json
+                                             ~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [ConvertFrom-Json], InvalidOperationException
    + FullyQualifiedErrorId : DuplicateKeysInJsonString,Microsoft.PowerShell.Commands.ConvertFromJsonCommand

The suggestion is to use -AsHashTable flag when using newer PSCore version. Alternatively the following also worked for me with default PS5:

Add-Type -AssemblyName System.Web.Extensions
$serializer = [Web.Script.Serialization.JavaScriptSerializer]::new()
$serializer.MaxJsonLength = [int]::MaxValue

Write-Host "Downloading drivers.json..."
$driversJsonUrl = "https://www.loldrivers.io/api/drivers.json"
$driversJsonContent = Invoke-WebRequest -Uri $driversJsonUrl
$driverData = $serializer.DeserializeObject($driversJsonContent.Content)
Write-Host "Download complete."

P.s. thanks for the script ^_^

@R3DActual
Copy link

R3DActual commented Aug 27, 2023

NodeJS Version
Command for modules
npm install fs path https crypto

Run command
node .\scan.js C:\WINDOWS\inf

const fs = require('fs');
const path = require('path');
const https = require('https');
const crypto = require('crypto');

class FileHashScanner {
    static computeSha256(path) {
        return new Promise((resolve, reject) => {
            const sha = crypto.createHash('sha256');
            const stream = fs.createReadStream(path);

            stream.on('data', data => {
                sha.update(data);
            });

            stream.on('end', () => {
                const checksum = sha.digest('hex');
                resolve(checksum);
            });

            stream.on('error', err => {
                reject(err);
            });
        });
    }

    static async getAuthenticodeHash(path) {
        try {
            const certBuffer = fs.readFileSync(path);
            const cert = crypto.createHash('sha1').update(certBuffer).digest('hex');
            return cert;
        } catch (err) {
            return null;
        }
    }
}

console.log('Downloading drivers.json...');
const driversJsonUrl = 'https://www.loldrivers.io/api/drivers.json';

https.get(driversJsonUrl, driversJsonRes => {
    let driversJsonContent = '';

    driversJsonRes.on('data', chunk => {
        driversJsonContent += chunk;
    });

    driversJsonRes.on('end', () => {
        console.log('Download complete.');
        const driverData = JSON.parse(driversJsonContent);

        console.log('Building correlation tables');
        const fileHashes = {};
        const authenticodeHashes = {};

        driverData.forEach(driverInfo => {
            driverInfo.KnownVulnerableSamples.forEach(sample => {
                ['MD5', 'SHA1', 'SHA256'].forEach(hashType => {
                    const fileHashValue = sample[hashType];
                    if (fileHashValue) {
                        fileHashes[fileHashValue] = driverInfo;
                    }
                
                    const authCodeHashValue = sample.Authentihash && sample.Authentihash[hashType];
                    if (authCodeHashValue) {
                        authenticodeHashes[authCodeHashValue] = driverInfo;
                    }
                });
            });
        });

        console.log('Done building correlation tables');

        function scanDirectory(directory) {
            const items = fs.readdirSync(directory, { withFileTypes: true });
        
            items.forEach(item => {
                const itemPath = path.join(directory, item.name);
        
                if (item.isFile()) {
                    console.log(`Computing hash for ${itemPath}...`);
                    FileHashScanner.computeSha256(itemPath)
                        .then(fileHash => {
                            const matchingDriver = fileHashes[fileHash];
                            if (matchingDriver) {
                                const matchingSHA256 = matchingDriver.KnownVulnerableSamples.find(sample => sample.SHA256 === fileHash);
                                if (matchingSHA256) {
                                    console.log(`SHA256 hash match found: ${itemPath} with hash ${fileHash} (matching ${matchingSHA256.SHA256})`);
                                }
                            }
                        })
                        .catch(err => {
                            console.error(err);
                        });
        
                    FileHashScanner.getAuthenticodeHash(itemPath)
                        .then(authCodeHash => {
                            if (authCodeHash && authenticodeHashes.hasOwnProperty(authCodeHash)) {
                                console.log(`Authenticode hash match found: ${itemPath} with hash ${authCodeHash} (matches ${fileHashes[fileHash]})`);
                                console.log('Matching driver info:', fileHashes[fileHash]);
                            }
                        })
                        .catch(err => {
                            console.error(err);
                        });
                } else if (item.isDirectory()) {
                    scanDirectory(itemPath);
                }
            });
        }

        const targetDirectory = process.argv[2];
        if (!targetDirectory) {
            console.error('Please provide a directory path to scan.');
        } else {
            console.log('Starting scan...');
            scanDirectory(targetDirectory);
            console.log('Scan complete.');
        }
    });
}).on('error', err => {
    console.error(err);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment