Although there are similar questions (such as 1, 2, 3), their answers do not solve my problem.
I’m using Android NDK with Android Studio 1.5.1 targeting Android API 18 (before Android KitKat 4.4, so I’m dealing with Dalvik, not ART runtime).
I know that a primitive Java local variable should be on the Dalvik interpreter stack but I could not find it.
I used the following code to declare a Java local integer magic number (0x23420023) in the Java code and search for it using a native code (C code).
I pass the process id (pid) and the thread id (tid) of the Java code to the C code, so I can search the virtual address space occupied by Java method that declared that magic number variable.
In the C code, I get the memory regions for the Java code by reading and parsing the file /proc/pid/task/tid/maps
What is the problem?
When I scan the memory region (extracted from the file /proc/pid/task/tid/maps):
ad5b1000-ad7d7000 r--p 00000000 1f:01 756 /data/dalvik- cache/data@app@com.example.magicnumber2-1.apk@classes.dex
I can find the magic number immediately but the problem is that memory region is occupied by the app object file and not the Dalvik stack. You can confirm that by un-commenting the first if-statement labeled “//1-dex:” and commenting out the second and third if-statments labeled “//2-permission:” and “//3-inode” between the two while-loops in the C code.
However, when I search the other remaining memory regions (extracted from the file /proc/pid/task/tid/maps) that have read, write, and private permissions “rw-p” (because the Dalvik stack should have a read/write/private permissions), I get a segmentation fault error. You can confirm that by commenting out the first if-statement labeled “//1-dex:” and un-commenting the second and third if-statments labeled “//2-permission:” and “//3-inode” between the two while-loops in the C code.
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 + " PID=" + pid + " TID=" + tid);
}
}
The C code:
#include "com_example_magicnumber2_MainActivity.h"
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <string.h>
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;
char filepath[100];
//pid is the process id and tid is the thread id of the Java calling method from the Java code
sprintf(filepath,"/proc/%d/task/%d/maps", pid, tid);
FILE* file = fopen(filepath, "r");
while (fgets(line, sizeof(line), file)) {
memset( filename, '\0', sizeof(filename) );
sscanf(line,"%llx-%llx %s %llx %s %llx %s", &startaddr, &endaddr, permissions, &offset, device, &inode, filename);
//1-dex: examine only the memory region mapped to the app dex file
if ((strstr(filename,".dex"))==NULL) continue;
//2-permission: examine only read, write, and private memory regions
//if (((strstr(permissions, "rw-p")))==NULL) continue;
//3-inode: examine only the memory region that is not mapped to a file or device
//if (inode !=0) 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){
if ((candidate[2]== 0x23) &&
(candidate[3] == 0x00) &&
(candidate[4] == 0x42) &&
(candidate[5] == 0x23)){
__android_log_print(ANDROID_LOG_DEBUG,"@@@@@@@@@@","The magic number is found at %p", candidate);
break;
}
else
candidate = memchr(candidate+1, 0x14, (end-candidate));
}
}
}