Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 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
46 changes: 21 additions & 25 deletions examples/fuzzing/dlink_dir815/dir815_mips32el_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

# Everything about the bug and firmware https://www.exploit-db.com/exploits/33863

import os,sys
import sys
sys.path.append("../../..")

from qiling import Qiling
from qiling.const import QL_VERBOSE
from qiling.extensions.afl import ql_afl_fuzz


def main(input_file, enable_trace=False):
def main(input_file: str):

env_vars = {
"REQUEST_METHOD": "POST",
Expand All @@ -24,40 +24,36 @@ def main(input_file, enable_trace=False):
# "CONTENT_LENGTH": "8", # no needed
}

ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs",
verbose=QL_VERBOSE.DEBUG, env=env_vars, console=enable_trace)
ql = Qiling(["./rootfs/htdocs/web/hedwig.cgi"], "./rootfs", verbose=QL_VERBOSE.DISABLED, env=env_vars)

def place_input_callback(ql: Qiling, input: bytes, _: int):
env_var = ("HTTP_COOKIE=uid=1234&password=").encode()
env_vars = env_var + input + b"\x00" + (ql.path).encode() + b"\x00"
ql.mem.write(ql.target_addr, env_vars)
def place_input_callback(ql: Qiling, data: bytes, _: int) -> bool:
# construct the payload
payload = b''.join((b"HTTP_COOKIE=uid=1234&password=", bytes(data), b"\x00", ql_path, b"\x00"))

def start_afl(_ql: Qiling):
# patch the value of 'HTTP_COOKIE' in memory
ql.mem.write(target_addr, payload)

# payload is in place, we are good to go
return True

def start_afl(_ql: Qiling):
"""
Callback from inside
"""

ql_afl_fuzz(_ql, input_file=input_file, place_input_callback=place_input_callback, exits=[ql.os.exit_point])

addr = ql.mem.search("HTTP_COOKIE=uid=1234&password=".encode())
ql.target_addr = addr[0]
addr = ql.mem.search(b"HTTP_COOKIE=uid=1234&password=")
target_addr = addr[0]
ql_path = ql.path.encode()

main_addr = ql.loader.elf_entry
ql.hook_address(callback=start_afl, address=main_addr)
ql.hook_address(start_afl, ql.loader.elf_entry)

try:
ql.run()
os._exit(0)
except:
if enable_trace:
print("\nFuzzer Went Shit")
os._exit(0)
ql.run()


if __name__ == "__main__":
if len(sys.argv) == 1:
if len(sys.argv) < 2:
raise ValueError("No input file provided.")
if len(sys.argv) > 2 and sys.argv[1] == "-t":
main(sys.argv[2], enable_trace=True)
else:
main(sys.argv[1])

main(sys.argv[1])
2 changes: 1 addition & 1 deletion examples/sality.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def hook_StartServiceA(ql: Qiling, address: int, params):
init_unseen_symbols(ql.amsint32_driver, ntoskrnl.base+0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe")
#ql.amsint32_driver.debugger= ":9999"
try:
ql.amsint32_driver.load()
ql.amsint32_driver.run()
return 1
except UcError as e:
print("Load driver error: ", e)
Expand Down
2 changes: 2 additions & 0 deletions examples/tendaac1518_httpd.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ def __vfork(ql: Qiling):

ql.os.set_syscall('vfork', __vfork)

os.unlink(fr'{ROOTFS}/proc/sys/kernel/core_pattern')

ql.run()


Expand Down
11 changes: 7 additions & 4 deletions qiling/arch/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def get_base_and_name(self, addr: int) -> Tuple[int, str]:
return addr, '-'

def disassembler(self, ql: Qiling, address: int, size: int):
data = ql.mem.read(address, size)
data = memoryview(ql.mem.read(address, size))

# knowing that all binary sections are aligned to page boundary allows
# us to 'cheat' and search for the containing image using the aligned
Expand All @@ -64,11 +64,14 @@ def disassembler(self, ql: Qiling, address: int, size: int):
ba, name = self.get_base_and_name(ql.mem.align(address))

anibbles = ql.arch.bits // 4
pos = 0

for insn in ql.arch.disassembler.disasm(data, address):
offset = insn.address - ba
for iaddr, isize, mnem, ops in ql.arch.disassembler.disasm_lite(data, address):
offset = iaddr - ba
ibytes = data[pos:pos + isize]

ql.log.info(f'{insn.address:0{anibbles}x} [{name:20s} + {offset:#08x}] {insn.bytes.hex(" "):20s} {insn.mnemonic:20s} {insn.op_str}')
ql.log.info(f'{iaddr:0{anibbles}x} [{name:20s} + {offset:#08x}] {ibytes.hex():22s} {mnem:16s} {ops}')
pos += isize

if ql.verbose >= QL_VERBOSE.DUMP:
for reg in ql.arch.regs.register_mapping:
Expand Down
6 changes: 6 additions & 0 deletions qiling/cc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ def setReturnValue(self, val: int) -> None:

raise NotImplementedError

def getReturnAddress(self) -> int:
"""Get function return address.
"""

raise NotImplementedError

def setReturnAddress(self, addr: int) -> None:
"""Set function return address.

Expand Down
7 changes: 6 additions & 1 deletion qiling/cc/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,22 @@ class QlArmBaseCC(QlCommonBaseCC):
def getNumSlots(argbits: int) -> int:
return 1

def getReturnAddress(self) -> int:
return self.arch.regs.lr

def setReturnAddress(self, addr: int) -> None:
self.arch.regs.lr = addr

def unwind(self, nslots: int) -> int:
# TODO: cleanup?
return self.arch.regs.lr
return self.getReturnAddress()


class aarch64(QlArmBaseCC):
_retreg = UC_ARM64_REG_X0
_argregs = make_arg_list(UC_ARM64_REG_X0, UC_ARM64_REG_X1, UC_ARM64_REG_X2, UC_ARM64_REG_X3, UC_ARM64_REG_X4, UC_ARM64_REG_X5, UC_ARM64_REG_X6, UC_ARM64_REG_X7)


class aarch32(QlArmBaseCC):
_retreg = UC_ARM_REG_R0
_argregs = make_arg_list(UC_ARM_REG_R0, UC_ARM_REG_R1, UC_ARM_REG_R2, UC_ARM_REG_R3)
3 changes: 3 additions & 0 deletions qiling/cc/intel.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class QlIntelBaseCC(QlCommonBaseCC):
Supports arguments passing over registers and stack.
"""

def getReturnAddress(self) -> int:
return self.arch.stack_read(0)

def setReturnAddress(self, addr: int) -> None:
self.arch.stack_push(addr)

Expand Down
3 changes: 3 additions & 0 deletions qiling/cc/mips.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class mipso32(QlCommonBaseCC):
_shadow = 4
_retaddr_on_stack = False

def getReturnAddress(self) -> int:
return self.arch.regs.ra

def setReturnAddress(self, addr: int):
self.arch.regs.ra = addr

Expand Down
3 changes: 3 additions & 0 deletions qiling/cc/ppc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ class ppc(QlCommonBaseCC):
def getNumSlots(argbits: int):
return 1

def getReturnAddress(self) -> int:
return self.arch.regs.lr

def setReturnAddress(self, addr: int):
self.arch.regs.lr = addr
3 changes: 3 additions & 0 deletions qiling/cc/riscv.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ class riscv(QlCommonBaseCC):
def getNumSlots(argbits: int):
return 1

def getReturnAddress(self) -> int:
return self.arch.regs.ra

def setReturnAddress(self, addr: int):
self.arch.regs.ra = addr
50 changes: 25 additions & 25 deletions qiling/core_struct.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 All @@ -25,14 +25,14 @@ def __init__(self, endian: QL_ENDIAN, bit: int):
QL_ENDIAN.EB: '>'
}[endian]

self._fmt8 = f'{modifier}B'
self._fmt8s = f'{modifier}b'
self._fmt16 = f'{modifier}H'
self._fmt16s = f'{modifier}h'
self._fmt32 = f'{modifier}I'
self._fmt32s = f'{modifier}i'
self._fmt64 = f'{modifier}Q'
self._fmt64s = f'{modifier}q'
self._fmt8 = struct.Struct(f'{modifier}B')
self._fmt8s = struct.Struct(f'{modifier}b')
self._fmt16 = struct.Struct(f'{modifier}H')
self._fmt16s = struct.Struct(f'{modifier}h')
self._fmt32 = struct.Struct(f'{modifier}I')
self._fmt32s = struct.Struct(f'{modifier}i')
self._fmt64 = struct.Struct(f'{modifier}Q')
self._fmt64s = struct.Struct(f'{modifier}q')

handlers = {
64 : (self.pack64, self.pack64s, self.unpack64, self.unpack64s),
Expand All @@ -51,49 +51,49 @@ def __init__(self, endian: QL_ENDIAN, bit: int):
self.unpacks = ups

def pack64(self, x: int, /) -> bytes:
return struct.pack(self._fmt64, x)
return self._fmt64.pack(x)

def pack64s(self, x: int, /) -> bytes:
return struct.pack(self._fmt64s, x)
return self._fmt64s.pack(x)

def unpack64(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64, x)[0]
return self._fmt64.unpack(x)[0]

def unpack64s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt64s, x)[0]
return self._fmt64s.unpack(x)[0]

def pack32(self, x: int, /) -> bytes:
return struct.pack(self._fmt32, x)
return self._fmt32.pack(x)

def pack32s(self, x: int, /) -> bytes:
return struct.pack(self._fmt32s, x)
return self._fmt32s.pack(x)

def unpack32(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32, x)[0]
return self._fmt32.unpack(x)[0]

def unpack32s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt32s, x)[0]
return self._fmt32s.unpack(x)[0]

def pack16(self, x: int, /) -> bytes:
return struct.pack(self._fmt16, x)
return self._fmt16.pack(x)

def pack16s(self, x: int, /) -> bytes:
return struct.pack(self._fmt16s, x)
return self._fmt16s.pack(x)

def unpack16(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16, x)[0]
return self._fmt16.unpack(x)[0]

def unpack16s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt16s, x)[0]
return self._fmt16s.unpack(x)[0]

def pack8(self, x: int, /) -> bytes:
return struct.pack(self._fmt8, x)
return self._fmt8.pack(x)

def pack8s(self, x: int, /) -> bytes:
return struct.pack(self._fmt8s, x)
return self._fmt8s.pack(x)

def unpack8(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8, x)[0]
return self._fmt8.unpack(x)[0]

def unpack8s(self, x: ReadableBuffer, /) -> int:
return struct.unpack(self._fmt8s, x)[0]
return self._fmt8s.unpack(x)[0]
4 changes: 2 additions & 2 deletions qiling/extensions/afl/afl.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ def ql_afl_fuzz_custom(ql: Qiling,
def __place_input_wrapper(uc: Uc, input_bytes: Array[c_char], iters: int, context: Any) -> bool:
return place_input_callback(ql, input_bytes.raw, iters)

def __validate_crash_wrapper(uc: Uc, result: int, input_bytes: bytes, iters: int, context: Any) -> bool:
return validate_crash_callback(ql, result, input_bytes, iters)
def __validate_crash_wrapper(uc: Uc, result: int, input_bytes: Array[c_char], iters: int, context: Any) -> bool:
return validate_crash_callback(ql, result, input_bytes.raw, iters)

def __fuzzing_wrapper(uc: Uc, context: Any) -> int:
return fuzzing_callback(ql)
Expand Down
Loading
Loading