
Interprete Python per i profili Malleable C2 di Cobalt Strike. Permette di analizzarli, crearli e modificarli programmaticamente.
Un interprete Python per i profili Malleable C2 di Cobalt Strike che ti consente di analizzare, modificarli, costruirli programmaticamente e convalidare la sintassi.
Supporta tutta la grammatica dei profili Malleable C2 di Cobalt Strike a partire dalla versione 4.3 di Cobalt Strike.
Non è retrocompatibile con le versioni precedenti di Cobalt Strike.
Quali sono le differenze tra pyMalleableC2 e altri progetti di questa natura?
if.pyMalleableC2 è stato sviluppato usando Python 3.9, ma dovrebbe essere retrocompatibile fino a Python 3.6.
Installa con Pip:
pip3 install pymalleablec2pyMalleableC2 ti tratta come un adulto consenziente e presume che tu sappia scrivere profili Malleable C2. È in grado di rilevare errori di sintassi, ma non sono implementati controlli a runtime. Genererà volentieri profili che non funzionano effettivamente in produzione se glielo chiedi. Esegui sempre i profili generati attraverso c2lint prima di usarli in produzione!
(Tecnicamente potresti costruire una versione Python di c2lint usando questa libreria, *tosse* PR benvenuto *tosse*)
L'autore principale di pyMalleableC2 è Marcello Salvati
Twitter: @byt3bl33d3r, Github: @byt3bl33d3r
(Vedi la cartella esempi per altri)
Genera l'AST per un profilo Malleable C2 situato in un file, poi ricostruisci il codice sorgente dall'AST:
from malleablec2 import Profile
# Parse a profile given its path
p = Profile.from_file("amazon.profile")
# Print the generated AST
print(p.ast.pretty())
# Reconstruct source code from the AST and print to console
print(p.reconstruct())
# Shortcut for the above :)
print(p)
Genera l'AST per un profilo Malleable C2 'inline' e poi ricostruisci il codice sorgente dall'AST:
code = '''
set jitter "0";
set sleeptime "3000";
http-get {
set uri "/wow/this/is/cool";
}
http-post {
set uri "/pymalleablec2/is/the/shit";
}
'''
# Parse a profile from a string
p = Profile.from_string(code)
# Print the generated AST
print(p.ast.pretty())
# Reconstruct source code from the AST and print to console
print(p)
Costruisci un profilo Malleable C2 programmaticamente da zero:
from malleablec2 import Profile
from malleablec2.components import *
# Create an empty profile
p = Profile.from_scratch()
# Set some global options
p.set_option("sleeptime", "0")
p.set_option("jitter", "0")
p.set_option("pipename", "mojo__##")
# Create an http-get block
http_get = HttpGetBlock()
# Set the uri http-get option
http_get.set_option("uri", "/wat/a/tease")
# Create a client block
client = ClientBlock()
# Add a header statement to the client block
client.add_statement("header", "Accept", "*/*")
# Create a server block
server = ServerBlock()
# Add the client and server blocks to the http-get block
http_get.add_code_block(client)
http_get.add_code_block(server)
# Create a http-post block
http_post = HttpPostBlock()
# Set the uri http-post option
http_post.set_option("uri", "/wat/ucraycray")
# Add the http-get and http-post blocks to the profile
p.add_code_block(http_get)
p.add_code_block(http_post)
# Reconstruct source code from the generated AST and print to console
print(p)
Esempio super semplice che mostra come randomizzare programmaticamente un profilo Malleable C2:
from malleablec2 import Profile
from malleablec2.randomizer import ProfileRandomizer
from lark import Token
class MyRandomizer(ProfileRandomizer):
# We implement the global_option_set method which will get called on every parsed global option statement in the profile
def global_option_set(self, tree):
option_name = tree.children[0]
if option_name == "pipename":
# "Randomize" the pipename value
tree.children[1].children[0] = Token('ESCAPED_STRING', '"my_random_pipename_##"')
# Parse a profile given its path
p = Profile.from_file("amazon.profile")
r = MyRandomizer()
# Walk through the generated profile AST and apply randomization rules
r.randomize(p)
# Reconstruct source code then output the profile to the console
print(p)