Skip to content
Merged
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
2 changes: 1 addition & 1 deletion src/chomper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .core import Chomper

__version__ = "0.3.7"
__version__ = "0.3.8"
56 changes: 22 additions & 34 deletions src/chomper/os/android/android.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@

ENVIRON_VARIABLES = """"""

# Virtual device files
DEVICES_FILES = {
"/dev/null": NullDevice,
"/dev/random": RandomDevice,
"/dev/urandom": UrandomDevice,
}


class AndroidOs(PosixOs):
"""Provide Android environment."""
Expand Down Expand Up @@ -154,17 +161,6 @@ def clock_getres(self) -> bytes:
)
return struct_to_bytes(st)

def _setup_hooks(self):
"""Initialize the hooks."""
self.emu.hooks.update(get_hooks())

def _setup_syscall_handlers(self):
"""Initialize system call handlers."""
# Only compatible with arm64 now
if self.emu.arch == arm64_arch:
self.emu.syscall_handlers.update(get_syscall_handlers())
self.emu.syscall_names.update(get_syscall_names())

def _setup_tls(self):
"""Initialize thread local storage (TLS)."""
if self.emu.arch == arm64_arch:
Expand All @@ -177,14 +173,10 @@ def _setup_tls(self):
self.emu.write_pointer(TLS_ADDRESS + 0x8, thread_ptr)
self.emu.write_pointer(TLS_ADDRESS + 0x10, errno_ptr)

def _check_libc(self) -> bool:
"""Check whether libc has been loaded."""
return bool(self.emu.find_module("libc.so"))

def _enable_libc(self):
def _enable_libc(self) -> bool:
"""Attempt to load libc."""
if not self.rootfs_path:
return
return False

if self.emu.arch == arm64_arch:
lib_dir = "system/lib64"
Expand All @@ -194,9 +186,10 @@ def _enable_libc(self):
libc_path = os.path.join(self.rootfs_path, lib_dir, "libc.so")

if not os.path.exists(libc_path):
return
return False

self.emu.load_module(libc_path, exec_init_array=False)
return True

def _create_fp(self, fd: int, mode: str, unbuffered: bool = False) -> int:
"""Wrap file descriptor to file object by calling `fdopen`."""
Expand Down Expand Up @@ -238,26 +231,21 @@ def _setup_environ(self):
environ = self.emu.get_symbol("environ")
self.emu.write_pointer(environ.address, environ_buf)

def _setup_devices(self):
"""Mount virtual device files."""
device_map = {
"/dev/null": NullDevice,
"/dev/random": RandomDevice,
"/dev/urandom": UrandomDevice,
}
def initialize(self):
# Setup hooks
self.emu.hooks.update(get_hooks())

for path, dev_cls in device_map.items():
self.mount_device(path, dev_cls)
# Setup syscall handles
if self.emu.arch == arm64_arch:
# Only compatible with arm64 now
self.emu.syscall_handlers.update(get_syscall_handlers())
self.emu.syscall_names.update(get_syscall_names())

def initialize(self):
self._setup_hooks()
self._setup_syscall_handlers()
self._setup_devices()
# Mount virtual device files
self.mount_devices(DEVICES_FILES)

self._setup_tls()

self._enable_libc()

if self._check_libc():
if self._enable_libc():
self._setup_standard_io()
self._setup_environ()
1 change: 1 addition & 0 deletions src/chomper/os/ios/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
SYS_FSTATFS64 = 0x15A
SYS_FSSTAT64 = 0x15B
SYS_BSDTHREAD_CREATE = 0x168
SYS_KQUEUE = 0x16A
SYS_LCHOWN = 0x16C
SYS_WORKQ_OPEN = 0x16F
SYS_WORKQ_KERNRETURN = 0x170
Expand Down
152 changes: 67 additions & 85 deletions src/chomper/os/ios/ios.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
# Symbolic links in the file system
SYMBOLIC_LINKS = {
"/etc": "/private/etc",
"/tmp": "/private/tmp",
"/tmp": "/private/var/tmp",
"/var": "/private/var",
"/usr/share/zoneinfo": "/var/db/timezone/zoneinfo",
"/var/db/timezone/icutz": "/var/db/timezone/tz/2024a.1.0/icutz/",
Expand All @@ -133,6 +133,13 @@
"AppleLocale": "zh-Hans",
}

# Virtual device files
DEVICES_FILES = {
"/dev/null": NullDevice,
"/dev/random": RandomDevice,
"/dev/urandom": UrandomDevice,
}


class IosOs(PosixOs):
"""Provide iOS environment."""
Expand Down Expand Up @@ -160,6 +167,14 @@ class IosOs(PosixOs):
MACH_PORT_START_VALUE = 65536
MACH_PORT_MAX_NUM = 10000

MACH_SERVICES = {
"com.apple.system.notification_center": MACH_PORT_NOTIFICATION_CENTER,
"com.apple.CARenderServer": MACH_PORT_CA_RENDER_SERVER,
"com.apple.lsd.advertisingidentifiers": MACH_PORT_ADVERTISING_IDENTIFIERS,
"com.apple.backboard.hid.services": MACH_PORT_BKS_HID_SERVER,
"com.apple.SystemConfiguration.configd": MACH_PORT_CONFIGD,
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

Expand Down Expand Up @@ -325,15 +340,6 @@ def getdirentries(self, fd: int, offset: int) -> Optional[bytes]:
)
return struct_to_bytes(st)

def _setup_hooks(self):
"""Initialize hooks."""
self.emu.hooks.update(get_hooks())

def _setup_syscall_handlers(self):
"""Initialize system call handlers."""
self.emu.syscall_handlers.update(get_syscall_handlers())
self.emu.syscall_names.update(get_syscall_names())

def _setup_tls(self):
"""Initialize thread local storage (TLS)."""
errno_ptr = self.emu.create_buffer(0x8)
Expand All @@ -345,18 +351,9 @@ def _setup_tls(self):
self.emu.write_pointer(TLS_ADDRESS + 0x8, errno_ptr)
self.emu.write_u32(TLS_ADDRESS + 0x18, 5)

def _setup_devices(self):
"""Mount virtual device files."""
device_map = {
"/dev/null": NullDevice,
"/dev/random": RandomDevice,
"/dev/urandom": UrandomDevice,
}
def _setup_system_registers(self):
"""Initialize MMIO for system registers."""

for path, dev_cls in device_map.items():
self.mount_device(path, dev_cls)

def _setup_mmio(self):
def read_cb(uc, offset, size_, read_ud):
# Arch type
if offset == 0x23:
Expand Down Expand Up @@ -414,9 +411,6 @@ def _init_lib_dyld(self):
environ = self.emu.get_symbol("_environ")
self.emu.write_pointer(environ.address, environ_buf)

def _init_lib_system_kernel(self):
self.emu.call_symbol("_mach_init_doit")

def _init_lib_system_c(self):
# __program_vars_init
argc = self.emu.create_buffer(8)
Expand Down Expand Up @@ -473,12 +467,6 @@ def _init_lib_system_pthread(self):
mach_task_self = self.emu.get_symbol("_mach_task_self_")
self.emu.write_u32(mach_task_self.address, self.MACH_PORT_TASK)

def _init_lib_system_trace(self):
self.emu.call_symbol("__libtrace_init")

def _init_lib_xpc(self):
self.emu.call_symbol("__libxpc_initializer")

def _init_lib_objc(self):
prototypes = self.emu.get_symbol("__ZL10prototypes")
self.emu.write_u64(prototypes.address, 0)
Expand All @@ -497,14 +485,6 @@ def _init_lib_objc(self):

self.emu.call_symbol("__objc_init")

def _init_core_foundation(self):
self._fix_method_signature_rom_table()

self.emu.call_symbol("___CFInitialize")

def _init_foundation(self):
self.emu.call_symbol("__NSInitializePlatform")

def _init_system_symbols(self):
# libsandbox.dylib
amkrtemp_sentinel = self.emu.get_symbol("__amkrtemp.sentinel")
Expand Down Expand Up @@ -532,6 +512,33 @@ def _init_system_symbols(self):
if g_user_unlocked_since_boot:
self.emu.write_u8(g_user_unlocked_since_boot.address, 1)

def _init_system_module(self, name: str, module: Module):
"""For certain system modules, perform additional initialization before
and after Objective-C initialization."""
if name == "libsystem_kernel.dylib":
self.emu.call_symbol("_mach_init_doit")
elif name == "libsystem_c.dylib":
self._init_lib_system_c()
elif name == "libdyld.dylib":
self._init_lib_dyld()
elif name == "libsystem_pthread.dylib":
self._init_lib_system_pthread()
elif name == "libsystem_trace.dylib":
self.emu.call_symbol("__libtrace_init")
elif name == "libobjc.A.dylib":
self._init_lib_objc()

# Initialize Objective-C
self.init_objc(module)

if name == "libxpc.dylib":
self.emu.call_symbol("__libxpc_initializer")
elif name == "CoreFoundation":
self._fix_method_signature_rom_table()
self.emu.call_symbol("___CFInitialize")
elif name == "Foundation":
self.emu.call_symbol("__NSInitializePlatform")

def init_objc(self, module: Module):
"""Initialize Objective-C for the module by calling `map_images`
and `load_images`.
Expand Down Expand Up @@ -625,33 +632,7 @@ def resolve_modules(self, paths: List[str]):
]
self.emu.exec_init_array(init_array)

# Initialize system modules
if name == "libsystem_kernel.dylib":
self._init_lib_system_kernel()
elif name == "libsystem_c.dylib":
self._init_lib_system_c()
elif name == "libdyld.dylib":
self._init_lib_dyld()
elif name == "libsystem_pthread.dylib":
self._init_lib_system_pthread()
elif name == "libsystem_trace.dylib":
self._init_lib_system_trace()
elif name == "libobjc.A.dylib":
self._init_lib_objc()

# Initialize Objective-C
self.init_objc(module)

if name == "libxpc.dylib":
self._init_lib_xpc()
elif name == "CoreFoundation":
self._init_core_foundation()
elif name == "Foundation":
self._init_foundation()

def _setup_symbolic_links(self):
for src, dst in SYMBOLIC_LINKS.items():
self.set_symbolic_link(src, dst)
self._init_system_module(name, module)

def _setup_bundle_dir(self):
"""Set bundle directory as current working directory."""
Expand Down Expand Up @@ -879,19 +860,6 @@ def mach_port_construct(self) -> int:
def mach_port_destruct(self, mach_port: int):
self._mach_port_manager.free(mach_port)

def _setup_mach_service(self):
services = {
"com.apple.system.notification_center": self.MACH_PORT_NOTIFICATION_CENTER,
"com.apple.CARenderServer": self.MACH_PORT_CA_RENDER_SERVER,
"com.apple.lsd.advertisingidentifiers": (
self.MACH_PORT_ADVERTISING_IDENTIFIERS
),
"com.apple.backboard.hid.services": self.MACH_PORT_BKS_HID_SERVER,
"com.apple.SystemConfiguration.configd": self.MACH_PORT_CONFIGD,
}

self._mach_services.update(services)

def bootstrap_look_up(self, name: str) -> int:
"""Find registered mach service.

Expand Down Expand Up @@ -926,20 +894,34 @@ def mach_msg(

def xpc_connection_send_message(self, connection: int, message: int) -> int:
"""Respond to `xpc_connection_send_message_with_reply_sync`."""
return self._xpc_message_handler.handle_connection_message(connection, message)
return self._xpc_message_handler.handle_connection_message(
connection,
message,
)

def initialize(self):
self._setup_hooks()
self._setup_syscall_handlers()
# Setup hooks
self.emu.hooks.update(get_hooks())

# Setup syscall handles
self.emu.syscall_handlers.update(get_syscall_handlers())
self.emu.syscall_names.update(get_syscall_names())

self._setup_tls()
self._setup_devices()

self._setup_mmio()
# Mount virtual device files
self.mount_devices(DEVICES_FILES)

self._setup_system_registers()

# Setup symbolic links
for src, dst in SYMBOLIC_LINKS.items():
self.set_symbolic_link(src, dst)

self._setup_symbolic_links()
self._setup_bundle_dir()

self._setup_mach_service()
# Setup mach services
self._mach_services.update(self.MACH_SERVICES)

# Setup system modules
self.resolve_modules(SYSTEM_MODULES)
Expand Down
10 changes: 10 additions & 0 deletions src/chomper/os/ios/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,13 @@ class DlInfo(ctypes.Structure):
("dli_sname", ctypes.c_uint64),
("dli_saddr", ctypes.c_uint64),
]


class Utsname(ctypes.Structure):
_fields_ = [
("sysname", ctypes.c_char * 256),
("nodename", ctypes.c_char * 256),
("release", ctypes.c_char * 256),
("version", ctypes.c_char * 256),
("machine", ctypes.c_char * 256),
]
5 changes: 5 additions & 0 deletions src/chomper/os/ios/syscall.py
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,11 @@ def handle_sys_bsdthread_create(emu: Chomper):
return 0


@register_syscall_handler(const.SYS_KQUEUE, "SYS_kqueue")
def handle_sys_kqueue(emu: Chomper):
return -1


@register_syscall_handler(const.SYS_LCHOWN, "SYS_lchown")
def handle_sys_lchown(emu: Chomper):
path = emu.read_string(emu.get_arg(0))
Expand Down
Loading