Skip to content

Commit

Permalink
Add tests for Objective-C (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
sledgeh4w committed May 3, 2024
1 parent 10875d5 commit 0c1da15
Show file tree
Hide file tree
Showing 6 changed files with 395 additions and 289 deletions.
12 changes: 9 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from chomper import Chomper
from chomper.const import ARCH_ARM, ARCH_ARM64, OS_IOS
from chomper.objc import ObjC

base_path = os.path.abspath(os.path.dirname(__file__))

Expand All @@ -19,13 +20,13 @@


@pytest.fixture(scope="module")
def str_test():
def input_str():
yield "chomper"


@pytest.fixture(scope="module")
def bytes_test(str_test):
yield str_test.encode("utf-8")
def input_bytes(input_str):
yield input_str.encode("utf-8")


@pytest.fixture(scope="module")
Expand Down Expand Up @@ -89,3 +90,8 @@ def emu_ios():
os_type=OS_IOS,
rootfs_path=ios_rootfs_path,
)


@pytest.fixture(scope="module")
def objc(emu_ios):
yield ObjC(emu_ios)
139 changes: 75 additions & 64 deletions tests/test_emulator.py
Original file line number Diff line number Diff line change
@@ -1,97 +1,108 @@
import pytest


class TestEmulator:
@pytest.mark.usefixtures("libc_arm64")
def test_find_symbol(self, emu_arm64):
symbol_name = "malloc"
symbol = emu_arm64.find_symbol(symbol_name)
@pytest.mark.usefixtures("libc_arm64")
def test_find_symbol(emu_arm64):
symbol_name = "malloc"
symbol = emu_arm64.find_symbol(symbol_name)

assert symbol.name == symbol_name
assert symbol.name == symbol_name

def test_backtrace(self, emu_arm64, libtiny_v73021_arm64):
def hook_code(uc, address, size, user_data):
trace_stack = emu_arm64.backtrace()
assert len(trace_stack) != 0

emu_arm64.add_hook(libtiny_v73021_arm64.base + 0x2BA08, hook_code)
def test_backtrace(emu_arm64, libtiny_v73021_arm64):
def hook_code(uc, address, size, user_data):
trace_stack = emu_arm64.backtrace()
assert len(trace_stack) != 0

a1 = emu_arm64.create_buffer(32)
a2 = emu_arm64.create_buffer(32)
a3 = emu_arm64.create_buffer(32)
emu_arm64.add_hook(libtiny_v73021_arm64.base + 0x2BA08, hook_code)

emu_arm64.call_address(libtiny_v73021_arm64.base + 0x289A4, a1, a2, a3)
a1 = emu_arm64.create_buffer(32)
a2 = emu_arm64.create_buffer(32)
a3 = emu_arm64.create_buffer(32)

@pytest.mark.usefixtures("libz_arm64")
def test_set_and_get_arg(self, emu_arm64):
args = [i for i in range(16)]
emu_arm64.call_address(libtiny_v73021_arm64.base + 0x289A4, a1, a2, a3)

for index, arg in enumerate(args):
emu_arm64.set_arg(index, arg)

for index, arg in enumerate(args):
assert emu_arm64.get_arg(index) == arg
@pytest.mark.usefixtures("libz_arm64")
def test_set_and_get_arg(emu_arm64):
args = [i for i in range(16)]

@pytest.mark.usefixtures("libz_arm64")
def test_set_and_get_retval(self, emu_arm64):
retval = 105
for index, arg in enumerate(args):
emu_arm64.set_arg(index, arg)

emu_arm64.set_retval(retval)
result = emu_arm64.get_retval()
for index, arg in enumerate(args):
assert emu_arm64.get_arg(index) == arg

assert result == retval

def test_create_buffer(self, emu_arm64):
result = emu_arm64.create_buffer(1024)
@pytest.mark.usefixtures("libz_arm64")
def test_set_and_get_retval(emu_arm64):
retval = 105

assert result is not None
emu_arm64.set_retval(retval)
result = emu_arm64.get_retval()

def test_create_string(self, emu_arm64, str_test):
result = emu_arm64.create_string(str_test)
assert result == retval

assert result is not None

def test_free(self, emu_arm64):
addr = emu_arm64.create_buffer(1024)
emu_arm64.free(addr)
def test_create_buffer(emu_arm64):
result = emu_arm64.create_buffer(1024)

def test_read_and_write_int(self, emu_arm64):
addr = emu_arm64.create_buffer(1024)
value = 105
assert result is not None

emu_arm64.write_int(addr, value, size=4)
result = emu_arm64.read_int(addr, size=4)

assert result == value
def test_create_string(emu_arm64, input_str):
result = emu_arm64.create_string(input_str)

def test_read_and_write_bytes(self, emu_arm64, bytes_test):
addr = emu_arm64.create_buffer(1024)
assert result is not None

emu_arm64.write_bytes(addr, bytes_test)
result = emu_arm64.read_bytes(addr, len(bytes_test))

assert result == bytes_test
def test_free(emu_arm64):
addr = emu_arm64.create_buffer(1024)
emu_arm64.free(addr)

def test_read_and_write_string(self, emu_arm64, str_test):
addr = emu_arm64.create_buffer(1024)

emu_arm64.write_string(addr, str_test)
result = emu_arm64.read_string(addr)
def test_read_and_write_int(emu_arm64):
addr = emu_arm64.create_buffer(1024)
value = 105

assert result == str_test
emu_arm64.write_int(addr, value, size=4)
result = emu_arm64.read_int(addr, size=4)

@pytest.mark.usefixtures("libz_arm64")
def test_call_symbol(self, emu_arm64):
result = emu_arm64.call_symbol("zlibVersion")
assert result == value

assert emu_arm64.read_string(result) == "1.2.8"

@pytest.mark.usefixtures("libz_arm64")
def test_call_address(self, emu_arm64):
symbol = emu_arm64.find_symbol("zlibVersion")
result = emu_arm64.call_address(symbol.address)
def test_read_and_write_bytes(emu_arm64, input_bytes):
addr = emu_arm64.create_buffer(1024)

assert emu_arm64.read_string(result) == "1.2.8"
emu_arm64.write_bytes(addr, input_bytes)
result = emu_arm64.read_bytes(addr, len(input_bytes))

def test_exec_init_array(self, emu_arm64, libszstone_v4945_arm64):
assert emu_arm64.read_string(libszstone_v4945_arm64.base + 0x49DD8) == "1.2.3"
assert result == input_bytes


def test_read_and_write_string(emu_arm64, input_str):
addr = emu_arm64.create_buffer(1024)

emu_arm64.write_string(addr, input_str)
result = emu_arm64.read_string(addr)

assert result == input_str


@pytest.mark.usefixtures("libz_arm64")
def test_call_symbol(emu_arm64):
result = emu_arm64.call_symbol("zlibVersion")

assert emu_arm64.read_string(result) == "1.2.8"


@pytest.mark.usefixtures("libz_arm64")
def test_call_address(emu_arm64):
symbol = emu_arm64.find_symbol("zlibVersion")
result = emu_arm64.call_address(symbol.address)

assert emu_arm64.read_string(result) == "1.2.8"


def test_exec_init_array(emu_arm64, libszstone_v4945_arm64):
assert emu_arm64.read_string(libszstone_v4945_arm64.base + 0x49DD8) == "1.2.3"
126 changes: 63 additions & 63 deletions tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,66 @@
import pytest


class TestExamples:
@pytest.mark.usefixtures("libc_arm", "libz_arm")
def test_libdusanwa_v4856_arm(self, emu_arm, libdusanwa_v4856_arm, bytes_test):
a1 = emu_arm.create_buffer(32)
a2 = 32
a3 = emu_arm.create_buffer(32)
a4 = emu_arm.create_buffer(32)

emu_arm.write_bytes(a1, bytes_test)
emu_arm.write_bytes(a4, bytes_test)

emu_arm.call_address((libdusanwa_v4856_arm.base + 0xA588) | 1, a1, a2, a3, a4)
result = emu_arm.read_bytes(a3, a2)

assert zlib.crc32(result) == 1148403178

@pytest.mark.usefixtures("libc_arm64", "libz_arm64")
def test_libszstone_v4945_arm64(
self, emu_arm64, libszstone_v4945_arm64, bytes_test
):
a1 = emu_arm64.create_buffer(len(bytes_test))
a2 = len(bytes_test)
a3 = emu_arm64.create_buffer(1024)

emu_arm64.write_bytes(a1, bytes_test)

result_size = emu_arm64.call_address(
libszstone_v4945_arm64.base + 0x2F1C8, a1, a2, a3
)
result = emu_arm64.read_bytes(a3, result_size)

assert zlib.crc32(result) == 3884391316

@pytest.mark.usefixtures("libc_arm64", "libz_arm64")
def test_libtiny_v73021_arm64(self, emu_arm64, libtiny_v73021_arm64, bytes_test):
a1 = emu_arm64.create_buffer(32)
a2 = emu_arm64.create_buffer(32)
a3 = emu_arm64.create_buffer(32)

emu_arm64.write_bytes(a1, bytes_test * 4)
emu_arm64.write_bytes(a2, bytes_test * 4)

emu_arm64.call_address(libtiny_v73021_arm64.base + 0x289A4, a1, a2, a3)
result = emu_arm64.read_bytes(a3, 32)

assert zlib.crc32(result) == 4192995551

# @staticmethod
# def test_duapp_v581(emu_ios, sample_str):
# duapp = emu_ios.load_module("DUApp")
#
# a1 = emu_ios.create_string("objc")
# a2 = emu_ios.create_string(sample_str)
# a3 = len(sample_str)
# a4 = emu_ios.create_string(str(uuid.uuid4()))
# a5 = emu_ios.create_buffer(8)
# a6 = emu_ios.create_buffer(8)
# a7 = emu_ios.create_string("com.siwuai.duapp")
#
# emu_ios.call_address(duapp.base + 0x109322118, a1, a2, a3, a4, a5, a6, a7)
# result = emu_ios.read_string(emu_ios.read_pointer(a5))
#
# assert re.match(r"\w{32}\.[\w=]+\.", result)
@pytest.mark.usefixtures("libc_arm", "libz_arm")
def test_libdusanwa_v4856_arm(emu_arm, libdusanwa_v4856_arm, input_bytes):
a1 = emu_arm.create_buffer(32)
a2 = 32
a3 = emu_arm.create_buffer(32)
a4 = emu_arm.create_buffer(32)

emu_arm.write_bytes(a1, input_bytes)
emu_arm.write_bytes(a4, input_bytes)

emu_arm.call_address((libdusanwa_v4856_arm.base + 0xA588) | 1, a1, a2, a3, a4)
result = emu_arm.read_bytes(a3, a2)

assert zlib.crc32(result) == 1148403178


@pytest.mark.usefixtures("libc_arm64", "libz_arm64")
def test_libszstone_v4945_arm64(emu_arm64, libszstone_v4945_arm64, input_bytes):
a1 = emu_arm64.create_buffer(len(input_bytes))
a2 = len(input_bytes)
a3 = emu_arm64.create_buffer(1024)

emu_arm64.write_bytes(a1, input_bytes)

result_size = emu_arm64.call_address(
libszstone_v4945_arm64.base + 0x2F1C8, a1, a2, a3
)
result = emu_arm64.read_bytes(a3, result_size)

assert zlib.crc32(result) == 3884391316


@pytest.mark.usefixtures("libc_arm64", "libz_arm64")
def test_libtiny_v73021_arm64(emu_arm64, libtiny_v73021_arm64, input_bytes):
a1 = emu_arm64.create_buffer(32)
a2 = emu_arm64.create_buffer(32)
a3 = emu_arm64.create_buffer(32)

emu_arm64.write_bytes(a1, input_bytes * 4)
emu_arm64.write_bytes(a2, input_bytes * 4)

emu_arm64.call_address(libtiny_v73021_arm64.base + 0x289A4, a1, a2, a3)
result = emu_arm64.read_bytes(a3, 32)

assert zlib.crc32(result) == 4192995551


# @staticmethod
# def test_duapp_v581(emu_ios, sample_str):
# duapp = emu_ios.load_module("DUApp")
#
# a1 = emu_ios.create_string("objc")
# a2 = emu_ios.create_string(sample_str)
# a3 = len(sample_str)
# a4 = emu_ios.create_string(str(uuid.uuid4()))
# a5 = emu_ios.create_buffer(8)
# a6 = emu_ios.create_buffer(8)
# a7 = emu_ios.create_string("com.siwuai.duapp")
#
# emu_ios.call_address(duapp.base + 0x109322118, a1, a2, a3, a4, a5, a6, a7)
# result = emu_ios.read_string(emu_ios.read_pointer(a5))
#
# assert re.match(r"\w{32}\.[\w=]+\.", result)
36 changes: 18 additions & 18 deletions tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,26 @@
from chomper.exceptions import EmulatorCrashedException


class TestExceptions:
def test_unhandled_system_call_exception(self):
with pytest.raises(EmulatorCrashedException, match=r"Unhandled system call.*"):
emu = Chomper(arch=ARCH_ARM64)
emu.hooks.pop("malloc")
def test_unhandled_system_call_exception():
with pytest.raises(EmulatorCrashedException, match=r"Unhandled system call.*"):
emu = Chomper(arch=ARCH_ARM64)
emu.hooks.pop("malloc")

emu.load_module(os.path.join(conftest.android_lib64_path, "libc.so"))
emu.load_module(os.path.join(conftest.android_lib64_path, "libc.so"))

emu.call_symbol("malloc")
emu.call_symbol("malloc")

def test_missing_symbol_required_exception(self, bytes_test):
with pytest.raises(EmulatorCrashedException, match=r"Missing symbol.*"):
emu = Chomper(arch=ARCH_ARM64)
libszstone = emu.load_module(
os.path.join(conftest.com_shizhuang_duapp_path, "libszstone.so")
)

a1 = emu.create_buffer(len(bytes_test))
a2 = len(bytes_test)
a3 = emu.create_buffer(1024)
def test_missing_symbol_required_exception(input_bytes):
with pytest.raises(EmulatorCrashedException, match=r"Missing symbol.*"):
emu = Chomper(arch=ARCH_ARM64)
libszstone = emu.load_module(
os.path.join(conftest.com_shizhuang_duapp_path, "libszstone.so")
)

emu.write_bytes(a1, bytes_test)
emu.call_address(libszstone.base + 0x289A4, a1, a2, a3)
a1 = emu.create_buffer(len(input_bytes))
a2 = len(input_bytes)
a3 = emu.create_buffer(1024)

emu.write_bytes(a1, input_bytes)
emu.call_address(libszstone.base + 0x289A4, a1, a2, a3)
Loading

0 comments on commit 0c1da15

Please sign in to comment.