Skip to content

This is a basic write up of My theories of passive evasion. I haven't check whether someones already written something just like this before me, if they have I apologize before hand

Notifications You must be signed in to change notification settings

MalwareMakers/Malware-Evasion-Theory-Passive

Repository files navigation

Malware-Evasion-Theory-Passive

This is a basic write up of My theories of passive evasion. I haven't check whether someones already written something just like this before me, if they have I apologize before hand.

Star this if you find this helpful!

please it means a lot

Into to Obfuscation, Junking and Encryption (And some encodings):

First Obfuscation is literally making something hard to read. Junking is just an additional layer of obfuscation Encryption is literally locking something in code and seeing if someone can get past it.

Just an image

Obfuscation theory: My version

First create a name array of where thinsg are being called, where and how. Create an random string generator. For the length of the first array, create a second array of the same length of the first with a random strings. Using the first array as a system for location for replacement in the given code, use the second array's contents to fill em. Essentially renaming every instance accurately with every calling of the same thing, renamed to the same thing. This can be complicated to having every instance being called different but point to the same thing. Making code even harder to read.

Note: I'll share an example of this soon

Junking: My version

Just have a bunch of fodder code. If you can it would be recommened that you you do a careful mix and match of malware into an actual program using an array to shuffle. Just makes life easier. I've created a random system gen of strings, comments, fodder classes and functions.

class Junker: 
    def __init__(self, code_array,start_data,end_data): 
        self.code_array = code_array
        self.start_data = start_data
        self.end_data = end_data

    def random_statments(self): 
        generator = Name_gen()
        var_names = []
        assignments = []
        statements = []
        for x in range(0,random.randint(20,1000)): 
            data = generator.generate_random_string()
            data1 = generator.generate_random_string()
            while data in var_names:
                data = generator.generate_random_string()
            var_names.append(data)

            while data1 in assignments: 
                data1 = generator.generate_random_string()
            assignments.append(data1)
        
        for x in range(0,len(assignments)): 
            line = f'''

{var_names[x]} = "{var_names[x]}"

'''
            statements.append(line)

        return statements

    def Random_functions(self): 
        generator = Name_gen()
        function_operations = []
        function_choices = ['add','print','subtract','multiply','massive']
        functions = []
        for x in range(0,random.randint(200,1000)): 
            func_choice = random.choice(function_choices)
            function_operations.append(func_choice)
        
        for x in range(0, len(function_operations)): 
            if function_operations[x] == "add": 
                func_data = []
                for x in range(0,5): 
                    data = generator.generate_random_string()
                    while data in func_data:
                        data = generator.generate_random_string()
                    func_data.append(data)

                func = [
                    f'''
def {func_data[0]}(): 
    {func_data[1]} = "{func_data[2]}"
    {func_data[3]} = "{func_data[4]}"
    print(f"{{{func_data[1]}}} add {{{func_data[3]}}} results in {{{func_data[1]} + {func_data[3]}}}")

'''
                ]
                functions.append(func)
        
            if function_operations[x] == "subtract": 
                func_data = []
                for x in range(0,5): 
                    data = generator.generate_random_string()
                    while data in func_data:
                        data = generator.generate_random_string()
                    func_data.append(data)

                
                func = [
                    f'''

def {func_data[0]}(): 
    {func_data[1]} = "{func_data[2]}"
    {func_data[3]} = "{func_data[4]}"
    print(f"{{{func_data[1]}}} subtract {{{func_data[3]}}} results in {{{func_data[1]}.replace({func_data[3]}, '')}}")

'''
                ]
                functions.append(func)
            
            if function_operations[x] == "print": 
                func_data = []
                for x in range(0,4): 
                    data = generator.generate_random_string()
                    while data in func_data:
                        data = generator.generate_random_string()
                    func_data.append(data)

                func = [
                    f'''

#print('"{func_data[0]}" + "{func_data[1]}" + "{func_data[2]}" = "{func_data[3]}"')

'''
                ]

                functions.append(func)
            
            if function_operations[x] == "multiply":
                func_data = []
                for x in range(0,3): 
                    data = generator.generate_random_string()
                    while data in func_data:
                        data = generator.generate_random_string()
                    func_data.append(data)
                    num1 = random.randint(0,1000)
                    num2 = random.randint(0,1000)

                func = [
                    f'''

def {func_data[0]}(): 
    {func_data[1]} = {num1}
    {func_data[2]} = {num2}
    print(f"{{{func_data[2]}}} multiply {{{func_data[1]}}} results in {{{func_data[1]}*{func_data[2]}}}")

'''
                ] 

                functions.append(func)
            
            if function_operations[x] == "massive": 
                func_data = []
                for x in range(0,20): 
                    data = generator.generate_random_string()
                    while data in func_data:
                        data = generator.generate_random_string()
                    func_data.append(data)
                func = [
                    f'''

class {func_data[0]}: 
    def __init__(self,{func_data[1]},{func_data[2]})
        self.{func_data[3]} = {func_data[1]}
        self.{func_data[4]} = {func_data[2]}
    
    def {func_data[5]}: 
        {func_data[6]} = "{func_data[7]}"
        {func_data[8]} = []
        while True: 
            try: 
                {func_data[8]}.append(self.{func_data[6]})
            except Exception as e: 
                pass
            
            print("{{{func_data[8]}}}")

            if {func_data[6]}.lower() == "{func_data[9]}": 
                if {func_data[6]}.lower() == "{func_data[10]}"
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")
                    print(f"{{{func_data[10]}}}")

                else: 
                    if {func_data[6]} = "{func_data[11]}": 
                        {func_data[12]} = "{func_data[13]}"
                        {func_data[14]} = "{func_data[15]}"
                        {func_data[16]} = "{func_data[17]}"
                        {func_data[18]} = "{func_data[19]}"

'''
                ]
        return functions
        
    def Merge_Shuffle(self): 
        one_liners = self.random_statments()
        functions = self.Random_functions()
        merger_array = []
        merger_array.extend(one_liners)
        merger_array.extend(functions)
        merger_array.extend(self.code_array)
        random.shuffle(merger_array)
        merger_array.append(self.end_data)

        return merger_array

This is quite and inefficent script and a better way to do this would be by creating an actual generation Algorithim. Imagine procedural generation used in infinite games except now in code.

Encryptions: My version

My personal recommendation is as follows; dont use static - or for the purposes of this, static encryptions. Here's how I would go about creating encryption algorithims. Similar to to how I created a dynamic encoding system (I'll explain that later, or in the encodings section), create a dynamic encryption system. Use systematic approches to this, such as creating a random array of possible encryptions, like AES (Advanced Encryption System), DES (Data Encryption System) and Blowfish. This way the generated software will atleast be harder to signature. Additionally, I would highly recommend chaining this, if possible. This is as it increases the possible forms the software can take, as well as making it harder for things to detect the software based on signature or heruistics (Herustics can be gotten round as a result of how by layer encyrptions, you be chnaging the behaviour of the software).

More on this: https://www.splunk.com/en_us/blog/learn/data-encryption-methods-types.html

Encodings: My version

Now encodings are a bit of a grey area in my opinion. This is for a couple of reasons. First of all, encodings signifcantly increase the size of a code, Base64 encodings increase it by 33%. Base32 by over 50%. Base16 - also just called hexadecimal encoding doesn't increase the code size at all. Also encodings can easily be reversed. But encodings are still effective at this given point in time, for that reason - heres an example script.

import base64
import random
from Obfuscation_modules.obfuscation import * 
import time

class Encoder: 
    def __init__(self,file_path,start_data): 
        self.file_path = file_path
        self.start_data = start_data
        with open(self.file_path, 'rb') as f: 
            self.code_data = f.read()
            f.close()
        
        self.generation = Name_gen()

    def encoders_list(self): 
        encoding_operations = []
        encoding_options = ['b64encode','b32encode','b16encode']

        for x in range(0,random.randint(5,10)): 
            choice = random.choice(encoding_options)
            encoding_operations.append(choice)
        return encoding_operations
    
    def encoding(self,operation,data): 
        if operation == "b64encode": 
            data = base64.b64encode(data)
            run_data = f'''

import base64
data = {data}
exec(base64.b64decode(data))

'''.encode()
            time.sleep(3)
            return run_data
        
        if operation == "b32encode": 
                    data = base64.b32encode(data)
                    run_data = f'''

import base64
data = {data}
exec(base64.b32decode(data))

'''.encode()
                    time.sleep(3)
                    return run_data

        if operation == "b16encode": 
                data = base64.b16encode(data)
                run_data = f'''

import base64
data = {data}
exec(base64.b16decode(data))

'''.encode()
                time.sleep(3)
                return run_data

    
    def chain(self): 
        encoded_data = self.code_data
        encoding_operations = self.encoders_list()
        for operations in encoding_operations: 
            encoded_data = self.encoding(operation=operations, data=encoded_data)
        return encoded_data.decode()

    def Complete(self): 
        finalised_data = self.chain()        
        complete_data = f"{self.start_data}\n{finalised_data}"
        return complete_data

You will only need the base64 and random modules. The Time modules are only there to stop the script from running things too quickly and overloading your memory all together. this lines 'from Obfuscation_modules.obfuscation import *', is just for an intergration im doing with this, this is not needed at all, you would be making your own callings etc when doing this.

This script is very inefficient. Also the variety of encodings used is quite minimal.

About

This is a basic write up of My theories of passive evasion. I haven't check whether someones already written something just like this before me, if they have I apologize before hand

Topics

Resources

Stars

Watchers

Forks