首页 > 其他分享 >ADVMP 三代壳(vmp加固)原理分析(执行流程)

ADVMP 三代壳(vmp加固)原理分析(执行流程)

时间:2023-04-14 13:24:44浏览次数:30  
标签:vsrc1 inst separatorData gAdvmp INST 加固 ADVMP vmp OP

由于在加壳时插入了System.loadLibrary("advmp");,看一下JNI_OnLoad

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
    JNIEnv* env = NULL;

    if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        return JNI_ERR;
    }

    // 注册本地方法。
    registerFunctions(env);

    // 获得apk路径。
    gAdvmp.apkPath = GetAppPath(env);
    MY_LOG_INFO("apk path:%s", gAdvmp.apkPath);

    // 释放yc文件。
    gAdvmp.ycSize = ReleaseYcFile(gAdvmp.apkPath, &gAdvmp.ycData);
    if (0 == gAdvmp.ycSize) {
        MY_LOG_WARNING("release Yc file fail!");
        goto _ret;
    }

    // 解析yc文件。
    gAdvmp.ycFile = new YcFile;
    if (!gAdvmp.ycFile->parse(gAdvmp.ycData, gAdvmp.ycSize)) {
        MY_LOG_WARNING("parse Yc file fail.");
        goto _ret;
    }

_ret:
    return JNI_VERSION_1_4;
}
在这里解析了yc文件,并保存在了内存中(gAdvmp.ycFile)

看一下MainActivity

public class MainActivity extends Activity {
	
	public static final String TAG = "debug";
	
	private Button mbtnTest;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		nativeLog();
		
		mbtnTest = (Button) findViewById(R.id.btnTest);
		mbtnTest.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View v) {
				int result = separatorTest(2);
				Log.i(TAG, "separatorTest result:" + result);
			}
		});
	}
	
	private native int separatorTest(int value);
	
	private native static void nativeLog();
	
	static {
		System.loadLibrary("advmp");
	}
	
}

壳已经将separatorTest 转化为了native方法了

当执行时就会执行到相应的native方法(也是之前壳生成的cpp代码)

jint separatorTest(JNIEnv* env, jobject thiz, jint value) {
    MY_LOG_INFO("separatorTest - value=%d", value);
    jvalue result = BWdvmInterpretPortable(gAdvmp.ycFile->GetSeparatorData(0), env, thiz, value);
    return result.i;
}

关键就是BWdvmInterpretPortable,这个函数实现的转发,看一下它的实现, 它在InterpC.cpp,这是一个自定义指令解释器的实现

InterpC.cpp::BWdvmInterpretPortable

jvalue BWdvmInterpretPortable(const SeparatorData* separatorData, JNIEnv* env, jobject thiz, ...) {
    jvalue* params = NULL; // 参数数组。
    jvalue retval;  // 返回值。

    const u2* pc;   // 程序计数器。
    u4 fp[65535];   // 寄存器数组。
    u2 inst;        // 当前指令。
    u2 vsrc1, vsrc2, vdst;      // usually used for register indexes

    unsigned int startIndex;

    // 处理参数。
    va_list args;
    va_start(args, thiz); 
    params = getParams(separatorData, args);
    va_end(args);

    // 获得参数寄存器个数。    
    size_t paramRegCount = getParamRegCount(separatorData);

    // 设置参数寄存器的值。
    if (isStaticMethod(separatorData)) {
        startIndex = separatorData->registerSize - separatorData->paramSize;
    } else {
        startIndex = separatorData->registerSize - separatorData->paramSize;
        fp[startIndex++] = (u4)thiz;
    }
    for (int i = startIndex, j = 0; j < separatorData->paramSize; j++ ) {
        if ('D' == separatorData->paramShortDesc.str[i] || 'J' == separatorData->paramShortDesc.str[i]) {
            fp[i++] = params[j].j & 0xFFFFFFFF;
            fp[i++] = (params[j].j >> 32) & 0xFFFFFFFF;
        } else {
            fp[i++] = params[j].i;
        }
    }

    pc = separatorData->insts;

    /* static computed goto table */
    DEFINE_GOTO_TABLE(handlerTable);

    // 抓取第一条指令。
    FINISH(0);

/*--- start of opcodes ---*/

/* File: c/OP_NOP.cpp */
HANDLE_OPCODE(OP_NOP)
    FINISH(1);
OP_END

这里通过数组来模拟寄存器, 通过int指针来模拟pc寄存器,完成各个指令的运算,比如

HANDLE_OPCODE(OP_MOVE /*vA, vB*/)
    vdst = INST_A(inst);
    vsrc1 = INST_B(inst);
    MY_LOG_VERBOSE("|move%s v%d,v%d %s(v%d=0x%08x)",
        (INST_INST(inst) == OP_MOVE) ? "" : "-object", vdst, vsrc1,
        kSpacing, vdst, GET_REGISTER(vsrc1));
    SET_REGISTER(vdst, GET_REGISTER(vsrc1));
    FINISH(1);
OP_END

HANDLE_OPCODE(OP_MOVE /*vA, vB*/),生成的是一个goto用的标签,
在FINISH中会有一个goto来实现跳转

# define FINISH(_offset) {                                                  \
        ADJUST_PC(_offset);                                                 \
        inst = FETCH(0);                                                    \
        /*if (self->interpBreak.ctl.subMode) {*/                                \
            /*dvmCheckBefore(pc, fp, self);*/                                   \
        /*}*/                                                                   \
        goto *handlerTable[INST_INST(inst)];                                \
    }

通过这种方式来完成多行指令的顺序执行
知道遇到RETURN指令结束执行,返回返回值

HANDLE_OPCODE(OP_RETURN /*vAA*/)
    vsrc1 = INST_AA(inst);
    MY_LOG_VERBOSE("|return%s v%d",
        (INST_INST(inst) == OP_RETURN) ? "" : "-object", vsrc1);
    retval.i = GET_REGISTER(vsrc1);
    /*GOTO_returnFromMethod();*/
    GOTO_bail();
OP_END
.....

bail:
    if (NULL != params) {
        delete[] params;
    }
    MY_LOG_INFO("|-- Leaving interpreter loop");
    return retval;
执行原理结论:
  1. JNI_OnLoad 读取yc文件,获取指令
  2. native 中执行BWdvmInterpretPortable 主要入参为从yc中获得的separatorData
  3. 通过自定义解释器逐行指令指令,并返回返回值

ps: 这个开源项目提供的是一种思路,不可用于商用, 仅支持计算用指令的解释, 引用类的指令解释未实现

标签:vsrc1,inst,separatorData,gAdvmp,INST,加固,ADVMP,vmp,OP
From: https://www.cnblogs.com/gradyblog/p/17317993.html

相关文章

  • 网络设备安全加固
    0x00前言目的:对网络设备进行加固,包括基础设备安全功能配置和账户登录、密码安全策略配置。网络设备版本路由器:CiscoIOS15.5(5)M交换机:CiscoIOS15.2(4)E防火墙:CiscoASA9.17网络设备配置文档CiscoIOS15.5(5)M:https://www.cisco.com/c/en/us/support......
  • ADVMP 三代壳(vmp加固)原理分析(加壳流程)
    开源项目地址https://github.com/chago/ADVMPvmp加固可以说时各大加固厂商的拳头产品了,这个开源项目虽然不是十分完善,让我们可以一览vmp加固的原理,是十分好的学习资源vmp全称:virtualmachineprotect,本质是将原来smali对应的代码转化为自定义的代码,然后通过自定义的......
  • 菜鸟手脱VMP,附上脱壳过程和自己写的脚本,可跨平台
    工作需要要脱一个VMP壳,我是一个从来没接触过脱壳的人。瞬间那种心情遇到的人应该都知道!没办法硬着头皮找教程,7天看完了《天草的壳的世界》尝试脱壳下面是我的脱壳过程希望大牛多多指正!1、准备工具,FEID(查壳工具)、DIE(查壳工具)、LordPE(dump工具)、ImpRec(IAT修复工具)、UIF(IAT修复工具)......
  • APK加固方式及步骤
    通过调研深盾科技的VirboxProtectorAPK加固,APK加固目前主要的保护需要注意三种。第一点:直接对APK加固,直接对APK加固,设置Dex函数的虚拟化保护,目前这类是安全性很高的保护方式,但是不能全选函数做虚拟化,会有性能损耗。第二点:APK里so的加固,APK里so的加固,如果想要安全性比较高,用apk加固......
  • VMProtect完美脱壳过程
    VMProtect完美脱壳过程1.查看程序这是我自己写的一个VB的小程序,长得有点丑,别介意。然后自己加了一个壳,是VMProtectv.1.6x-2.03的壳。接下来我们国际惯例,用PEID,EXEinfoPE查一下壳可以看到是加了VMP的壳的,VMP壳的介绍我会放在帖子的最后哦。2.拉到OD去啦~push......
  • 漏洞扫描与安全加固之Apache Axis组件
    一、ApacheAxis组件高危漏洞自查及整改ApacheAxis组件存在由配置不当导致的远程代码执行风险。1.影响版本Axis1和Axis2各版本均受影响2.处置建议1)禁用此服务的远......
  • SpringCloud微服务实战——搭建企业级开发框架(五十一):微服务安全加固—自定义Gateway拦
      SQL注入是常见的系统安全问题之一,用户通过特定方式向系统发送SQL脚本,可直接自定义操作系统数据库,如果系统没有对SQL注入进行拦截,那么用户甚至可以直接对数据库进行增删......
  • CentOS -Linux 等保-安全加固相关配置
     1、口令锁定策略规则描述:设置口令认证失败后的锁定策略为了保障用户系统的安全,建议用户设置口令出错次数的阈值,以及由于口令尝试被锁定用户的自动解锁时间。用户锁定......
  • Android各代加固总结
    Android软件加固概述从2012年开始,移动互联网进入快速发展阶段,AndroidApp开发热潮的兴起,也推动了Android平台软件保护技术的发展。•为何做加固保护核心代码防止营销......
  • Linux-等保加固-记录用户的登录和操作日志
    通过脚本代码实现记录所有用户的登录操作日志,防止出现安全事件后无据可查修改/etc/profile配置文件,在配置文件中新增以下内容 vi/etc/profileihistoryUSER=`whoam......