
Interpretador Python para perfis C2 maleáveis do Cobalt Strike. Permite analisá-los, construí-los e modificá-los programaticamente.
Um interpretador Python para perfis Malleable C2 do Cobalt Strike que permite analisar, modificar, construí-los programaticamente e validar a sintaxe.
Suporta toda a gramática do perfil Malleable C2 do Cobalt Strike a partir da versão 4.3 do Cobalt Strike.
Não é compatível com versões anteriores do Cobalt Strike.
Quais são as diferenças entre o pyMalleableC2 e outros projetos da mesma natureza?
if.O pyMalleableC2 foi construído com Python 3.9, no entanto deve ser compatível até Python 3.6.
Instale usando o Pip:
pip3 install pymalleablec2O pyMalleableC2 trata-o como um adulto consentido e assume que sabe como escrever Perfis Malleable C2. É capaz de detetar erros de sintaxe, no entanto não existem verificações em tempo de execução implementadas. Irá gerar perfis que não funcionam na prática se assim for instruído. Execute sempre os perfis gerados através do c2lint antes de os utilizar em produção!
(Tecnicamente poderia construir uma versão Python do c2lint usando esta biblioteca, *tosse* PRs bem-vindos *tosse*)
O autor principal do pyMalleableC2 é Marcello Salvati
Twitter: @byt3bl33d3r, Github: @byt3bl33d3r
(Consulte a pasta exemplos para mais)
Gerar a AST para um Perfil Malleable C2 localizado num ficheiro e depois reconstruir o código fonte a partir da 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)
Gerar a AST para um Perfil Malleable C2 'inline' e depois reconstruir o código fonte a partir da 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)
Construir um perfil Malleable C2 programaticamente do 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)
Exemplo muito simples a mostrar como aleatorizar programaticamente um Perfil 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)