本文仅限于技术讨论,不得用于非法途径,后果自负。
这是萌新第一次逆向vmp,主要是分享分析过程,这里借鉴了金罡大佬的文章https://bbs.kanxue.com/thread-282300.htm,vmp的内存布局和context 在我选用的这个版本差别并不大。选用的TT 中libEncryptor.so 中被vm 的jnionload。
用ida打开so 定位到AF8 ,看一下cfg 下面这一排就是handle的实现了 不过handle太多了 我只会还原被执行的指令集。
从下面两张图可以看出vm指令集4字节对齐和arm一致 ,在后面的逆向中发现开发者并没有实现指令集或者说指令集就是arm64 还原指令的第一步就是解析出指令中携带的信息,一般来说,有这几个信息 1.指令类型 2.寄存器信息 3.立即数 可以看到在虚拟机循环的开头就是虚拟机取出指令各个信息的过程
可以看到 指令类型 sourceREG destREG opcode 这几个关键的信息
可以理解为虚拟机使用的寄存器 堆栈 等信息 这里可以参考金罡大佬的文章https://bbs.kanxue.com/thread-282300.htm 这个版本没什么变化,唯一注意的是我并不是通过汇编而是f5代码来确定coutext的结构的,而开发者为了对抗,这个context结构体是负指针寻址的 所以需要自己patch代码 比如 STP X3, X20, [X19,#-0x100]=>STP X3, X20, [X19,#0x100] 这个方法中只需要patch 所有有关x19的指针操作即可 效果图
这个可能是最头疼的一点,明明开发者写的就是一个while switch 可是被编译器优化后代码复用,各种跳转比如 可能你找handle的时间都比逆向handle的时间长 这里,我使用了一个实验性质的方法 利用trace在剔除控制流指令后重新patch 效果图 可以看到 所有handle都被打印出来了 指令缩短 变成单次打印单个handle 这样我觉得是提高了我的分析效率
这个是我觉得最繁琐的地方,我看了我还原出来的指令和金罡大佬的还原,还是细节不够 对比可以看到mov少了个z,这就是细节不够,另外还有对arm指令集不够熟悉一些偏门指令如果不知道那就完犊子了
这是我还原最后一个handle看出来的 原先我以为是cmp 但是不对劲,简而言之就是每一次call 后会检查返回值 如果返回值对 vm_pc+2 结合br指令集 lr = pc+2 刚好四字节对齐,如果不对 哦吼 pc +2 指令集对齐直接挂 随机崩溃 br handle
// unsigned int code
// Bit_28_State = code & 0x10000000;
// Bit_29_State = code & 0x20000000;
// Bit_30_State = code & 0x40000000;
// v17 = (code >> 11) & 2 | (code >> 31) | (code >> 11) & 4 | (code >> 11) & 8 | (code >> 11) & 0x10;// 提取第31位 提取第12,13,14,15位 组合
// // [15,14,13,12,31]
// sourceREG = (code >> 21) & 0x1F; // 取第22 =>26的值
// // [26,25,24,23,22]
// destREG = HIWORD(code) & 0x1F; // 取17 > 21位
// // [21,20,19,18,17]
// Bit_31_State = code & 0x80000000;
// Bit_30_State_1 = code & 0x4000000;
// Bit_31_State_1 = code & 0x8000000;
var type = code.and(0x3f)
var code = this.vm_handles
var sourceREG = code.shr(21).and(0x1F)
var destREG = code.shr(16).and(0x1F)
var Bit_28_State = code.and(0x10000000)
var Bit_29_State = code.and(0x20000000)
var Bit_30_State = code.and(0x40000000)
var Bit_31_State = code.and(0x80000000)
var Bit_30_State_1 = code.and(0x4000000)
var Bit_31_State_1 = code.and(0x8000000)
var intv17 = code.toUInt32()
var v17 = (intv17 >>> 11) & 2 | (intv17 >>> 31) | (intv17 >>> 11) & 4 | (intv17 >>> 11) & 8 | (intv17 >>> 11) & 0x10
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
// unsigned int code
// Bit_28_State = code & 0x10000000;
// Bit_29_State = code & 0x20000000;
// Bit_30_State = code & 0x40000000;
// v17 = (code >> 11) & 2 | (code >> 31) | (code >> 11) & 4 | (code >> 11) & 8 | (code >> 11) & 0x10;// 提取第31位 提取第12,13,14,15位 组合
// // [15,14,13,12,31]
// sourceREG = (code >> 21) & 0x1F; // 取第22 =>26的值
// // [26,25,24,23,22]
// destREG = HIWORD(code) & 0x1F; // 取17 > 21位
// // [21,20,19,18,17]
// Bit_31_State = code & 0x80000000;
// Bit_30_State_1 = code & 0x4000000;
// Bit_31_State_1 = code & 0x8000000;
var type = code.and(0x3f)
var code = this.vm_handles
var sourceREG = code.shr(21).and(0x1F)
var destREG = code.shr(16).and(0x1F)
var Bit_28_State = code.and(0x10000000)
var Bit_29_State = code.and(0x20000000)
var Bit_30_State = code.and(0x40000000)
var Bit_31_State = code.and(0x80000000)
var Bit_30_State_1 = code.and(0x4000000)
var Bit_31_State_1 = code.and(0x8000000)
var intv17 = code.toUInt32()
var v17 = (intv17 >>> 11) & 2 | (intv17 >>> 31) | (intv17 >>> 11) & 4 | (intv17 >>> 11) & 8 | (intv17 >>> 11) & 0x10
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
decode(): string {
//ArrayBuffer to ptr
var type = this.vm_handles.and(0x3F)
// unsigned int code
// Bit_28_State = code & 0x10000000;
// Bit_29_State = code & 0x20000000;
// Bit_30_State = code & 0x40000000;
// v17 = (code >> 11) & 2 | (code >> 31) | (code >> 11) & 4 | (code >> 11) & 8 | (code >> 11) & 0x10;// 提取第31位 提取第12,13,14,15位 组合
// // [15,14,13,12,31]
// sourceREG = (code >> 21) & 0x1F; // 取第22 =>26的值
// // [26,25,24,23,22]
// destREG = HIWORD(code) & 0x1F; // 取17 > 21位
// // [21,20,19,18,17]
// Bit_31_State = code & 0x80000000;
// Bit_30_State_1 = code & 0x4000000;
// Bit_31_State_1 = code & 0x8000000;
var code = this.vm_handles
var sourceREG = code.shr(21).and(0x1F)
var destREG = code.shr(16).and(0x1F)
var Bit_28_State = code.and(0x10000000)
var Bit_29_State = code.and(0x20000000)
var Bit_30_State = code.and(0x40000000)
var Bit_31_State = code.and(0x80000000)
var Bit_30_State_1 = code.and(0x4000000)
var Bit_31_State_1 = code.and(0x8000000)
var intv17 = code.toUInt32()
var v17 = (intv17 >>> 11) & 2 | (intv17 >>> 31) | (intv17 >>> 11) & 4 | (intv17 >>> 11) & 8 | (intv17 >>> 11) & 0x10
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
switch (type.toUInt32()) {
case 3:
case 5:
case 0xF:
case 0x1A:
case 0x2C:
case 0x2D:
case 0x3A:
case 0x3F:
switch (type.toUInt32()) {
case 5:
case 0xF:
case 0x2C:
case 0x3A:
return "cmp " + this.reg(sourceREG) + "," + this.reg(destREG)
}
case 0x2:
// vm_regs[(HIWORD(vm_code_1) & 0x1F) + 1] = *(_QWORD *)(vm_regs[((vm_code_1 >> 21) & 0x1F) + 1]
// + (__int16)(vm_code_1 & 0xF000 | ((vm_code_1 & 0x4000000) >> 20) | (vm_code_1 >> 6) & 0x3F | ((vm_code_1 & 0x8000000) >> 20) | ((vm_code_1 & 0x10000000) >> 20) | ((vm_code_1 & 0x20000000) >> 20) | ((vm_code_1 & 0x40000000) >> 20) | ((vm_code_1 & 0x80000000) >> 20)));
let opcode1 = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
return "ldr " + this.reg(destREG) + ",[" + this.reg(sourceREG) + ",#" + opcode1 + "]"
case 0xA:
case 0xB:
case 0xE:
case 0x14:
case 0x16:
case 0x24:
case 0x36:
case 0x3b:
// (__int16)(code & 0xF000 | (Bit_30_State_1 >> 20) | (code >> 6) & 0x3F | (Bit_31_State_1 >> 20) | (Bit_28_State >> 20) | (Bit_29_State >> 20) | (Bit_30_State >> 20) | (Bit_31_State >> 20));
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
return "stp " + this.reg(destREG) + " ,[" + this.reg(sourceREG) + "," + opcode + "]"
case 4:
case 0x20:
case 0x38:
case 0x3e:
// v39 = vm_code_1 & 0x3F;
// if (v39 > 0x37) {
// if (v39 == 56) {
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) ^ (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20));
// }
// else if (v39 == 62) {
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) | vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20);
// }
// }
// else {
// if (v39 == 4) {
// LODWORD(v18) = (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20)) << 16;
// v18 = (int)v18;
// v25 = &vm_regs[(unsigned int)v19];
// v25[1] = v18;
// }
// if (v39 == 32)
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) & (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20));
// }
var v39 = code.and(0x3F)
let opcode2 = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
if(v39.toUInt32() > 0x37){
if(v39.toUInt32() == 56){
return "eor " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}else if(v39.toUInt32() == 62){
return "orr " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}
}else{
if(v39.toUInt32() == 4){
return "mov " + this.reg(destREG) + "," + opcode2
}else if(v39.toUInt32() == 32){
return "and " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}
}
case 0:
case 2:
case 8:
case 0x12:
case 0x1F:
case 0x21:
case 0x22:
case 0x27:
case 0x2B:
case 0x30:
case 0x31:
case 0x33:
case 0x37:
return "mov " + this.reg(destREG) + " , " + this.reg(sourceREG)
case 0xD:
case 0x15:
case 0x1B:
case 0x28:
// v40 = vm_code_1 & 0x3F;
// v41 = vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20);
// if ( v40 == 13 || v40 == 40 )
// {
// *(&v5->REGS + (unsigned int)v19) = *(&v5->REGS + (unsigned int)v18) + (__int16)v41;
// }
// else if ( v40 == 21 )
// {
// *(&v5->REGS + (unsigned int)v19) = *((int *)&v5->REGS + 2 * v18) + (__int64)(__int16)v41;
// }
let v40 = code.and(0x3F)
let v41 = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
if (v40.toUInt32() == 13 || v40.toUInt32() == 40) {
return "add " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + v41
}
else if (v40.toUInt32() == 21) {
return "add " + this.reg(destREG) + "," + this.reg(sourceREG.shl(1)) + "," + v41
}
case 0x2f:
// v71 = vm_code_1 & 0xFFF;
// HIDWORD(v72) = v71 - 111;
// LODWORD(v72) = HIDWORD(v72);
// switch ( (unsigned int)(v72 >> 6) )
var v71 = code.and(0xFFF)
var v72 = v71.sub(111)
switch (v72.shr(6).toUInt32()) {
case 0x30:
if (v71.toInt32() == 0xC6F)
// p_REGS = &v5->REGS;
// v96 = *((_DWORD *)&v5->REGS + 2 * v19) << (((vm_code_1 & 0x10000000) >> 26) & 0xFC | (vm_code_1 >> 26) & 3 | ((vm_code_1 & 0x20000000) >> 26) | ((vm_code_1 & 0x40000000) >> 26));
return "ldr " + this.reg(destREG) + ",[" + this.reg(sourceREG.shl(1)) + ",#" + code.shr(26).and(0xFC).or(Bit_28_State.shr(26).and(3)).or(Bit_29_State.shr(26)).or(Bit_30_State.shr(26)).or(Bit_31_State.shr(26)) + "]"
return "ret"
case 0x15:
if(v71.toInt32() == 0x5af)
return "br " + this.reg(sourceREG)
case 0x19:
return "ret"
case 6:
case 0xD:
case 0x1A:
case 0x20:
case 0x24:
case 0x26:
case 0x28:
case 0x33:
// v73 = vm_code_1 & 0xFFF;
// if ( v73 > 0x86E )
// {
// if ( (vm_code_1 & 0xFFF) <= 0x9EE )
// goto LABEL_154;
// goto LABEL_64;
// }
// if ( (vm_code_1 & 0xFFF) > 0x3AE )
// goto LABEL_254;
// if ( v73 != 495 )
// goto LABEL_218;
// goto LABEL_252;
var v73 = v71.toUInt32()
if (v73 > 0x86E) {
if (v71.toUInt32() <= 0x9EE) {
return "ret"
} else {
if ( v73 == 2543 )
// *(&v5->REGS + v17) = *(&v5->REGS + (unsigned int)v19) + *(&v5->REGS + (unsigned int)v18);
return "add " + this.reg(ptr(v17)) + "," + this.reg(destREG) + "," + this.reg(sourceREG)
}
}
if (v73 > 0x3AE) {
return "ret"
}
if (v73 != 495) {
return "ret"
} else {
return "ret"
}
case 0xC:
case 0x17:
case 0x1F:
case 0x3C:
// v108 = vm_code_1 & 0xFFF;
// if ( v108 > 0x82E )
// {
// if ( v108 == 2095 )
// {
// *(&v5->REGS + v17) = ~(*(&v5->REGS + (unsigned int)v19) | *(&v5->REGS + (unsigned int)v18));
// }
// else if ( v108 == 3951 )
// {
// *(&v5->REGS + v17) = *(&v5->REGS + (unsigned int)v19) & *(&v5->REGS + (unsigned int)v18);
// }
// }
// else if ( v108 == 879 )
// {
// *(&v5->REGS + v17) = *(&v5->REGS + (unsigned int)v19) ^ *(&v5->REGS + (unsigned int)v18);
// }
// else if ( v108 == 1583 )
// {
// *(&v5->REGS + v17) = *(&v5->REGS + (unsigned int)v19) | *(&v5->REGS + (unsigned int)v18);
// }
var v108 = v71.toUInt32()
if (v108 > 0x82E) {
if (v108 == 2095) {
return "not " + this.reg(ptr(v17)) + "," + this.reg(destREG) + "," + this.reg(sourceREG)
} else if (v108 == 3951) {
return "and " + this.reg(ptr(v17)) + "," + this.reg(destREG) + "," + this.reg(sourceREG)
}
} else if (v108 == 879) {
return "eor " + this.reg(ptr(v17)) + "," + this.reg(destREG) + "," + this.reg(sourceREG)
} else if (v108 == 1583) {
return "orr " + this.reg(ptr(v17)) + "," + this.reg(destREG) + "," + this.reg(sourceREG)
}
}
}
return ""
}
reg(index: NativePointer): string {
var index1 = index.toUInt32()
if (index1 == 31) {
return "lr"
}
if (index1 == 29) {
return "sp"
}
if (index1 == 30) {
return "fp"
}
return "x" + index1
}
decode(): string {
//ArrayBuffer to ptr
var type = this.vm_handles.and(0x3F)
// unsigned int code
// Bit_28_State = code & 0x10000000;
// Bit_29_State = code & 0x20000000;
// Bit_30_State = code & 0x40000000;
// v17 = (code >> 11) & 2 | (code >> 31) | (code >> 11) & 4 | (code >> 11) & 8 | (code >> 11) & 0x10;// 提取第31位 提取第12,13,14,15位 组合
// // [15,14,13,12,31]
// sourceREG = (code >> 21) & 0x1F; // 取第22 =>26的值
// // [26,25,24,23,22]
// destREG = HIWORD(code) & 0x1F; // 取17 > 21位
// // [21,20,19,18,17]
// Bit_31_State = code & 0x80000000;
// Bit_30_State_1 = code & 0x4000000;
// Bit_31_State_1 = code & 0x8000000;
var code = this.vm_handles
var sourceREG = code.shr(21).and(0x1F)
var destREG = code.shr(16).and(0x1F)
var Bit_28_State = code.and(0x10000000)
var Bit_29_State = code.and(0x20000000)
var Bit_30_State = code.and(0x40000000)
var Bit_31_State = code.and(0x80000000)
var Bit_30_State_1 = code.and(0x4000000)
var Bit_31_State_1 = code.and(0x8000000)
var intv17 = code.toUInt32()
var v17 = (intv17 >>> 11) & 2 | (intv17 >>> 31) | (intv17 >>> 11) & 4 | (intv17 >>> 11) & 8 | (intv17 >>> 11) & 0x10
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
switch (type.toUInt32()) {
case 3:
case 5:
case 0xF:
case 0x1A:
case 0x2C:
case 0x2D:
case 0x3A:
case 0x3F:
switch (type.toUInt32()) {
case 5:
case 0xF:
case 0x2C:
case 0x3A:
return "cmp " + this.reg(sourceREG) + "," + this.reg(destREG)
}
case 0x2:
// vm_regs[(HIWORD(vm_code_1) & 0x1F) + 1] = *(_QWORD *)(vm_regs[((vm_code_1 >> 21) & 0x1F) + 1]
// + (__int16)(vm_code_1 & 0xF000 | ((vm_code_1 & 0x4000000) >> 20) | (vm_code_1 >> 6) & 0x3F | ((vm_code_1 & 0x8000000) >> 20) | ((vm_code_1 & 0x10000000) >> 20) | ((vm_code_1 & 0x20000000) >> 20) | ((vm_code_1 & 0x40000000) >> 20) | ((vm_code_1 & 0x80000000) >> 20)));
let opcode1 = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
return "ldr " + this.reg(destREG) + ",[" + this.reg(sourceREG) + ",#" + opcode1 + "]"
case 0xA:
case 0xB:
case 0xE:
case 0x14:
case 0x16:
case 0x24:
case 0x36:
case 0x3b:
// (__int16)(code & 0xF000 | (Bit_30_State_1 >> 20) | (code >> 6) & 0x3F | (Bit_31_State_1 >> 20) | (Bit_28_State >> 20) | (Bit_29_State >> 20) | (Bit_30_State >> 20) | (Bit_31_State >> 20));
let opcode = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
return "stp " + this.reg(destREG) + " ,[" + this.reg(sourceREG) + "," + opcode + "]"
case 4:
case 0x20:
case 0x38:
case 0x3e:
// v39 = vm_code_1 & 0x3F;
// if (v39 > 0x37) {
// if (v39 == 56) {
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) ^ (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20));
// }
// else if (v39 == 62) {
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) | vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20);
// }
// }
// else {
// if (v39 == 4) {
// LODWORD(v18) = (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20)) << 16;
// v18 = (int)v18;
// v25 = &vm_regs[(unsigned int)v19];
// v25[1] = v18;
// }
// if (v39 == 32)
// * (& v5 -> REGS + (unsigned int)v19) = * (& v5 -> REGS + (unsigned int)v18) & (vm_code_1 & 0xF000 | (v21 >> 20) | (vm_code_1 >> 6) & 0x3F | (v22 >> 20) | (v14 >> 20) | (v15 >> 20) | (v16 >> 20) | (v20 >> 20));
// }
var v39 = code.and(0x3F)
let opcode2 = code.and(0xF000).or(Bit_30_State_1.shr(20)).or(code.shr(6).and(0x3F)).or(Bit_31_State_1.shr(20)).or(Bit_28_State.shr(20)).or(Bit_29_State.shr(20)).or(Bit_30_State.shr(20)).or(Bit_31_State.shr(20))
if(v39.toUInt32() > 0x37){
if(v39.toUInt32() == 56){
return "eor " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}else if(v39.toUInt32() == 62){
return "orr " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}
}else{
if(v39.toUInt32() == 4){
return "mov " + this.reg(destREG) + "," + opcode2
}else if(v39.toUInt32() == 32){
return "and " + this.reg(destREG) + "," + this.reg(sourceREG) + "," + opcode2
}
}
case 0:
case 2:
case 8:
case 0x12:
case 0x1F:
case 0x21:
case 0x22:
case 0x27:
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: