android逆向之NDK基础(so更改java全局变量/so调用java方法)(一)

<strong>
</strong>
本章讲解so层怎么修改java层的变量,以及so层调用java层的方法,直接上代码.


package JNIEnvMethod;

public class JniDemo {

	static {
		System.load(
				"F:\\HelloJava_Code_AndroidDecompilation\\_(一)Decompilation_testJNI\\libs\\lib_(一)JNIEnvMethods.dll");
	}

	String name = "~~";
	String sex = "~~";
	String age = "~~";

	//
	public static void main(String[] args) {
		JniDemo mJniDemo = new JniDemo();
		mJniDemo.BxlCPPMethod("My decompilation");
		System.out.println("name:" + mJniDemo.name + "; sex:" + mJniDemo.sex + "; age:" + mJniDemo.age);
		mJniDemo.awaitSoInvoke("java");
	}

	native void BxlCPPMethod(String jstr);

	public void awaitSoInvoke(String param1) {
		System.out.println(String.format("我被%s运行了", param1));
	}
}

c++代码:



#include "jni.h"
//#include <string>
#include "JNIEnvMethod_JniDemo.h"

/** 本章解析:
 *
 * 本章内存比较简单,主要是说的
 * 	1.java字符串怎么转c++字符串
 * 	2.c++访问java层的全局变量
 * 	3.c++调用java层的方法
 *
 * 	主要牵涉的方法有:
 * 	Get***ID:获取方法 / 变量ID(需要对应的clazz/名字/签名)
 * 	getObjectClass:其实也可以这样写:env->FindClass("JNIEnvMethod.JniDemo"); 其实就是一个反射!
 * 	Call**Method: 调用java层方法
 *
 * 	jclass: 可以想成是java里面的反射, 通过他可以获取到该类里面所有的成员变量/方法, 但是不能对该变量/方法做任何的操作!为什么?因为你没有对象!没有实例!而方法的对象是谁?是jobject!
 * 	jobject: 上面其实已经说了,jobject是java层的对象,谁调用谁对象!通过getobjectclass/findclass可获取到jclass,在结合jobject是不是就可以对参数对象实现调用 修改了?
 *
 *  方法签名:什么是方法签名?这么说吧,这个东西不用理解,死记就行,看多了就记住了.如果逆向过apk,应该就很好记,smail语法随处可见这东西
 *  		打个几个比方来说:(Ljava/lang/String;)V : 括号里面的"Ljava/lang/String;"说明方法的有一个参数String, "V"说明方法的返回值是void
 *  					   (Ljava/lang/String;)Ljava/lang/String; : 括号里面的"Ljava/lang/String;"说明方法的有一个参数String, "V"说明方法的返回值是String
 *			可以这么想,方法签名就是 方法参数和方法返回值的一组特殊字符串,参数签名就是参数的类型!
 *	签名对应表:boolean : Z
 *	 	 	 char : c
 *	 	 	 byte : B
 *	 	 	 short : S
 *	 	 	 int : I
 *	 	 	 long : J
 *	 	 	 float : F
 *	 	 	 double : D
 *
 *
 */

/**
 * 参数一:env 代表的是java环境!,可以想成是一个数组,里面装的全是方法,
 * 参数二:obj 代表的是java层调用者的对象,谁调用的这个so,obj就代表谁的对象
 * 参数三:jstr代表的是java层第一个参数
 * 参数四:这里其实是没有参数四的. 如果有,它代表的是java层的第二个参数.
 * 参数五:同上!
 */
JNIEXPORT void JNICALL Java_JNIEnvMethod_JniDemo_BxlCPPMethod(JNIEnv *env,
		jobject obj, jstring jstr) {

	/** 一:GetStringUTFChars方法:jstr转cstr并输出
	 *
	 */
	jsize jstrLength = env->GetStringLength(jstr);
	const char *cstr = env->GetStringUTFChars(jstr, NULL);
	printf("str:%s; length:%ld", cstr, jstrLength);

	/** 二:获取java的全局变量并修改
	 *
	 * GetObjectClass:类似getClass();
	 * getXXXID类方法:此类方法可以获取java层的信息(全局变量 方法),其中参数三是字段签名,签名在最后讲;可以想成放射获取
	 */
	//修改字段name的值为caijincheng
	jfieldID name = env->GetFieldID(env->GetObjectClass(obj), "name",
			"Ljava/lang/String;");
	char new_name[40] = "CaiJinCheng";
	jstring nameValue = env->NewStringUTF(new_name);
	env->SetObjectField(obj, name, nameValue);

	//修改sex的字段为N
	jfieldID sex = env->GetFieldID(env->GetObjectClass(obj), "sex",
			"Ljava/lang/String;");
	char new_sex[40] = "N";
	jstring sexValue = env->NewStringUTF(new_sex);
	env->SetObjectField(obj, sex, sexValue);

	//设置age的字段为26
	jfieldID age = env->GetFieldID(env->GetObjectClass(obj), "age",
			"Ljava/lang/String;");
	char new_age[40] = "26";
	jstring ageValue = env->NewStringUTF(new_age);
	env->SetObjectField(obj, age, ageValue);

	/** 三.获取java层方法,并调用
	 *
	 * GetMethodID: 通过方法class/方法名/方法签名来获取java层方法的id.
	 * CallVoidMethod:通过方法id 和 class对象来调用java层的方法;
	 */
	jmethodID jawaitSoInvoke = env->GetMethodID(env->GetObjectClass(obj),
			"awaitSoInvoke", "(Ljava/lang/String;)V");
	char new_param[] = "c++";
	jstring param1 = env->NewStringUTF(new_param);
	env->CallVoidMethod(obj, jawaitSoInvoke, param1);

}


 

为了方便.上面的代码并没有在android环境上写,而是用的java环境,其实是一样的,或者说一模一样.

不懂的留言给我或者加QQ交流群:492788365


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值