Finding the memory address of a Java local variable on the Dalvik Stack from native code

User

I am using JNI with Android Studio 1.5.1 targeting Android API 18 and my question is:

Q) Without using a tool or changing/modifying the Dalvik VM source code, how can I find the memory address of a Java local variable on the Dalvik Stack from native code?

For example, I try to use the following code (adapted from the Internet) to find the memory address of a Java local variable magicNumber = 0x23420023 but I am getting segmentation fault errors.

public class MainActivity extends AppCompatActivity {
static {
    System.loadLibrary("MyLibrary");
}

public native boolean findMagicNumber(int pid, int tid);
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    int magicNumber = 0x23420023 ;
    int pid = android.os.Process.myPid();
    int tid = android.os.Process.myTid();
    findMagicNumber(pid, tid);
}

}

#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "com_example_magicnumber2_MainActivity.h"
#include <unistd.h>
#include <memory.h>
#define ENOENT           2      /* No such file or directory */
#define ENOMEM          12      /* Out of memory */
#define EACCES          13      /* Permission denied */
#define EFAULT          14      /* Bad address */
#define EINVAL          22      /* Invalid argument */

jboolean validAddress(char* address)
{
    if ((access(address, F_OK)==-1) && !(errno == ENOENT) && !(errno == ENAMETOOLONG))
        return JNI_FALSE;
    else if ((access(address, F_OK)==-1) && (errno == ENOMEM) ||
             (access(address, F_OK)==-1) && (errno == EACCES) ||
             (access(address, F_OK)==-1) && (errno == EFAULT) ||
             (access(address, F_OK)==-1) && (errno == EINVAL))
        return JNI_FALSE;

    else if (address == NULL)
        return JNI_FALSE;
    else
        return JNI_TRUE;
}
JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {

    long long startaddr, endaddr, size, offset, inode;
    char permissions[8], device[8], filename[200], line[250];
    char *start, *end, *candidate;
    int result, i = 0;
    char filepath[100];
    sprintf(filepath,"/proc/%d/task/%d", pid, tid);

    FILE* file = fopen(filepath, "r");
    jboolean found = JNI_FALSE;
    while (fgets(line, sizeof(line), file) && !found) {
        sscanf(line,"%llx-%llx %s %llx %s %llx", &startaddr, &endaddr, permissions, &offset, device, &inode);
        start = startaddr;
        end = endaddr;
        mprotect( (void*)start , (end-start), PROT_READ);
        candidate = memchr( start, 0x14, (end-start));
        while( validAddress(candidate) && !found){
            if ((validAddress(candidate[2]) && (candidate[2]== 0x23)) &&
                (validAddress(candidate[3]) && (candidate[3] == 0x00)) &&
                (validAddress(candidate[4]) && (candidate[4] == 0x42)) &&
                (validAddress(candidate[5]) && (candidate[5] == 0x23))){
                __android_log_print(ANDROID_LOG_DEBUG,"***","Location=%p WE FOUND IT!", candidate);
                found = JNI_TRUE;
                break;
                return JNI_TRUE;
            }
            else if ((validAddress(candidate)) &&
                     validAddress(candidate=memchr(candidate+1, 0x14, (end-candidate)))){;
            }
        }
    }
}

This is an update:

The previous code that I posted was not the latest one, here is the latest one:

The Java Code:

public class MainActivity extends AppCompatActivity {
   static {
       System.loadLibrary("MyLibrary");
   }

   public native boolean findMagicNumber(int pid, int tid);
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       int magicNumber = 0x23420023 ;
       int pid = android.os.Process.myPid();
       int tid = android.os.Process.myTid();
       findMagicNumber(pid, tid);
       System.out.println("magicNumber = " + magicNumber );
   }
}

The native Code:

JNIEXPORT jboolean JNICALL Java_com_example_magicnumber2_MainActivity_findMagicNumber(JNIEnv *env, jobject obj, jint pid, jint tid) {

   long long startaddr, endaddr, size, offset, inode;
   char permissions[8], device[8], filename[200], line[250];
   char *start, *end, *candidate;
   int result, i = 0;
   char filepath[100];
   sprintf(filepath,"/proc/%d/task/%d/maps", pid, tid);
   FILE* file = fopen(filepath, "r");
   jboolean found = JNI_FALSE;

   while (fgets(line, sizeof(line), file) && !found) {
       sscanf(line,"%llx-%llx %s %llx %s %llx %s", &startaddr, &endaddr, permissions, &offset, device, &inode, filename);

       if (((strstr(filename, "[email protected]")))==NULL) {
       continue;
       }
       __android_log_print(ANDROID_LOG_DEBUG, "*****************", "%llx-%llx %s %llx %s %llx %s",
                           startaddr, endaddr, permissions, offset, device, inode, filename);
       start = startaddr;
       end = endaddr;
       candidate = memchr( start, 0x14, (end-start));
       while( candidate !=0 && !found){
           if ((candidate[2]== 0x23) &&
               (candidate[3] == 0x00) &&
               (candidate[4] == 0x42) &&
               (candidate[5] == 0x23)){
               __android_log_print(ANDROID_LOG_DEBUG,"********************************************************************","WE FOUND IT at %p!!!", candidate);
               found = JNI_TRUE;
               break;
           }
           else
               candidate=memchr(candidate+1, 0x14, (end-candidate));
       }
   }
}

This code is working and it can find the magic number but it finds it in the memory region mapped to /data/dalvik-cache/data@[email protected]@classes.dex which is not the Dalvik stack.

However, by running the above code and by looking at these two papers : paper1 (appendix B, only the egg-hunting code, I do not need to change any Dalvik code, so skip the code changing part) and paper2, we can notice the following (also to comments on fadden's remarks below):

(1) It seems that the int value magicNumber is stored in one Dalvik register. Also it seems that it is stored in the Dalvik stack and it is not on the native code stack because the int variable magicNumber is declared and assigned a value in the Java code section.

(2) According to the paper1, this answer and as evidence by running the attached latest code, we are not searching for 0x14 using the memchr function but we want to make sure we are at the beginning of a memory cell that store the int in ARM CPUs.

(3) I do not need to call the findMagicNumber function again. I just need to find the memory address of the magic number in the Dalvik stack

(4) I do not need to find nearby variables to the MagicNumber, so this is not a problem in my case.

(5) The project is targeting only Dalvik, so ART is not a problem

(6) I agree, using mprotect() is not a good idea and was not necessary in my case.

(7) If you refer to paper2, you can see that access() can be used for something that it is not designed for, checking if a virtual memory address is valid or not. I’m not using access() for any file related operations, although it was written for that purpose

(8) I do not need to change the variable. I just need the address of the variable magicNumber on the Dalvik stack programmatically without using any tool or changing the Dalvik source code

I want to know which of the memory regions of /proc/pid/task/tid/maps Dalvik uses to store its stack.

As you can see in paper1, the authors in section B.2, line #4, did not explain which memory region from procs/maps they used to assign the start and end variables their values.

fadden

It looks like you're trying to open /proc/[pid]/task/[tid]/maps, walk through the map, and manually scan through every address range for a magic number. Setting aside the fact that you're opening the task directory rather than the maps magic file in that directory, this approach has a few problems:

  1. You're not guaranteed that the value is unique. If it appears somewhere else in memory -- perhaps because the value was stored in two different Dalvik registers -- you'll be in the wrong place. If the JIT compiler has compiled this stretch of code, you don't know if the "active" value will be on the managed stack or in a spilled register on the native stack.
  2. You're searching for 0x14, which isn't part of your magic number.
  3. You're scanning for the local variable on the thread that created it. Even if you find it and can change it, once the findMagicNumber method returns, the stack-allocated variable will disappear. It's not guaranteed to be in the same place if the method is called again.
  4. If you were hoping to find related variables nearby, you will again have trouble if the JIT compiler rearranges things.
  5. ART compiles almost everything ahead of time, so this is even less likely to be useful there.

I'm also not sure why you're calling mprotect(), rather than simply skipping the segments that aren't readable. You're forcing the permissions to read-only, disabling write and execute permission, which will cause you to crash when execute permission is disabled for the chunk of code that's executing, or when a thread tries to execute and touches its stack.

The access() system call takes a filename, not a memory address, and reports file permissions. I don't think there's an "is this address valid" call, but since you just sscanf'ed the map entry you shouldn't need one.

The only reliable way to find and change the value of a local variable is to use the JDWP debug interface. The compiler and debugger support work together to make reliable read-write access to local variables possible.

To sum up: the code is seriously broken, the approach is unsound. What problem are you trying to solve?

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Work around error 'Address of stack memory associated with local variable returned'

From Dev

C - Avoiding warning "address of stack memory associated with local variable returned"

From Dev

Using C-string gives Warning: "Address of stack memory associated with local variable returned"

From Dev

Does Android Runtime(ART or Dalvik) contain Java VM stack or Native Method Stack like JVM?

From Dev

Finding the address of a variable from another process

From Dev

Java memory model and local variable

From Dev

Memory address of local variable changes depending on the presense of lambda parameters

From Dev

semantic of local final variable in the Java Memory Model?

From Dev

generate random stack memory address

From Dev

Embed and execute native code from memory

From Dev

Finding address of variable in shared library

From Dev

storage of address of variable in memory

From Dev

Java Code for finding grade from marks is incorrect

From Java

Is the address of a local variable a constexpr?

From Dev

Finding new memory address? C++

From Dev

How to resolve a Bad global or local ref passed to JNI error when calling a java method from native code

From Dev

Watch a variable (memory address) change in Linux kernel, and print stack trace when it changes?

From Dev

Where do these java native memory allocated from?

From Dev

Can native code cause memory corruption in Java code in Android?

From Dev

Tracing a memory address in Java

From Dev

Why more memory is assigned to a local variable in stack than required in C++?

From Dev

Why more memory is assigned to a local variable in stack than required in C++?

From Dev

Address ordering in static, stack and heap memory allocation?

From Dev

Memory address for arrays allocated on heap and on stack

From Java

Printing a variable memory address in swift

From Dev

Different memory address of same variable

From Dev

Local variable position on stack not changing

From Dev

when the memory is cleared on stack for a local function?

From Dev

when the memory is cleared on stack for a local function?

Related Related

  1. 1

    Work around error 'Address of stack memory associated with local variable returned'

  2. 2

    C - Avoiding warning "address of stack memory associated with local variable returned"

  3. 3

    Using C-string gives Warning: "Address of stack memory associated with local variable returned"

  4. 4

    Does Android Runtime(ART or Dalvik) contain Java VM stack or Native Method Stack like JVM?

  5. 5

    Finding the address of a variable from another process

  6. 6

    Java memory model and local variable

  7. 7

    Memory address of local variable changes depending on the presense of lambda parameters

  8. 8

    semantic of local final variable in the Java Memory Model?

  9. 9

    generate random stack memory address

  10. 10

    Embed and execute native code from memory

  11. 11

    Finding address of variable in shared library

  12. 12

    storage of address of variable in memory

  13. 13

    Java Code for finding grade from marks is incorrect

  14. 14

    Is the address of a local variable a constexpr?

  15. 15

    Finding new memory address? C++

  16. 16

    How to resolve a Bad global or local ref passed to JNI error when calling a java method from native code

  17. 17

    Watch a variable (memory address) change in Linux kernel, and print stack trace when it changes?

  18. 18

    Where do these java native memory allocated from?

  19. 19

    Can native code cause memory corruption in Java code in Android?

  20. 20

    Tracing a memory address in Java

  21. 21

    Why more memory is assigned to a local variable in stack than required in C++?

  22. 22

    Why more memory is assigned to a local variable in stack than required in C++?

  23. 23

    Address ordering in static, stack and heap memory allocation?

  24. 24

    Memory address for arrays allocated on heap and on stack

  25. 25

    Printing a variable memory address in swift

  26. 26

    Different memory address of same variable

  27. 27

    Local variable position on stack not changing

  28. 28

    when the memory is cleared on stack for a local function?

  29. 29

    when the memory is cleared on stack for a local function?

HotTag

Archive