Android逆向基础-java基础入门

目录

        • 一、vscode安装java插件
        • 二、java代码基础知识扫盲了解
          • 1、类class
          • 2、导包依赖
          • 3、定义变量
          • 4、方法函数
        • 三、apk_java层逆向小案例
        • 四、java与frida的hook文章推荐

一、vscode安装java插件

  • jdk(Java Develpment Kit java 开发工具)是我们用来写代码的,jdk中包含jre,

  • jre(Java Runtime Environment java运行时环境)是用来使用代码的,jre包含jvm,

  • jvm(java Virtual Machine java 虚拟机)是用来运行代码的,jdk是给开发人员使用的, jre和jvm是给普通用户使用
    Android逆向基础-java基础入门_第1张图片

  • JVM+Lib=JRE,总体来说就是,我们利用JDK(调用JAVA API)开发了属于我们自己的JAVA程序后,通过JDK中的编译程序(javac)将我们的.java文件编译成JAVA字节码(.class文件),在JRE上运行这些JAVA字节码(.class文件),JVM解析这些字节码,映射到CPU指令集或OS的系统调用。通俗的讲运行java代码实际上走了如图中的两步命令:javac编译,java运行;而python运行文件只需要python test.py即可
    在这里插入图片描述

  • java的JDK环境准备:参考jdk1.8_java环境安装(目录3) 的介绍

  • 下载vscode ,然后直接安装,中间安装路径可以自定义,以及创建桌面快捷方式,其它的不用改直接next

  • 搜索Extension Pack for Java,然后下载安装
    Android逆向基础-java基础入门_第2张图片

  • vscode测试java运行:ctrl+shift+p然后搜索Java: create Project,选择No build tools,然后选择一个文件夹,输入项目名,然后会自动创建好java工程目录,在src下直接runApp.java输出成功,配置完毕在这里插入图片描述
    Android逆向基础-java基础入门_第3张图片
    在这里插入图片描述

  • 注意CodeLens即代码中出现的灰色的Run|Debug按钮,如果你的文件没有的话,可能是网络不好的原因,导致没有加载出来
    Android逆向基础-java基础入门_第4张图片

  • Java语言,源码文件是.java,而编译后的.class文件才是真正可以被JVM执行的字节码,所以我们的步骤都是先写.java文件,再编译成.class文件运行

  • 新建一个文件MD5Util.java测试MD5加密,有两种方式运行java文件,这里推荐代码中的Run按钮即可输出md5值,bin目录下会有.class文件;第二种方式是控制台输入javac -encoding UTF-8 MD5Util.java对文件进行编译在src目录下生成.class文件,然后输入java MD5Util即可输出md5值
    Android逆向基础-java基础入门_第5张图片

    import java.security.MessageDigest;
    import java.math.BigInteger;
    
    public class MD5Util {
        
        public static String md5(String str) {
            byte[] digest = null;
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                digest  = md.digest(str.getBytes("utf-8"));
                String md5Str = new BigInteger(1, digest).toString(16);  //16是表示转换为16进制数
                return md5Str;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        public static void main(String[] args){
            System.out.println(md5("1234"));
        }
    
    }
    

二、java代码基础知识扫盲了解

  • 推荐java视频
  • 推荐文档教程
1、类class
  • 一个文件里面可以有多个类,但是只能有一个公有的类(即public修饰的),公有的类名和文件名必须一致,一个类里面可以有很多方法,如图HelloWordHelloWord.java文件下唯一的用public修饰的公有类Android逆向基础-java基础入门_第6张图片

  • 一个文件里有多少个类,通过javac -encoding UTF-8 HelloWorld.java编译后就会生成相应个数的.class文件,而要运行单个类的话,就通过java class文件名来运行即可
    Android逆向基础-java基础入门_第7张图片

  • 每个单独的类要执行的入口,都是先寻找主函数main,所以主函数的写法是固定的,{}代表代码的开始和结束,语句结束都要加上分号; ,void代表返回类型为空

    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello World"); // 输出 Hello World
        }
    }
    

    Android逆向基础-java基础入门_第8张图片

  • 通过static关键字修饰的,叫静态属性,静态方法,静态属性调用方式是类名.属性名,静态方法的调用方式类名.方法名()
    Android逆向基础-java基础入门_第9张图片

  • 未通过static关键字修饰的统一称之为实例(对象)属性或方法,创建一个实例对象:XXclass obj = new XXclass(),实例属性,实例属性的调用方式,obj.属性名,实例调用方法obj.方法名()
    Android逆向基础-java基础入门_第10张图片

  • 类属性是唯一共有的,任何一个与之相连的都会随它一起改变,和列表引用的概念很相似;类直接调用的方式仅仅限于静态的属性和方法,每个实例对象的属性方法是独立的互不影响;这里建议直接看视频理解
    Android逆向基础-java基础入门_第11张图片

  • 构造器:构造器又称构造方法构造函数,构造器名和类名一致,无返回值;当对象创建时会自动调用构造器,进一步讲解看
    Android逆向基础-java基础入门_第12张图片

  • 类的继承,看这里介绍,extends关键字是单一继承类,implements关键字是多继承的特性
    Android逆向基础-java基础入门_第13张图片

  • 对父类的访问,看这里介绍,this关键字指向自己的引用,super关键字引用父类的
    Android逆向基础-java基础入门_第14张图片

  • final关键字,看这里介绍,使类不能被继承,是方法不能被子类重写
    Android逆向基础-java基础入门_第15张图片

2、导包依赖
  • 导包依赖管理:下载.jar包,比如搜索Commons Codec包然后下载下来
    Android逆向基础-java基础入门_第16张图片
    Android逆向基础-java基础入门_第17张图片
    Android逆向基础-java基础入门_第18张图片

  • 将下载下来的.jar包放在lib目录下,之后通过import的方式即可导入,如下图片代码是一个java爬虫案例并导入了相关的包
    Android逆向基础-java基础入门_第19张图片

  • 所谓的.jar包里面都是众多的.class文件打包在一起的;而settings如下的配置,表示我们要import某个包时,它会自动去lib目录下寻找相关包依赖
    Android逆向基础-java基础入门_第20张图片
    Android逆向基础-java基础入门_第21张图片

  • 一个文件DigestTest的类调用另一个文件DigestUtils的类方法

    import java.security.MessageDigest;  
    
    
    public class DigestUtils {
        public static String md5(String txt) {
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update(txt.getBytes("GBK"));
                StringBuffer buf = new StringBuffer();
                for (byte b : md.digest()) {
                    buf.append(String.format("%02x", b & 0xff));
                }
                return buf.toString();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        // public static void main(String[] args){
        //     System.out.println(md5("1234"));
        // }
    }
     
    
    import java.io.*;
    public class DigestTest{
     
       public static void main(String[] args){
            DigestUtils dig = new DigestUtils();  // 先实列化
            System.out.println(dig.md5("1234"));
    
       }
    }
    
3、定义变量
  • 变量的格式是:数据类型 变量名 = 初始化值,且必须初始化给个值,即三要素:类型、名称、值
  • 基本数据类型:8种,byte、short、int、long、float、double、boolean、char,其中char数据类型的字符是单引号,String类定义的是双引号
    // 四种整数类型
    byte a = 127;  // 1字节8bit位,最大值2^7-1,最小值-2^7
    short b = 32767; // 2字节16位,最大值2^15-1
    int c = 2147483647;  // 4字节32位
    long d = 9223372036854775807L; // 8字节64位
    // 两种浮点型
    float e = 234.5f; // 4字节32位
    double f = 12.9867;  // 8字节64位
    // 布尔型
    boolean g = true;
    // 字符型
    char h = '中';  // 2字节16位,类型是一个单一的16位Unicode字符,字符必须用单引号,且是单个字符,双引号代表字符串
    char i = 97; // char类型输出97对应的字符
    
  • 其它类型:String类、StringBuilder、数组等
    // String类
    String j = "abcd";
    // StringBuilder类
    StringBuilder k = new StringBuilder(10);
    k.append("shiyiyi");  // 字符串追加到此字符序列
    // 数组动态初始化
    int size = 10; // 数组大小
    double[] myList1 = new double[size]; 
    myList1[0] = 5.6;
    myList1[1] = 4.5;
    // 数组静态初始化
    int[] myList2 = new int[]{3, 1, 2, 6, 4, 2};
    int[] myList3 = {3, 1, 2, 6, 4, 2};
    double[] myList4 = {1.9, 2.9, 3.4, 3.5};
    String[] myList5 = {"23132", "fdaf"};
    
4、方法函数
  • 参考教程1,参考教程2,不管是调用方法,还是定义方法,与python不同的是,java必须明确指定类型,传参类型,返参类型
    Android逆向基础-java基础入门_第22张图片
    Android逆向基础-java基础入门_第23张图片

  • 方法重载:参考案例,重载(overloading) 是在一个类里面,方法名字相同,而参数不同,返回类型可以相同也可以不同
    Android逆向基础-java基础入门_第24张图片

三、apk_java层逆向小案例

  • 选择的是抓包工具fiddler安卓手机 或者可以试试模拟器,jadx反编译工具, 一些软件安装配置看这篇文章

  • 如图,案例:com.mylrc.mymusic,通过抓包发现sign是加密的,而这个sign类似md5
    Android逆向基础-java基础入门_第25张图片

  • 打开jadx反编译apk后,直接通过搜索定位sign加密代码处
    Android逆向基础-java基础入门_第26张图片

  • 通过如下的java代码行分析,sign = md5(搜索词+时间+wyy_search)
    在这里插入图片描述

  • 带着上面的猜想去测试,猜测正确
    Android逆向基础-java基础入门_第27张图片

  • 测试请求,成功返回
    Android逆向基础-java基础入门_第28张图片

  • 上面是看java代码直接就猜出sign的生成逻辑,下面我再通过hook的方法去验证以下明文和结果:

  • 第一步:已经root的手机与电脑通过usb连接,并开启frida服务,只有开启了frida服务才能进行frida hook

    adb shell
    su
    cd /data/local/tmp
    ./frida-server-15.1.14-android-arm64
    

    Android逆向基础-java基础入门_第29张图片

  • 第二步,分析代码编写frida-hook脚本,如图我们知道sign值是MD5加密得到的,所以我们要hook的类名就是com.mylrc.mymusic.tool.Utils,要hook的方法就是MD5,传入参数一个,返回参数一个
    在这里插入图片描述
    Android逆向基础-java基础入门_第30张图片

  • 第三步:编写脚本如下,输出明文,以及返回结果
    Android逆向基础-java基础入门_第31张图片

    function hook_java(){
        // 目的:hook 类名:com.mylrc.mymusic.tool.Utils 下的 MD5 方法,查看输入明文组成结构
        Java.perform(function(){
            var utils = Java.use("com.mylrc.mymusic.tool.Utils");
            console.log(utils)
            utils.MD5.implementation = function(key){
                console.log("Utils.MD5_key", key);
                var result = this.MD5(key);
                console.log("Utils.MD5_result", result);
                return result
            }
        })
    
    }
    
    setImmediate(hook_java)
    
  • 第四步:查看app的包名com.mylrc.mymusic,另开一个cmd窗口输入frida -U -l music_match.js --no-pause -f com.mylrc.mymusic,此时敲个回车,然后在手机端app上搜索,如图打印出hook的内容,明文周杰伦1646545254800wyy_search,确实和我们前面看java代码的明文组成是一样的,hook成功,第一个案例结束
    Android逆向基础-java基础入门_第32张图片
    Android逆向基础-java基础入门_第33张图片

  • 以上整个步骤用到的cmd命令如下

    # 一个cmd窗口先开frida服务
    adb shell
    su
    cd /data/local/tmp
    ./frida-server-15.1.14-android-arm64
    # 另开一个cmd窗口注入hook的js
    frida -U -l music_match_hook.js --no-pause -f com.mylrc.mymusic
    
  • 总结:frida hook 函数方法,确定类名,确定方法名,然后传参个数,然后按如下格式填写即可hook;setImmediate用于执行给定的function,当从控制台进行hook时会调用相关的function
    Android逆向基础-java基础入门_第34张图片

    function hook_java(){
        // 目的:hook 类名:xxxxxxxx 下的 kkkk 方法
        Java.perform(function(){
            var utils = Java.use("待填写的类名");
            utils.待填写的方法名.implementation = function(key){
                待编写的逻辑
            }
        })
    
    }
    setImmediate(hook_java)
    
  • 前面步骤的第三步和第四步也可以用python启动,代码如下
    Android逆向基础-java基础入门_第35张图片

四、java与frida的hook文章推荐

  • frida hook java
  • frida hook so
  • Java视频讲解
  • Java文档讲解
  • java类api

你可能感兴趣的:(SpiderCrawl,pytorch)