Chameleon is a polymorphic engine for x86_64 position independent shellcode that has been created out of the need to evade signature-based detections in red team environments.
Ensure you have radare2 installed. If you don't, clone the latest version and install it. Check radare2 repository for more information if needed.
git clone https://github.com/radareorg/radare2
radare2/sys/install.sh
Clone Chameleon and install the requirements.
git clone https://github.com/gum3t/chameleon
cd chameleon
pip3 install -r requirements.txt
Ready to go :)
$ python3 chameleon.py -h
usage: chameleon.py [-h] -i INPUT -o OUTPUT [-b BASE_ADDRESS] [-v] [--save-asm] [--shuffle] [--os {windows,linux}]
chameleon.py
options:
-h, --help show this help message and exit
-i INPUT, --input INPUT
input path (PI shellcode file to mutate)
-o OUTPUT, --output OUTPUT
output path (mutated shellcode)
-b BASE_ADDRESS, --base_address BASE_ADDRESS
shellcode base address
-v, --verbose verbose output
--save-asm save generated asm file in the current directory
--shuffle shuffle basic blocks before reassembling
--os {windows,linux} defined os for generated logic operations constants - windows by default
Chameleon provides an easy way to implement mutations for x86_64. Here there's an explaination on how to do it.
Each instance of the MutationPatternPool
class focuses on the mutation of a certain action. For example, moving a value from one register to another.
The implementation of this class can be found in mutation_patterns.py. There you can also find some examples of defined MutationPatternPool
.
Each instance of the MutationPatternPool
class has a set of match rules. The objective of the match rules is detecting the many patterns an action can have. For example, moving a value from one register to another one can be achieved using mov regA, regB
, but it can also be achieved via push regB; pop regA
(among many other possibilies).
A match rule receives a List[Instruction]
that represent a basic block and is able to check any of the attributes of the Instruction
class to find the desired patterns.
More information about the Instruction
class can be found in utils/disasm.py. Recommended attributes to find patterns are mnemonic
, operand_1
, operand_2
, opcode
, bytes
, esil
and type
.
The idea is to create a match rule for each of the patterns the desired action can have.
To create match rules, check mutation_match_rules.py. There you can find a template and some examples.
The mutation probability is the probability to apply a mutation once a mutation pattern has been found. It is defined as a percentage.
This value is assigned on the definition of a new MutationPatternPool
in mutation_patterns.py.
Each mutation generator is the responsible to provide an equivalent List[Instruction]
for the desired pattern.
A generator receives a List[Any]
that contains the necessary information to generate the new instructions. This list is generated by the match rules.
If we take the example told before (move a value from one register to another one), this list could contain the destination and the source registers of the action.
Generators can use the feature generate_shellcode(size, os)
, that will return a semantically neutral assembled shellcode of the given size.
The idea is to create a generator for each of the possible equivalent alternatives for the desired action.
To create generators, check mutation_generators.py. There you can find a template and some examples.
The author assumes no responsibility for misuse. |
Chameleon has been heavily tested with the ufo implant. Don't forget to check the repo!