Exemplo n.º 1
0
def second_stage(ql: Qiling):
    disk = QlDisk("rootfs/8086/petya/out_1M.raw", 0x80)
    #nonce = get_nonce(disk)
    verfication_data = disk.read_sectors(0x37, 1)
    nonce_data = disk.read_sectors(0x36, 1)
    ql.reg.sp -= 0x200
    verification_data_address = ql.reg.sp
    ql.reg.sp -= 0x200
    nonce_address = ql.reg.sp + 0x21
    ql.reg.sp -= 0x20
    key_address = ql.reg.sp
    ql.mem.write(verification_data_address, verfication_data)
    ql.mem.write(nonce_address - 0x21, nonce_data)
    ql.arch.stack_push(0x200)
    ql.arch.stack_push(verification_data_address)
    ql.arch.stack_push(0)
    ql.arch.stack_push(nonce_address)
    ql.arch.stack_push(key_address)
    for x in product(list(accepted_chars), repeat=2):
        ctx = ql.save()
        # 3xMxjxXxLxoxmxAx
        key = b"3xMxjxXxLxoxmx" + ("".join(x)).encode("utf-8")
        print(f"Trying: {key}")
        if one_round(ql, key, key_address):
            print(f"Key: {key}")
            return key
        else:
            ql.restore(ctx)
    return None
Exemplo n.º 2
0
def first_stage():
    ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"],
                "rootfs/8086",
                console=False,
                verbose=QL_VERBOSE.DEBUG)
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
    # Workaround for `until` in uc_emu_start not working with dynamic loaded code.
    ql.hook_code(stop, begin=petya_2nd_stage_start, end=petya_2nd_stage_start)
    ql.run()
    return ql
Exemplo n.º 3
0
def first_stage():
    ql = Qiling(["rootfs/8086/petya/mbr.bin"],
                "rootfs/8086",
                console=False,
                output="debug",
                log_dir=".")
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
    # Workaround for `until` in uc_emu_start not working with dynamic loaded code.
    ql.hook_code(stop, begin=petya_2nd_stage_start, end=petya_2nd_stage_start)
    ql.run()
    return ql
Exemplo n.º 4
0
def first_stage():
    ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
                "rootfs/8086",
                console=False)
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
    # Doogie suggests that the datetime should be 1990-02-06.
    ql.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
    # A workaround to stop the program.
    hk = ql.hook_code(stop, begin=0x8018, end=0x8018)
    ql.run()
    ql.hook_del(hk)
    return ql
Exemplo n.º 5
0
    def run(self):
        path = self.ql.path

        self.ticks_per_second = float(
            self.ql.profile.get("KERNEL", "ticks_per_second"))
        if (str(path)).endswith(".DOS_COM") or (
                str(path)).endswith(".DOS_EXE"):
            # pure com
            self.cs = int(self.ql.profile.get("COM", "start_cs"), 16)
            self.ip = int(self.ql.profile.get("COM", "start_ip"), 16)
            self.sp = int(self.ql.profile.get("COM", "start_sp"), 16)
            self.stack_size = int(self.ql.profile.get("COM", "stack_size"), 16)
            self.ql.reg.cs = self.cs
            self.ql.reg.ds = self.cs
            self.ql.reg.es = self.cs
            self.ql.reg.ss = self.cs
            self.ql.reg.ip = self.ip
            self.ql.reg.sp = self.sp
            self.start_address = self.cs * 16 + self.ip
            self.base_address = int(self.ql.profile.get("COM", "base_address"),
                                    16)
            self.stack_address = int(self.ql.reg.ss * 16 + self.ql.reg.sp)
            self.ql.mem.map(0, 0x100000, info="[FULL]")
            with open(path, "rb+") as f:
                bs = f.read()
            self.ql.mem.write(self.start_address, bs)
            self.load_address = self.base_address
            self.ql.os.entry_point = self.start_address
        elif (str(path)).endswith(".DOS_MBR"):
            # MBR
            self.start_address = 0x7C00
            with open(path, "rb+") as f:
                bs = f.read()
            if not self.ql.os.fs_mapper.has_mapping(0x80):
                self.ql.os.fs_mapper.add_fs_mapping(0x80, QlDisk(path, 0x80))
            # Map all available address.
            self.ql.mem.map(0x0, 0x1000000)
            self.ql.mem.write(self.start_address, bs)
            self.cs = 0
            self.ql.reg.ds = self.cs
            self.ql.reg.es = self.cs
            self.ql.reg.ss = self.cs
            # 0x80 -> first drive.
            # https://en.wikipedia.org/wiki/Master_boot_record#BIOS_to_MBR_interface
            self.ql.reg.dx = 0x80
            self.ip = self.start_address
            self.load_address = self.start_address
            self.ql.os.entry_point = self.start_address
        else:
            raise NotImplementedError()

        sys.excepthook = self.excepthook
Exemplo n.º 6
0
def third_stage(keys):
    # To setup terminal again, we have to restart the whole program.
    ql = Qiling(["rootfs/8086/doogie/doogie.DOS_MBR"],
                "rootfs/8086",
                console=False)
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", 0x80))
    ql.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT)
    hk = ql.hook_code(stop, begin=0x8018, end=0x8018)
    ql.run()
    ql.hook_del(hk)
    # Snapshot API.
    ctx = ql.save()
    for key in keys:
        show_once(ql, key)
        ql.restore(ctx)
Exemplo n.º 7
0
def third_stage(key):
    def pass_red(ql, addr, data):
        curses.ungetch(ord("\n"))
        curses.ungetch(ord("\r"))

    def input_key(ql, addr, data):
        for i in key[::-1]:
            curses.ungetch(i)
        curses.ungetch(ord("\n"))
        curses.ungetch(ord("\r"))

    ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"],
                "rootfs/8086",
                console=False,
                verbose=QL_VERBOSE.DEBUG)
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
    ql.hook_code(pass_red, begin=0x886d, end=0x886d)
    ql.hook_code(input_key, begin=0x85f0, end=0x85f0)
    ql.hook_code(stop, begin=0x6806, end=0x6806)
    ql.run()
Exemplo n.º 8
0
def third_stage(key):
    def pass_red(ql, addr, data):
        curses.ungetch(ord("\n"))
        curses.ungetch(ord("\r"))

    def input_key(ql, addr, data):
        for i in key[::-1]:
            curses.ungetch(i)
        curses.ungetch(ord("\n"))
        curses.ungetch(ord("\r"))

    ql = Qiling(["rootfs/8086/petya/mbr.bin"],
                "rootfs/8086",
                console=False,
                output="debug",
                log_dir=".")
    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
    ql.hook_code(pass_red, begin=0x886d, end=0x886d)
    ql.hook_code(input_key, begin=0x85f0, end=0x85f0)
    ql.hook_code(stop, begin=0x6806, end=0x6806)
    ql.run()
Exemplo n.º 9
0
    def run(self):
        path = self.ql.path
        profile = self.ql.profile

        # bare com file
        if path.endswith(".DOS_COM"):
            with open(path, "rb") as f:
                content = f.read()

            cs = int(profile.get("COM", "start_cs"), 0)
            ip = int(profile.get("COM", "start_ip"), 0)
            sp = int(profile.get("COM", "start_sp"), 0)
            ss = cs

            base_address = (cs << 4) + ip

        # com file with a dos header
        elif path.endswith(".DOS_EXE"):
            with open(path, "rb") as f:
                content = f.read()

            com = ComParser(self.ql, content)

            cs = com.init_cs
            ip = com.init_ip
            sp = com.init_sp
            ss = com.init_ss

            base_address = 0
            content = content[0x80:]

        elif path.endswith(".DOS_MBR"):
            with open(path, "rb") as f:
                content = f.read()

            cs = 0x0000
            ip = 0x7c00
            sp = 0xfff0
            ss = cs

            base_address = (cs << 4) + ip

            # https://en.wikipedia.org/wiki/Master_boot_record#BIOS_to_MBR_interface
            if not self.ql.os.fs_mapper.has_mapping(0x80):
                self.ql.os.fs_mapper.add_fs_mapping(0x80, QlDisk(path, 0x80))

            # 0x80 -> first drive
            self.ql.arch.regs.dx = 0x80
        else:
            raise NotImplementedError()

        self.ql.arch.regs.cs = cs
        self.ql.arch.regs.ds = cs
        self.ql.arch.regs.es = cs
        self.ql.arch.regs.ss = ss
        self.ql.arch.regs.ip = ip
        self.ql.arch.regs.sp = sp

        self.stack_address = (ss << 4) + sp
        self.start_address = (cs << 4) + ip
        self.stack_size = int(profile.get("COM", "stack_size"), 0)
        self.ticks_per_second = profile.getfloat("KERNEL", "ticks_per_second")

        # map the entire system memory
        self.ql.mem.map(0, 0x100000, info="[FULL]")
        self.ql.mem.write(base_address, content)

        self.load_address = base_address
        self.ql.os.entry_point = self.start_address

        sys.excepthook = self.excepthook
Exemplo n.º 10
0
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
# Built on top of Unicorn emulator (www.unicorn-engine.org)

import sys
sys.path.append("..")
from qiling import *
from qiling.os.disk import QlDisk

if __name__ == "__main__":
    ql = Qiling(["rootfs/8086/petya/mbr.bin"],
                "rootfs/8086",
                console=False,
                output="debug",
                log_dir=".")
    # Note:
    # This image is only intended for PoC since the core petya code resides in the
    # specific sectors of a harddisk. It doesn't contain any data, either encryted
    # or unencrypted.

    ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80))
    ql.run()