Skip to content

Commit

Permalink
Setup stack properly for calls, fixes AeonLucid#29.
Browse files Browse the repository at this point in the history
  • Loading branch information
AeonLucid committed Feb 11, 2020
1 parent fbcb950 commit b8ed68d
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 18 deletions.
2 changes: 1 addition & 1 deletion androidemu/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def call_symbol(self, module, symbol_name, *argv):
logger.error('Unable to find symbol \'%s\' in module \'%s\'.' % (symbol_name, module.filename))
return

self.call_native(symbol.address, *argv)
return self.call_native(symbol.address, *argv)

def call_native(self, addr, *argv):
# Detect JNI call
Expand Down
8 changes: 5 additions & 3 deletions androidemu/java/helpers/native_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ def native_write_args(emu, *argv):
if amount >= 5:
sp_start = emu.mu.reg_read(UC_ARM_REG_SP)
sp_current = sp_start - STACK_OFFSET # Need to offset because our hook pushes one register on the stack.
sp_current = sp_current - (4 * (amount - 4)) # Reserve space for arguments.
sp_end = sp_current

for arg in argv[4:]:
emu.mu.mem_write(sp_current - STACK_OFFSET, native_translate_arg(emu, arg).to_bytes(4, byteorder='little'))
sp_current = sp_current - 4
emu.mu.mem_write(sp_current, native_translate_arg(emu, arg).to_bytes(4, byteorder='little'))
sp_current = sp_current + 4

emu.mu.reg_write(UC_ARM_REG_SP, sp_current)
emu.mu.reg_write(UC_ARM_REG_SP, sp_end)


def native_read_args(mu, args_count):
Expand Down
1 change: 1 addition & 0 deletions androidemu/java/jni_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,7 @@ def get_string_utf_chars(self, mu, env, string, is_copy_ptr):

@native_method
def release_string_utf_chars(self, mu, env, string, utf_ptr):
logger.debug("JNIEnv->ReleaseStringUTFChars(%x, %x) was called" % (string, utf_ptr))
pass

@native_method
Expand Down
40 changes: 26 additions & 14 deletions tests/test_native.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import logging
import posixpath
import os
import sys
import unittest

from unicorn import UC_HOOK_MEM_UNMAPPED, UC_HOOK_CODE
from unicorn import *

from androidemu.emulator import Emulator
from samples import debug_utils
Expand All @@ -14,27 +14,39 @@
format="%(asctime)s %(levelname)7s %(name)34s | %(message)s"
)

dir_samples = posixpath.join(posixpath.dirname(__file__), "..", "samples")
dir_samples = os.path.join(os.path.dirname(__file__), "..", "samples")


class TestNative(unittest.TestCase):

def test_something(self):
def testOneArg(self):
# Initialize emulator
emulator = Emulator(
vfp_inst_set=True,
vfs_root=posixpath.join(dir_samples, "vfs")
vfs_root=os.path.join(dir_samples, "vfs")
)

emulator.load_library(posixpath.join(dir_samples, "example_binaries", "libdl.so"), do_init=False)
emulator.load_library(posixpath.join(dir_samples, "example_binaries", "libc.so"), do_init=False)
emulator.load_library(posixpath.join(dir_samples, "example_binaries", "libstdc++.so"), do_init=False)
module = emulator.load_library(posixpath.join(posixpath.dirname(__file__), "test_binaries", "test_native.so"), do_init=False)
emulator.load_library(os.path.join(dir_samples, "example_binaries", "libdl.so"))
emulator.load_library(os.path.join(dir_samples, "example_binaries", "libc.so"))
emulator.load_library(os.path.join(dir_samples, "example_binaries", "libstdc++.so"))
module = emulator.load_library(os.path.join(os.path.dirname(__file__), "test_binaries", "test_native.so"))

print(module.base)
res = emulator.call_symbol(module, 'Java_com_aeonlucid_nativetesting_MainActivity_testOneArg', emulator.java_vm.jni_env.address_ptr, 0x00, 'Hello')

emulator.mu.hook_add(UC_HOOK_CODE, debug_utils.hook_code)
emulator.mu.hook_add(UC_HOOK_MEM_UNMAPPED, debug_utils.hook_unmapped)
res = emulator.call_symbol(module, 'Java_com_aeonlucid_nativetesting_MainActivity_testOneArg', emulator.java_vm.address_ptr, 0x00, 'Hello', 'asd')
self.assertEqual('Hello', res)

print(res)
def testSixArg(self):
# Initialize emulator
emulator = Emulator(
vfp_inst_set=True,
vfs_root=os.path.join(dir_samples, "vfs")
)

emulator.load_library(os.path.join(dir_samples, "example_binaries", "libdl.so"))
emulator.load_library(os.path.join(dir_samples, "example_binaries", "libc.so"))
emulator.load_library(os.path.join(dir_samples, "example_binaries", "libstdc++.so"))
module = emulator.load_library(os.path.join(os.path.dirname(__file__), "test_binaries", "test_native.so"))

res = emulator.call_symbol(module, 'Java_com_aeonlucid_nativetesting_MainActivity_testSixArg', emulator.java_vm.jni_env.address_ptr, 0x00, 'One', 'Two', 'Three', 'Four', 'Five', 'Six')

self.assertEqual('OneTwoThreeFourFiveSix', res)

0 comments on commit b8ed68d

Please sign in to comment.