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

Execute libmacho.dylib directly instead of hooking #78

Merged
merged 1 commit into from
May 22, 2024
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
9 changes: 5 additions & 4 deletions src/chomper/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,12 @@ def add_symbol_hooks(self, symbols: List[Symbol], trace_symbol_calls: bool = Fal

# Hook symbol
if self.emu.hooks.get(symbol.name):
message = 'Hook export symbol "{}" at {}'.format(
symbol.name,
self.emu.debug_symbol(symbol.address),
self.emu.logger.info(
'Hook export symbol "{}" at {}'.format(
symbol.name,
self.emu.debug_symbol(symbol.address),
)
)
self.emu.logger.info(message)

self.emu.add_interceptor(symbol.address, self.emu.hooks[symbol.name])

Expand Down
1 change: 1 addition & 0 deletions src/chomper/os/ios/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
SYS_GETEGID = 0x2B
SYS_GETTIMEOFDAY = 0x74
SYS_CSOPS = 0xA9
SYS_RLIMIT = 0xC2
SYS_SYSCTL = 0xCA
SYS_SHM_OPEN = 0x10A
SYS_SYSCTLBYNAME = 0x112
Expand Down
50 changes: 16 additions & 34 deletions src/chomper/os/ios/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

from unicorn.unicorn import UC_HOOK_CODE_TYPE

from chomper.utils import pyobj2cfobj
from chomper.exceptions import SymbolMissingException
from chomper.objc import ObjC
from chomper.utils import pyobj2cfobj

hooks: Dict[str, UC_HOOK_CODE_TYPE] = {}

Expand Down Expand Up @@ -323,47 +324,28 @@ def hook_posix_memalign(uc, address, size, user_data):
return 0


@register_hook("_getsectiondata")
def hook_getsectiondata(uc, address, size, user_data):
emu = user_data["emu"]
module = emu.modules[-1]

section_name = emu.read_string(emu.get_arg(2))
size_ptr = emu.get_arg(3)

section = module.binary.get_section(section_name)
if not section:
return 0
@register_hook("__os_activity_initiate")
def hook_os_activity_initiate(uc, address, size, user_data):
return 0

emu.write_u64(size_ptr, section.size)

return module.base - module.image_base + section.virtual_address
@register_hook("_notify_register_dispatch")
def hook_notify_register_dispatch(uc, address, size, user_data):
return 0


@register_hook("_getsegmentdata")
def hook_getsegmentdata(uc, address, size, user_data):
@register_hook("_dlsym")
def hook_dlsym(uc, address, size, user_data):
emu = user_data["emu"]
module = emu.modules[-1]

segment_name = emu.read_string(emu.get_arg(1))
size_ptr = emu.get_arg(2)
symbol_name = f"_{emu.read_string(emu.get_arg(1))}"

segment = module.binary.get_segment(segment_name)
if not segment:
return 0

emu.write_u64(size_ptr, segment.virtual_size)

return module.base - module.image_base + segment.virtual_address
try:
symbol = emu.find_symbol(symbol_name)
return symbol.address
except SymbolMissingException:
pass


@register_hook("__os_activity_initiate")
def hook_os_activity_initiate(uc, address, size, user_data):
return 0


@register_hook("_notify_register_dispatch")
def hook_notify_register_dispatch(uc, address, size, user_data):
return 0


Expand Down
1 change: 0 additions & 1 deletion src/chomper/os/ios/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ def _get_init_array(self, binary: lief.MachO.Binary, module_base: int):

begin = module_base + section.virtual_address
end = begin + section.size

values = self.emu.read_array(begin, end)

return [addr for addr in values if addr]
Expand Down
29 changes: 9 additions & 20 deletions src/chomper/os/ios/os.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import os
from ctypes import sizeof
from typing import List

from chomper.base import BaseOs
from chomper.types import Module
from chomper.utils import struct2bytes
from chomper.os.ios import const
from chomper.os.ios.fixup import SystemModuleFixup
from chomper.os.ios.hooks import get_hooks
from chomper.os.ios.loader import MachoLoader
from chomper.os.ios.structs import MachHeader64
from chomper.os.ios.syscall import get_syscall_handlers


Expand Down Expand Up @@ -144,7 +141,10 @@ def init_objc(self, module: Module):

Calling `map_images` and `load_images` of `libobjc.A.dylib`.
"""
if not self.emu.find_module("libobjc.A.dylib") or not module.binary:
if not module.binary or not module.image_base:
return

if not self.emu.find_module("libobjc.A.dylib"):
return

initialized = self.emu.find_symbol("__ZZ10_objc_initE11initialized")
Expand All @@ -155,31 +155,19 @@ def init_objc(self, module: Module):
self._init_dyld_vars()
self._init_objc_vars()

mach_header = MachHeader64(
magic=module.binary.header.magic.value,
cputype=module.binary.header.cpu_type.value,
cpusubtype=module.binary.header.cpu_subtype,
filetype=module.binary.header.file_type.value,
ncmds=module.binary.header.nb_cmds,
sizeofcmds=module.binary.header.sizeof_cmds,
flags=module.binary.header.flags,
reserved=module.binary.header.reserved,
)

mach_header_ptr = self.emu.create_buffer(sizeof(MachHeader64))
self.emu.write_bytes(mach_header_ptr, struct2bytes(mach_header))
text_segment = module.binary.get_segment("__TEXT")

mach_header_ptr = module.base - module.image_base + text_segment.virtual_address
mach_header_ptrs = self.emu.create_buffer(self.emu.arch.addr_size)

self.emu.write_pointer(mach_header_ptrs, mach_header_ptr)

try:
self.emu.call_symbol("_map_images", 1, 0, mach_header_ptrs)
self.emu.call_symbol("_load_images")

self.emu.call_symbol("_load_images", 0, mach_header_ptr)
except Exception as e:
self.emu.logger.error("Initialize Objective-C failed.")
self.emu.logger.exception(e)

finally:
module.binary = None

Expand Down Expand Up @@ -243,6 +231,7 @@ def _enable_objc(self):
"libcommonCrypto.dylib",
"libc++abi.dylib",
"libc++.1.dylib",
"libmacho.dylib",
"libdyld.dylib",
"libobjc.A.dylib",
"libdispatch.dylib",
Expand Down
16 changes: 12 additions & 4 deletions src/chomper/os/ios/syscall.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ def handle_sys_csops(emu):
return 0


@register_syscall_handler(const.SYS_RLIMIT)
def handle_sys_rlimit(emu):
return 0


@register_syscall_handler(const.SYS_SYSCTL)
def handle_sys_sysctl(emu):
return 0
Expand Down Expand Up @@ -139,12 +144,15 @@ def handle_sys_issetugid(emu):

@register_syscall_handler(const.SYS_PROC_INFO)
def handle_sys_proc_info(emu):
# pid = emu.get_arg(1)
flavor = emu.get_arg(2)
buffer = emu.get_arg(4)

process_path = (
"/private/var/containers/Bundle/Application/%s/App.app" % uuid.uuid4()
)
emu.write_string(buffer, process_path)
if flavor == 11:
emu.write_string(
buffer,
"/private/var/containers/Bundle/Application/%s/App.app" % uuid.uuid4(),
)

clear_carry_flag(emu)

Expand Down
Loading