本文为看雪论坛优秀文章
看雪论坛作者ID:glider菜鸟
dalvik解释器解释指令前的准备工作
dalvik解释器的模型
invoke-super指令实例分析
解释器解释指令前的准备工作
解释器的模型
invoke-super指令实例分析
1. 取出函数的简单声明,如onCreate函数的简单声明为:VL
2. 分配虚拟寄存器栈
3. 放入this参数,根据参数类型放入申明中的参数
4. 如果方法是native方法,直接跳转到method->nativeFunc执行
5. 如果方法是java方法,进入dvmInterpret解释执行
void dvmCallMethodV(Thread* self, const Method* method, Object* obj, bool fromJni, JValue* pResult, va_list args)
{
const char* desc = &(method->shorty[1]);
int verifyCount = 0;
ClassObject* clazz;
u4* ins;
clazz = callPrep(self, method, obj, false);
if (clazz == NULL)
return;
ins = ((u4*)self->interpSave.curFrame) + (method->registersSize - method->insSize);
if (!dvmIsStaticMethod(method)) {
*ins++ = (u4) obj;
verifyCount++;
}
while (*desc != '\0') {
switch (*(desc++)) {
case 'D': case 'J': {
u8 val = va_arg(args, u8);
memcpy(ins, &val, 8);
ins += 2;
verifyCount += 2;
break;
}
case 'F': {
float f = (float) va_arg(args, double);
*ins++ = dvmFloatToU4(f);
verifyCount++;
break;
}
case 'L': {
void* arg = va_arg(args, void*);
assert(obj == NULL || dvmIsHeapAddress(obj));
jobject argObj = reinterpret_cast<jobject>(arg);
if (fromJni)
*ins++ = (u4) dvmDecodeIndirectRef(self, argObj);
else
*ins++ = (u4) argObj;
verifyCount++;
break;
}
default: {
*ins++ = va_arg(args, u4);
verifyCount++;
break;
}
}
}
if (dvmIsNativeMethod(method)) {
TRACE_METHOD_ENTER(self, method);
(*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
method, self);
TRACE_METHOD_EXIT(self, method);
} else {
dvmInterpret(self, method, pResult);
}
dvmPopFrame(self);
}
void dvmInterpret(Thread* self, const Method* method, JValue* pResult)
{
InterpSaveState interpSaveState;
ExecutionSubModes savedSubModes;
double calleeSave[JIT_CALLEE_SAVE_DOUBLE_COUNT];
interpSaveState = self->interpSave;
self->interpSave.prev = &interpSaveState;
savedSubModes = (ExecutionSubModes)(
self->interpBreak.ctl.subMode & LOCAL_SUBMODE);
if (savedSubModes != kSubModeNormal) {
dvmDisableSubMode(self, savedSubModes);
}
dvmJitCalleeSave(calleeSave);
self->interpSave.debugTrackedRefStart =
dvmReferenceTableEntries(&self->internalLocalRefTable);
self->debugIsMethodEntry = true;
self->jitState = kJitNot;
/初始化解释器的执行环境
self->interpSave.method = method;
self->interpSave.curFrame = (u4*) self->interpSave.curFrame;
self->interpSave.pc = method->insns;
assert(!dvmIsNativeMethod(method));
if (method->clazz->status < CLASS_INITIALIZING || method->clazz->status == CLASS_ERROR)
{
ALOGE("ERROR: tried to execute code in unprepared class '%s' (%d)",
method->clazz->descriptor, method->clazz->status);
dvmDumpThread(self, false);
dvmAbort();
}
typedef void (*Interpreter)(Thread*);
Interpreter stdInterp;
if (gDvm.executionMode == kExecutionModeInterpFast)
stdInterp = dvmMterpStd;
else if (gDvm.executionMode == kExecutionModeJit ||
gDvm.executionMode == kExecutionModeNcgO0 ||
gDvm.executionMode == kExecutionModeNcgO1)
stdInterp = dvmMterpStd;
else
stdInterp = dvmInterpretPortable;
(*stdInterp)(self);
*pResult = self->interpSave.retval;
self->interpSave = interpSaveState;
dvmJitCalleeRestore(calleeSave);
if (savedSubModes != kSubModeNormal) {
dvmEnableSubMode(self, savedSubModes);
}
}
while (*ins) {
switch (*ins) {
case NOP:
break;
case MOV:
break;
......
}
}
1. 初始化一些关于虚拟机执行环境的变量
2. 初始化分发表
3. FINISH(0)开始执行指令
void dvmInterpretPortable(Thread* self)
{
DvmDex* methodClassDex;
JValue retval;
const Method* curMethod;
const u2* pc;
u4* fp;
u2 inst;
u4 ref;
u2 vsrc1, vsrc2, vdst;
const Method* methodToCall;
bool methodCallRange;
DEFINE_GOTO_TABLE(handlerTable);
curMethod = self->interpSave.method;
pc = self->interpSave.pc;
fp = self->interpSave.curFrame;
retval = self->interpSave.retval;
methodClassDex = curMethod->clazz->pDvmDex;
if (self->interpBreak.ctl.subMode != 0) {
TRACE_METHOD_ENTER(self, curMethod);
self->debugIsMethodEntry = true;
}
methodToCall = (const Method*) -1;
FINISH(0);
HANDLE_OPCODE(OP_NOP)
FINISH(1);
OP_END
.....
do { \
methodCallRange = _methodCallRange; \
goto _target; \
} while(false)
HANDLE_OPCODE(OP_INVOKE_SUPER )
GOTO_invoke(invokeSuper, false);
OP_END
GOTO_TARGET(invokeSuper, bool methodCallRange)
{
Method* baseMethod;
u2 thisReg;
EXPORT_PC();
vsrc1 = INST_AA(inst);
ref = FETCH(1);
vdst = FETCH(2);
if (methodCallRange) {
ILOGV("|invoke-super-range args=%d @0x%04x {regs=v%d-v%d}",
vsrc1, ref, vdst, vdst+vsrc1-1);
thisReg = vdst;
} else {
ILOGV("|invoke-super args=%d @0x%04x {regs=0x%04x %x}",
vsrc1 >> 4, ref, vdst, vsrc1 & 0x0f);
thisReg = vdst & 0x0f;
}
if (!checkForNull((Object*) GET_REGISTER(thisReg)))
GOTO_exceptionThrown();
baseMethod = dvmDexGetResolvedMethod(methodClassDex, ref);
if (baseMethod == NULL) {
baseMethod = dvmResolveMethod(curMethod->clazz, ref,METHOD_VIRTUAL);
if (baseMethod == NULL) {
ILOGV("+ unknown method or access denied");
GOTO_exceptionThrown();
}
}
if (baseMethod->methodIndex >= curMethod->clazz->super->vtableCount) {
dvmThrowNoSuchMethodError(baseMethod->name);
GOTO_exceptionThrown();
}
methodToCall = curMethod->clazz->super->vtable[baseMethod->methodIndex];
if (dvmIsAbstractMethod(methodToCall)) {
dvmThrowAbstractMethodError("abstract method not implemented");
GOTO_exceptionThrown();
}
assert(!dvmIsAbstractMethod(methodToCall) ||
methodToCall->nativeFunc != NULL);
LOGVV("+++ base=%s.%s super-virtual=%s.%s",
baseMethod->clazz->descriptor, baseMethod->name,
methodToCall->clazz->descriptor, methodToCall->name);
assert(methodToCall != NULL);
GOTO_invokeMethod(methodCallRange, methodToCall, vsrc1, vdst);
}
GOTO_TARGET_END
GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall, u2 count, u2 regs)
{
if (!dvmIsNativeMethod(methodToCall)) {
curMethod = methodToCall;
self->interpSave.method = curMethod;
methodClassDex = curMethod->clazz->pDvmDex;
pc = methodToCall->insns;
fp = newFp;
self->interpSave.curFrame = fp;
debugSaveArea = SAVEAREA_FROM_FP(newFp);
self->debugIsMethodEntry = true;
ILOGD("> pc <-- %s.%s %s", curMethod->clazz->descriptor,
curMethod->name, curMethod->shorty);
DUMP_REGS(curMethod, fp, true);
FINISH(0);
}
struct GlobalInfo {
DexInfo *dex_info;
vector<MethodInfo*> method_list;
};
struct DexInfo {
void *dexBase;
int unknow[12];
void *dexHeader;
.....
optable[];
};
struct MethodInfo {
int dex_type_id;
int dex_class_def_id;
int unknow;
int codeoff;
};
struct StackInfo {
JNIEnv * jni_env;
int registerSize;
DexCode *dexCode;
int unkonw;
void *registerSpace;
void *registerSpace2;
int unkonw2;
char key;
char origin_key;
};
int __fastcall sub_D930(unsigned int a1, JNIEnv *a2, _DWORD *a3)
{
global_info = sub_66BD4(v109, &v114);
if ( v114 & 1 )
j_j_j__ZdlPv(*(v47 + 5));
if ( global_info && (v52 = *(global_info + 4), (*(global_info + 8) - v52) >> 2 > v4) )
{
v53 = v52 + 4 * v4;
a2c = v3;
method_info = *v53;
dexInfo = *global_info;
DexCode = (**global_info + *(*v53 + 12));
((*v3)->PushLocalFrame)();
stackinfo = malloc_1(0x20u);
v56 = *DexCode;
*stackinfo = a2c;
*(stackinfo + 4) = v56;
*(stackinfo + 8) = DexCode;
*(stackinfo + 12) = 0;
v57 = 4 * v56;
v58 = malloc_0(4 * v56);
*(stackinfo + 16) = v58;
memset(v58, v57, 0);
v59 = malloc_0(v57);
*(stackinfo + 20) = v59;
memset(v59, v57, 0);
*(stackinfo + 29) = 0;
*(stackinfo + 28) = 0;
v60 = sub_3E268();
v61 = DexCode;
*(stackinfo + 28) = *DexCode ^ *(v60 + 24) ^ *(method_info + 4) ^ *method_info;
*(stackinfo + 29) = *(v60 + 24);
}
int __fastcall sub_D930(unsigned int a1, JNIEnv *a2, _DWORD *a3)
{
//节选
v107 = stackinfo;
proto = (*dexInfo
+ *(*dexInfo
+ *(dexInfo[4] + 60)
+ 4 * *(*dexInfo + *(dexInfo[4] + 76) + 12 * *(*dexInfo + *(dexInfo[4] + 92) + 8 * *(method_info + 4) + 2))));
do
v63 = proto++; // 方法的简单声明: VL
while ( *v63 < 0 );
v64 = j_j_strlen(proto);
v99 = v64;
v65 = *v61 - v61[1]; // 函数内部使用寄存器个数:DexCode.registerSize - DexCode.insSize
v105 = v65 - 1;
v66 = v95 + 1;
v67 = v107;
if ( !*(method_info + 8) )
{
v105 = v65;
v68 = 4 * v65;
v69 = *(*(v107 + 20) + v68); // 函数的第一个参数 thisReg
v96 = *v95;
//节选
v111 = v68;
v73 = (*(v67 + 20) + v68);
v74 = *v73;
if ( *v73 && !*(v74 + 4) )
{
*(v74 + 4) = 1;
v78 = v111;
v77 = v96;
**(*(v67 + 20) + v111) = v96;
}
else
{
v75 = v64;
v76 = malloc_1(8u); // 重新创建了一个MainActivity object,并放入第二个register space位置。
*v76 = 0;
*(v76 + 4) = 0;
v77 = v96;
*v76 = v96;
*(v76 + 4) = 1;
*v73 = v76;
v67 = v107;
v64 = v75;
v78 = v111;
}
*(*(v67 + 16) + v78) = v77; // 直接将Activity实例,放入第一个register space的相应位置、
}
v108 = v67;
if ( v64 >= 2 ) // 处理除了this之外的其他参数。
{
v79 = 1;
v112 = 1;
do
{
v80 = v63[v79++ + 1];
if ( v80 > 89 )
{
if ( v80 == 90 )
{
*(*(v67 + 16) + 4 * (v112++ + v105)) = *v66;
++v66;
}
}
else
{
v81 = v80 - 66;
if ( v81 <= 0x11 )
JUMPOUT(__CS__, *(&off_E308 + v81) + 58120);// 调用jni->newGlobalRef,构造将传递给onCreate的参数
}
}
while ( v79 < v64 );
}
}
struct InterpState {
void *pc;
char key;
DexInfo *dex_info;
};
LOAD:0003FF18 BL malloc_1 ; 创建InterpState结构
LOAD:0003FF1C PUSH {R4}
LOAD:0003FF1E POP {R1}
LOAD:0003FF20 PUSH {R0}
LOAD:0003FF22 POP {R4}
LOAD:0003FF24 STR R4, [SP,#0x74+var_24]
LOAD:0003FF26 LDRB R0, [R1,#0x1C]
LOAD:0003FF28 ADDS R6, #0x10
LOAD:0003FF2A STR R6, [SP,#0x74+var_2C]
LOAD:0003FF2C STR R6, [R4] ; InterpState->pc
LOAD:0003FF2E STRB R0, [R4,#4] ; InterpState->key
LOAD:0003FF30 STR R5, [R4,#8] ; InterpState->dex_info
LOAD:0003FF5C LDRB R1, [R4,
LOAD:0003FF5E MOVS R6,
LOAD:0003FF60 PUSH {R1}
LOAD:0003FF62 POP {R2}
LOAD:0003FF64 ANDS R2, R6
LOAD:0003FF66 LDR R0, loc_402C8
LOAD:0003FF68 PUSH {R0}
LOAD:0003FF6A POP {R3}
LOAD:0003FF6C BICS R3, R1
LOAD:0003FF6E ORRS R3, R2
LOAD:0003FF70 MOVS R2,
LOAD:0003FF74 LSLS R1, R1,
LOAD:0003FF76 ANDS R2, R1
LOAD:0003FF78 BICS R0, R1
LOAD:0003FF7A ORRS R0, R2
LOAD:0003FF7C EORS R0, R3
LOAD:0003FF7E LDR R1, [R4] ; 取出pc, Interpstate->pc
LOAD:0003FF80 LDRH R4, [R1] ; 取出指令
LOAD:000463EC loc_463EC
LOAD:000463EC
LOAD:000463EC LDR R0, [R4]
LOAD:000463EE ADDS R0,
LOAD:000463F0 STR R0, [R4] ; InterpState->pc = InterpState->pc + 6
LOAD:000463F2 BL loc_3FF5C ; 跳转到解释器开头,执行下一条指令。
int sub_4878C(int a1, bool methodCallRange, JNIEnv *a3, DexInfo *a4, StackInfo *a5, InterpState *a6, int opNumber, void *a8)
{
a1a = v8;
dex_base = *v8;
dex_header = *(a1a + 16);
key = *(a6 + 4);
v11 = (key << 8) | key;
DexMethodId = dex_base + *(dex_header + 92) + 8 * (*(*a6 + 2) ^ v11);
v13 = dex_base + *(dex_header + 60);
methodName = (dex_base + *(v13 + 4 * *(DexMethodId + 4)));
do
v15 = *methodName++ < 0;
while ( v15 );
DexMethodId2 = (dex_base + *(dex_header + 92) + 8 * (*(*a6 + 2) ^ ((key << 8) | key)));
proto = (dex_base
+ *(v13
+ 4 * *(dex_base + *(dex_header + 68) + 4 * *(dex_base + *(dex_header + 76) + 12 * *(DexMethodId + 2) + 4))));
do
v17 = *proto++;
while ( v17 < 0 );
v18 = *(*a6 + 4);
if ( v52 == 1 )
thisReg = v18 ^ ((key << 8) | key);
else
thisReg = (v18 ^ key) & 0xF;
v20 = 0;
if ( v51 )
{
v21 = *(*(a5 + 20) + 4 * thisReg);
if ( !v21 || (v20 = *v21) == 0 )
{
v30 = ((*v53)->FindClass)(v53, "java/lang/NullPointerException");
.....
}
}
arg0 = v20;
v62 = v53;
v63 = 0;
if ( ((*v53)->ExceptionCheck)(v53) )
v63 = 0;
if ( v51 != 2 && v51 != 4 )
{
sub_610BC(a1a, v53, *DexMethodId2);
return sub_48AE2(v32, v33, v34, v35, a5);
}
看雪ID:glider菜鸟
https://bbs.pediy.com/user-657393.htm
推荐文章++++
* CVE-2017-13258 Android 蓝牙BNEP漏洞分析