mirror of
https://github.com/Mister-Joe/PositiveIntent
synced 2026-06-21 13:44:54 +00:00
105 lines
3.8 KiB
Python
105 lines
3.8 KiB
Python
import os
|
|
import re
|
|
import shutil
|
|
import random
|
|
import string
|
|
import colorama
|
|
import shlex
|
|
import xml.etree.ElementTree as ET
|
|
import wonderwords
|
|
|
|
CURRENT_SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
def update_encryption_key(content):
|
|
key = ''.join(random.choices(string.ascii_letters, k=16))
|
|
content = re.sub(re.escape('public static byte[] key = Encoding.UTF8.GetBytes("DepthSecurity");'), f'public static byte[] key = Encoding.UTF8.GetBytes("{key}");', content)
|
|
return content, key
|
|
|
|
def update_writetofile(content):
|
|
content = re.sub(re.escape('bool shouldWriteToFile = false;'), 'bool shouldWriteToFile = true;', content)
|
|
return content
|
|
|
|
def update_hostname(content, hostname):
|
|
content = re.sub(r'TESTVM', hostname, content)
|
|
return content
|
|
|
|
def update_resource_references(content, num_chunks):
|
|
resources = ''
|
|
for i in range(num_chunks):
|
|
resources += (f"chunks.Add(Resources.FileChunk{i});\n ")
|
|
content = re.sub(re.escape(f"chunks.Add(Resources.FileChunk1);"), resources, content)
|
|
return content
|
|
|
|
def update_arguments(args, content):
|
|
# Split args into a list of strings
|
|
arg_parts = shlex.split(args)
|
|
|
|
# Format each argument as a reversed string in the C# string array
|
|
formatted_args = ", ".join(f'"{arg}"' for arg in arg_parts)
|
|
|
|
# Update the parameters declaration
|
|
content = re.sub(
|
|
re.escape('object[] parameters = new[] { args };'),
|
|
rf'string[] parameters = new string[] {{ {formatted_args} }};',
|
|
content
|
|
)
|
|
|
|
# Update the method invocation
|
|
content = re.sub(
|
|
re.escape('object execute = method.Invoke(null, parameters);'),
|
|
'object execute = method.Invoke(null, new object[] { parameters });',
|
|
content
|
|
)
|
|
|
|
return content
|
|
|
|
def randomize_loader_name(tmp_dir):
|
|
|
|
csproj_filepath = os.path.normpath(os.path.join(tmp_dir, "PositiveIntent/PositiveIntent.csproj"))
|
|
r = wonderwords.RandomWord()
|
|
loader_name = f"{r.word()}_{r.word()}"
|
|
|
|
# Parse the .csproj XML file
|
|
tree = ET.parse(csproj_filepath)
|
|
root = tree.getroot()
|
|
|
|
property_group = root.find('PropertyGroup')
|
|
if property_group is not None:
|
|
assembly_name_element = ET.SubElement(property_group, 'AssemblyName')
|
|
|
|
# Update the AssemblyName to the new random name
|
|
assembly_name_element.text = loader_name
|
|
|
|
# Write changes back to the .csproj file
|
|
tree.write(csproj_filepath, encoding="utf-8", xml_declaration=True)
|
|
|
|
return loader_name
|
|
|
|
def run(tmp_dir, hostname, num_chunks, args, writetofile):
|
|
# Copy entire project to temp directory
|
|
input_dir = os.path.normpath(os.path.join(CURRENT_SCRIPT_PATH, "../"))
|
|
shutil.copytree(input_dir, tmp_dir, dirs_exist_ok=True)
|
|
|
|
loader_name = randomize_loader_name(tmp_dir)
|
|
|
|
# Loop over source files and update user-supplied hostname/args/writetofile options as well as resource file references
|
|
for root, dirs, files in os.walk(tmp_dir, topdown=True):
|
|
dirs[:] = [d for d in dirs if d not in ("bin", "obj", "Resources", "Properties")]
|
|
for file_name in files:
|
|
file_path = os.path.join(root, file_name)
|
|
if file_name.endswith('.cs'):
|
|
with open(file_path, 'r+', encoding='utf-8') as file:
|
|
content = file.read()
|
|
if(writetofile):
|
|
content = update_writetofile(content)
|
|
if(args):
|
|
content = update_arguments(args, content)
|
|
if("RC4" in file_name):
|
|
content, key = update_encryption_key(content)
|
|
content = update_hostname(content, hostname)
|
|
content = update_resource_references(content, num_chunks)
|
|
file.seek(0)
|
|
file.write(content)
|
|
file.truncate()
|
|
return loader_name, key
|