Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed DOS Disk Mapping #1439

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/doogie_8086_crack.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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.
Expand Down
20 changes: 10 additions & 10 deletions examples/petya_8086_crack.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#

Expand Down Expand Up @@ -39,26 +39,26 @@ 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)
ql.run()

# 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)
Expand Down Expand Up @@ -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)
4 changes: 2 additions & 2 deletions qiling/loader/dos.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 28 additions & 14 deletions qiling/os/dos/interrupts/int13.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,27 @@ class DiskError(IntEnum):
def parse_dap(dapbs):
return struct.unpack("<BBHHHQ", dapbs)

def get_dos_disk_id(idx):
# https://en.wikipedia.org/wiki/Master_boot_record#BIOS_to_MBR_interface
fixed_disk_letters = "CDEFGHIJKLMNOPQRSTUVWXYZ"
floppy_letters = "ABCDEFGH"
if idx < 0x80 and idx < len(floppy_letters):
return floppy_letters[idx] + ":"
elif idx >= 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()


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
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down
Loading