一个很好的、通俗易懂的安卓VMP原理介绍
参见:https://www.cnblogs.com/theseventhson/p/14933920.html
VMP中的解释器的完整代码:
#include <jni.h>
#include <string>
// Raw code_item.
struct CodeItem {
uint16_t registers_size_; // the number of registers used by this code
// (locals + parameters)
uint16_t ins_size_; // the number of words of incoming arguments to the method
// that this code is for
uint16_t outs_size_; // the number of words of outgoing argument space required
// by this code for method invocation
uint16_t tries_size_; // the number of try_items for this instance. If non-zero,
// then these appear as the tries array just after the
// insns in this instance.
uint32_t debug_info_off_; // file offset to debug info stream
uint32_t insns_size_in_code_units_; // size of the insns array, in 2 byte code units
uint16_t insns_[1]; // actual array of bytecode.
};
/*123cdc: 92000606 |0000: mul-int v0, v6, v6
123ce0: 92010607 |0002: mul-int v1, v6, v7
123ce4: 91020607 |0004: sub-int v2, v6, v7
123ce8: 93030607 |0006: div-int v3, v6, v7
123cec: 90040001 |0008: add-int v4, v0, v1
123cf0: b024 |000a: add-int/2addr v4, v2
123cf2: b034 |000b: add-int/2addr v4, v3
123cf4: 0f04 |000c: return v4*/
//90 20
//91 21
//92 22
//93 23
const unsigned char Compute[] = {0x08, 0x00,
0x03, 0x00,
0x00, 0x00,
0x00, 0x00,
0x6e, 0x77, 0x14,0x00,
0x0d, 0x00, 0x00, 0x00,
0x22, 0x00, 0x06, 0x06,
0x22, 0x01,0x06, 0x07,
0x21, 0x02, 0x06, 0x07,
0x23, 0x03, 0x06, 0x07,
0x20,0x04, 0x00, 0x01,
0xb0, 0x24,
0xb0, 0x34,
0x0f, 0x04};
/*const unsigned char Compute[] = { 0x08, 0x00, //寄存器使用的个数
0x03, 0x00, //参数个数
0x00, 0x00, //调用其他方法时使用寄存器的个数
0x00, 0x00, //try catch个数
0x6e, 0x77, 0x14,0x00, //指令调试信息偏移
0x0d, 0x00, 0x00, 0x00, //指令集个数,以2字节为单位;这里是d,那么指令总长度是13*2=26个字节,可以用这个确认函数结尾
0x92, 0x00, 0x06, 0x06, //指令开始了
0x92, 0x01, 0x06, 0x07,
0x91, 0x02, 0x06, 0x07,
0x93, 0x03, 0x06, 0x07,
0x90, 0x04, 0x00, 0x01,
0xb0, 0x24,
0xb0, 0x34,
0x0f, 0x04};
*/
extern "C" JNIEXPORT jstring JNICALL
Java_com_kanxue_vmpprotect_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
int myinterpreter(JNIEnv *env, jobject obj, jint a, jint b) {
/* .prologue
.insnsSize 13 (16-bit)
.registers 8 [ v0 v1 v2 v3 v4 v5 v6 v7 ]*/
CodeItem *codeItem = (CodeItem *) Compute;
int registersize = codeItem->registers_size_;
int result = 0;
int *VREG = reinterpret_cast<int *>(malloc(sizeof(int) * registersize));//分配一块连续的内存模拟寄存器,这里也可以用数组实现
if (VREG != nullptr) {
memset(VREG, 0, registersize * sizeof(int));
int insNum = codeItem->ins_size_;//参数的个数
int startIndex = registersize - insNum;//总的寄存器数量减去参数个数,剩下的才是解释器能自由使用的寄存器个数
VREG[startIndex] = 0;
VREG[++startIndex] = a;
VREG[++startIndex] = b;
int pc = 0;
unsigned long address = (unsigned long) Compute;
unsigned char *opOffset = reinterpret_cast<unsigned char *>(address + 16);//指令集的地址
while (true) {
unsigned char op = *opOffset;
switch (op) {
/*case 0x90: {//90040001 |0008: add-int v4, v0, v1
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] + VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x91: {//91020607 |0004: sub-int v2, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] - VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x92: {//92010607 |0002: mul-int v1, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] * VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x93: {//93030607 |0006: div-int v3, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] / VREG[arg1];
opOffset = opOffset + 4;
break;
}*/
case 0x20: {//90040001 |0008: add-int v4, v0, v1
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] + VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x21: {//91020607 |0004: sub-int v2, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] - VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x22: {//92010607 |0002: mul-int v1, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] * VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0x23: {//93030607 |0006: div-int v3, v6, v7
unsigned char des = *(opOffset + 1);
unsigned char arg0 = *(opOffset + 2);
unsigned char arg1 = *(opOffset + 3);
VREG[des] = VREG[arg0] / VREG[arg1];
opOffset = opOffset + 4;
break;
}
case 0xb0: {//b024 |000a: add-int/2addr v4, v2
unsigned char des = *(opOffset + 1);
int arg0 = des & 0x0F;
int arg1 = des >> 4;
VREG[arg0] = VREG[arg0] + VREG[arg1];
opOffset = opOffset + 2;
break;
}
case 0x0f: {//123cf4: 0f04 |000c: return v4*/
unsigned char des = *(opOffset + 1);
return VREG[des];
}
}
}
}
}
extern "C" JNIEXPORT jint JNICALL
Java_com_vmpprotect_Compute_compute(JNIEnv *env, jobject obj, jint a, jint b) {
int result = myinterpreter(env, obj, a, b);
return result;
}