Skip to content

Commit c0daea1

Browse files
committed
Refactor hooks in ntdll
1 parent b895748 commit c0daea1

File tree

1 file changed

+38
-37
lines changed

1 file changed

+38
-37
lines changed

qiling/os/windows/dlls/ntdll.py

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,36 @@ def hook_RtlPcToFileHeader(ql: Qiling, address: int, params):
493493
ql.mem.write_ptr(base_of_image_ptr, base_addr)
494494
return base_addr
495495

496+
def _FindImageBaseAndFunctionTable(ql: Qiling, control_pc: int, image_base_ptr: int):
497+
"""
498+
Helper function to locate a containing image for `control_pc` as well as its
499+
function table, while writing the image base to `image_base_ptr` (if non-zero).
500+
Returns:
501+
(base_addr, function_table_addr)
502+
if no image is found, otherwise
503+
(0, 0)
504+
"""
505+
containing_image = ql.loader.find_containing_image(control_pc)
506+
507+
if containing_image:
508+
base_addr = containing_image.base
509+
else:
510+
base_addr = 0
511+
512+
# Write base address to the ImageBase pointer, if provided
513+
if image_base_ptr != 0:
514+
ql.mem.write_ptr(image_base_ptr, base_addr)
515+
516+
# If we don’t have a valid base, abort now
517+
if base_addr == 0:
518+
return 0, 0
519+
520+
# Look up the function-table RVA and compute the absolute address
521+
function_table_rva = ql.loader.function_table_lookup.get(base_addr)
522+
function_table_addr = base_addr + function_table_rva if function_table_rva else 0
523+
524+
return base_addr, function_table_addr
525+
496526
# NTSYSAPI PRUNTIME_FUNCTION RtlLookupFunctionEntry(
497527
# [in] DWORD64 ControlPc,
498528
# [out] PDWORD64 ImageBase,
@@ -518,22 +548,11 @@ def hook_RtlLookupFunctionEntry(ql: Qiling, address: int, params):
518548
if ql.arch.type is QL_ARCH.X86:
519549
raise QlErrorNotImplemented("RtlLookupFunctionEntry is not implemented for x86")
520550

521-
containing_image = ql.loader.find_containing_image(control_pc)
522-
523-
if containing_image:
524-
base_addr = containing_image.base
525-
else:
526-
base_addr = 0
551+
base_addr, function_table_addr = _FindImageBaseAndFunctionTable(ql, control_pc, image_base_ptr)
527552

553+
# If no function table was found, abort.
554+
if function_table_addr == 0:
528555
return 0
529-
530-
# If we got a valid location to write the image base ptr,
531-
# copy it there, and proceed.
532-
if image_base_ptr != 0:
533-
ql.mem.write_ptr(image_base_ptr, base_addr)
534-
535-
# Get the base address of the function table.
536-
function_table_addr = base_addr + ql.loader.function_table_lookup[base_addr]
537556

538557
# Look up the RUNTIME_FUNCTION entry; we are interested in the index in the table
539558
# so that we can compute the address.
@@ -564,35 +583,17 @@ def hook_RtlLookupFunctionTable(ql: Qiling, address: int, params):
564583
size_of_table_ptr = params["SizeOfTable"]
565584

566585
# This function should not be getting called on x86.
567-
if ql.arch.type != QL_ARCH.X8664:
586+
if ql.arch.type is QL_ARCH.X86:
568587
raise QlErrorNotImplemented("RtlLookupFunctionTable is not implemented for x86")
569588

570-
containing_image = ql.loader.find_containing_image(control_pc)
589+
base_addr, function_table_addr = _FindImageBaseAndFunctionTable(ql, control_pc, image_base_ptr)
571590

572-
if containing_image:
573-
base_addr = containing_image.base
574-
else:
575-
base_addr = 0
591+
# If no function table was found, abort.
592+
if function_table_addr == 0:
593+
ql.mem.write_ptr(size_of_table_ptr, 0, 4)
576594

577595
return 0
578596

579-
# If we got a valid location to write the image base ptr,
580-
# copy it there, and proceed.
581-
if image_base_ptr != 0:
582-
ql.mem.write_ptr(image_base_ptr, base_addr)
583-
584-
# If image base was 0, we are not going to find a valid function
585-
# table anyway, so just return.
586-
if base_addr == 0:
587-
return 0
588-
589-
# Look up the RVA of the function table.
590-
function_table_rva = ql.loader.function_table_lookup[base_addr]
591-
592-
# The caller is expecting a pointer, so convert the RVA
593-
# to an absolute address.
594-
function_table_addr = int(base_addr + function_table_rva)
595-
596597
# If a valid pointer for the size was provided,
597598
# we want to figure out the size of the table.
598599
if size_of_table_ptr != 0:

0 commit comments

Comments
 (0)