Shofel2_T124_python/venv/lib/python3.10/site-packages/qiling/arch/arch.py

133 lines
3.4 KiB
Python
Raw Permalink Normal View History

2024-05-25 16:45:07 +00:00
#!/usr/bin/env python3
#
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#
from abc import abstractmethod
from unicorn import Uc
from unicorn.unicorn import UcContext
from capstone import Cs
from keystone import Ks
from qiling import Qiling
from qiling.const import QL_ARCH, QL_ENDIAN
from .register import QlRegisterManager
from .utils import QlArchUtils
class QlArch:
type: QL_ARCH
bits: int
def __init__(self, ql: Qiling):
self.ql = ql
self.utils = QlArchUtils(ql)
@property
@abstractmethod
def uc(self) -> Uc:
"""Get unicorn instance bound to arch.
"""
pass
@property
@abstractmethod
def regs(self) -> QlRegisterManager:
"""Architectural registers.
"""
pass
@property
def pointersize(self) -> int:
return self.bits // 8
def stack_push(self, value: int) -> int:
"""Push a value onto the architectural stack.
Args:
value: a numeric value to push
Returns: the top of stack after pushing the value
"""
self.regs.arch_sp -= self.pointersize
self.ql.mem.write_ptr(self.regs.arch_sp, value)
return self.regs.arch_sp
def stack_pop(self) -> int:
"""Pop a value from the architectural stack.
Returns: the value at the top of stack
"""
data = self.ql.mem.read_ptr(self.regs.arch_sp)
self.regs.arch_sp += self.pointersize
return data
def stack_read(self, offset: int) -> int:
"""Peek the architectural stack at a specified offset from its top, without affecting
the top of the stack.
Note that this operation violates the FIFO property of the stack and may be used cautiously.
Args:
offset: offset in bytes from the top of the stack, not necessarily aligned to the
native stack item size. the offset may be either positive or netagive, where
a 0 value means retrieving the value at the top of the stack
Returns: the value at the specified address
"""
return self.ql.mem.read_ptr(self.regs.arch_sp + offset)
def stack_write(self, offset: int, value: int) -> None:
"""Write a value to the architectural stack at a specified offset from its top, without
affecting the top of the stack.
Note that this operation violates the FIFO property of the stack and may be used cautiously.
Args:
offset: offset in bytes from the top of the stack, not necessarily aligned to the
native stack item size. the offset may be either positive or netagive, where
a 0 value means overwriting the value at the top of the stack
"""
self.ql.mem.write_ptr(self.regs.arch_sp + offset, value)
# Unicorn's CPU state save
def save(self) -> UcContext:
return self.uc.context_save()
# Unicorn's CPU state restore method
def restore(self, saved_context: UcContext):
self.uc.context_restore(saved_context)
@property
@abstractmethod
def disassembler(self) -> Cs:
"""Get disassembler instance bound to arch.
"""
pass
@property
@abstractmethod
def assembler(self) -> Ks:
"""Get assembler instance bound to arch.
"""
pass
@property
@abstractmethod
def endian(self) -> QL_ENDIAN:
"""Get processor endianess.
"""
pass