diff --git a/examples/doogie_8086_crack.py b/examples/doogie_8086_crack.py index 8553a9309..58db6a27b 100644 --- a/examples/doogie_8086_crack.py +++ b/examples/doogie_8086_crack.py @@ -137,7 +137,7 @@ def show_once(ql: Qiling, key): 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.add_fs_mapper("C:", QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", "C:")) ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT) hk = ql.hook_code(stop, begin=0x8018, end=0x8018) ql.run() @@ -191,7 +191,7 @@ def stop(ql, addr, data): # In this stage, we get the encrypted data which xored with the specific date. 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)) + ql.add_fs_mapper("C:", QlDisk("rootfs/8086/doogie/doogie.DOS_MBR", "C:")) # Doogie suggests that the datetime should be 1990-02-06. ql.os.set_api((0x1a, 4), set_required_datetime, QL_INTERCEPT.EXIT) # A workaround to stop the program. diff --git a/examples/petya_8086_crack.py b/examples/petya_8086_crack.py index 752202690..8cc5e4be6 100644 --- a/examples/petya_8086_crack.py +++ b/examples/petya_8086_crack.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -39,18 +39,18 @@ 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"], + ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"], "rootfs/8086", - console=False, + console=False, verbose=QL_VERBOSE.DEBUG) - ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80)) + ql.add_fs_mapper("C:", QlDisk("rootfs/8086/petya/out_1M.raw", "C:")) 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) @@ -58,7 +58,7 @@ def input_key(ql, addr, data): # In this stage, we will crack for the password. def second_stage(ql: Qiling): - disk = QlDisk("rootfs/8086/petya/out_1M.raw", 0x80) + disk = QlDisk("rootfs/8086/petya/out_1M.raw", "C:") #nonce = get_nonce(disk) verfication_data = disk.read_sectors(0x37, 1) nonce_data = disk.read_sectors(0x36, 1) @@ -89,18 +89,18 @@ def second_stage(ql: Qiling): # In this stage, we have to wait for petya being load to the right place. def first_stage(): - ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"], + ql = Qiling(["rootfs/8086/petya/petya.DOS_MBR"], "rootfs/8086", - console=False, + console=False, verbose=QL_VERBOSE.DEBUG) - ql.add_fs_mapper(0x80, QlDisk("rootfs/8086/petya/out_1M.raw", 0x80)) + ql.add_fs_mapper("C:", QlDisk("rootfs/8086/petya/out_1M.raw", "C:")) # 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 if __name__ == "__main__": - + ql = first_stage() key = second_stage(ql) third_stage(key) \ No newline at end of file diff --git a/qiling/loader/dos.py b/qiling/loader/dos.py index 8b844841b..8502d6fee 100644 --- a/qiling/loader/dos.py +++ b/qiling/loader/dos.py @@ -90,8 +90,8 @@ def run(self): 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_mapping(0x80, QlDisk(path, 0x80)) + if not self.ql.os.fs_mapper.has_mapping("C:"): + self.ql.os.fs_mapper.add_mapping("C:", QlDisk(path, 0x80)) # 0x80 -> first drive self.ql.arch.regs.dx = 0x80 diff --git a/qiling/os/dos/interrupts/int13.py b/qiling/os/dos/interrupts/int13.py index a9c08a013..b87ea0998 100644 --- a/qiling/os/dos/interrupts/int13.py +++ b/qiling/os/dos/interrupts/int13.py @@ -43,6 +43,16 @@ class DiskError(IntEnum): def parse_dap(dapbs): return struct.unpack("= 0x80 and idx < 0x80 + len(fixed_disk_letters): + return fixed_disk_letters[idx-0x80] + ":" + else: + return f"INVALID{idx:#x}" + ":" def __leaf_00(ql: Qiling): ql.os.clear_cf() @@ -50,9 +60,10 @@ def __leaf_00(ql: Qiling): def __leaf_02(ql: Qiling): idx = ql.arch.regs.dl + disk_id = get_dos_disk_id(idx) - if not ql.os.fs_mapper.has_mapping(idx): - ql.log.warning(f'Warning: No such disk: {idx:#x}') + if not ql.os.fs_mapper.has_mapping(disk_id): + ql.log.warning(f'Warning: No such disk: {disk_id}') ql.arch.regs.ah = DiskError.BadCommand.value ql.os.set_cf() return @@ -62,7 +73,7 @@ def __leaf_02(ql: Qiling): sector = ql.arch.regs.cx & 63 cnt = ql.arch.regs.al - disk = ql.os.fs_mapper.open(idx, None) + disk = ql.os.fs_mapper.open(disk_id, None) content = disk.read_chs(cylinder, head, sector, cnt) ql.mem.write(utils.linaddr(ql.arch.regs.es, ql.arch.regs.bx), content) @@ -73,14 +84,15 @@ def __leaf_02(ql: Qiling): # @see: https://stanislavs.org/helppc/int_13-8.html def __leaf_08(ql: Qiling): idx = ql.arch.regs.dl + disk_id = get_dos_disk_id(idx) - if not ql.os.fs_mapper.has_mapping(idx): - ql.log.warning(f'Warning: No such disk: {idx:#x}') + if not ql.os.fs_mapper.has_mapping(disk_id): + ql.log.warning(f'Warning: No such disk: {disk_id}') ql.arch.regs.ah = DiskError.BadCommand.value ql.os.set_cf() return - disk = ql.os.fs_mapper.open(idx, None) + disk = ql.os.fs_mapper.open(disk_id, None) ql.arch.regs.dl = ql.os.fs_mapper.mapping_count() ql.arch.regs.dh = disk.n_heads - 1 ql.arch.regs.bl = 0x4 @@ -108,18 +120,19 @@ def __leaf_41(ql: Qiling): def __leaf_42(ql: Qiling): idx = ql.arch.regs.dl + disk_id = get_dos_disk_id(idx) - if not ql.os.fs_mapper.has_mapping(idx): - ql.log.warning(f'Warning: No such disk: {idx:#x}') + if not ql.os.fs_mapper.has_mapping(disk_id): + ql.log.warning(f'Warning: No such disk: {disk_id}') ql.arch.regs.ah = DiskError.BadCommand.value ql.os.set_cf() return dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16) _, _, cnt, offset, segment, lba = parse_dap(dapbs) - ql.log.info(f'Reading {cnt} sectors from disk {idx:#x} with LBA {lba}') + ql.log.info(f'Reading {cnt} sectors from disk {disk_id} with LBA {lba}') - disk = ql.os.fs_mapper.open(idx, None) + disk = ql.os.fs_mapper.open(disk_id, None) content = disk.read_sectors(lba, cnt) ql.mem.write(utils.linaddr(segment, offset), content) @@ -128,18 +141,19 @@ def __leaf_42(ql: Qiling): def __leaf_43(ql: Qiling): idx = ql.arch.regs.dl + disk_id = get_dos_disk_id(idx) - if not ql.os.fs_mapper.has_mapping(idx): - ql.log.info(f"Warning: No such disk: {hex(idx)}") + if not ql.os.fs_mapper.has_mapping(disk_id): + ql.log.info(f"Warning: No such disk: {disk_id}") ql.arch.regs.ah = DiskError.BadCommand.value ql.os.set_cf() return dapbs = ql.mem.read(utils.linaddr(ql.arch.regs.ds, ql.arch.regs.si), 16) _, _, cnt, offset, segment, lba = parse_dap(dapbs) - ql.log.info(f'Writing {cnt} sectors to disk {idx:#x} with LBA {lba}') + ql.log.info(f'Writing {cnt} sectors to disk {disk_id} with LBA {lba}') - disk = ql.os.fs_mapper.open(idx, None) + disk = ql.os.fs_mapper.open(disk_id, None) buffer = ql.mem.read(utils.linaddr(segment, offset), cnt * disk.sector_size) disk.write_sectors(lba, cnt, buffer)