移动安全入门

移动安全入门

编写安卓程序

xml界面类似于web的界面 layout为布局,wrap_content为填充布局,表示填充满

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:gravity="center">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="用户名" />

            <EditText
                android:id="@+id/editTextTextPersonName"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:inputType="textPersonName"
                android:text="User" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="密码" />

            <EditText
                android:id="@+id/editTextTextPassword"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:ems="10"
                android:inputType="textPassword" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">


            <Button
                android:id="@+id/button"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="登陆" />

        </LinearLayout>

    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

登陆按钮监听代码

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
EditText Name;
EditText Pass;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Name = findViewById(R.id.editTextTextPersonName);
        Pass = findViewById(R.id.editTextTextPassword);
        Button Login = findViewById(R.id.button);
        Login.setOnClickListener(new View.OnClickListener() { //监听有没有点击按钮控件 如果点击了就会执行onClick函数
            @Override
            public void onClick(View view) {
                check(Name.getText().toString().trim(), Pass.getText().toString().trim()); //调用check函数
            }
        });
    }
    public void check(String name,String pass) //自定义函数check 这里用来检查用户名和密码是否是hfdcxy和1234
    {
        if(name.equals("hfdcxy")&&pass.equals("1234"))
        {
            Toast.makeText(MainActivity.this,"登录成功", Toast.LENGTH_SHORT).show();//弹框
        }
        else
            Toast.makeText(MainActivity.this,"登录失败", Toast.LENGTH_SHORT).show();//弹框
    }
}

课后作业

使用Intent来传递数据

登陆界面

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
EditText Name;
EditText Pass;
TextView test;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test=findViewById(R.id.textView4);
        //test.setText("123");
        Name = findViewById(R.id.editTextTextPersonName);
        Pass = findViewById(R.id.editTextTextPassword);
        Button Login = findViewById(R.id.button);
        Login.setOnClickListener(new View.OnClickListener() { //监听有没有点击按钮控件 如果点击了就会执行onClick函数
            @Override
            public void onClick(View view) {
                go_to();
            }
        });
    }
    public void go_to()
    {
        Intent intent=new Intent(MainActivity.this,MainActivity2.class);
        //intent = Intent(this,MineOrdersListActivity::class.java)
        intent.putExtra("show_name",Name.getText().toString());
        startActivity(intent);
    }
}

跳转界面

//import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity2 extends AppCompatActivity {
TextView Name1;
EditText Name2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        //final View rowView = inflater.inflate(R.layout.activity_main, null);
        Intent intent=getIntent();
        int i = intent.getIntExtra("show_name",0);
        String show_name=intent.getStringExtra("show_name");
        Name1=(TextView) findViewById(R.id.textView3);
       Name1.setText(show_name);
    }
}

破解安卓程序

(1)if-eqz vA, vB, :cond_**"   如果vA等于vB则跳转到:cond_**
(2)if-nez vA, vB, :cond_**"   如果vA不等于vB则跳转到:cond_**

回编译遇到错误apktools版本问题同时也可能存在frame_work框架问题

https://blog.csdn.net/Andrio/article/details/103887045

调试smali代码

版本Andriod4.1.2,和正常的调试方法不一样记录一下

Andriod studio 打开apk,此时出现的都是smali文件,并且提示需要附加java源代码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KrM632Ci-1618733777063)(https://raw.githubusercontent.com/p1aymaker/picture/master/20210122200619.png)]

利用命令得到java文件

jadx.bat -d java_source app.apk 

之后就可以对java文件下断点调试了

手机连接上之后,使其进入调试状态

adb shell pm list package
adb shell am start -D -n com.example.myapplication/com.example.myapplication.MainActivity 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L3Auhye0-1618733777066)(https://raw.githubusercontent.com/p1aymaker/picture/master/20210122201928.png)]

点击此即可开始调试java代码

smali代码中插入log

从int转string的log插入

 const-string v0, "\u8fd9\u4e2a\u503c\u662f"

  invoke-virtual {p0}, Lhfdcxy05/com/myapplication/MainActivity;->fun1()I

  move-result v1

    invoke-static {v1}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

string类型的log插入

    const-string v0, "\u8fd9\u4e2a\u503c\u662f"

    invoke-virtual {p0}, Lhfdcxy05/com/myapplication/MainActivity;->fun3()I

    move-result-object v1

    invoke-static {v0, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I

Andriod中编写第一个so

https://blog.csdn.net/luo_boke/article/details/107306531

参考文章

课后作业

package com.example.soprogram;

import androidx.appcompat.app.AppCompatActivity;
s
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        int a=10;
        int b=12;
        tv.setText(String.valueOf(add(a,b)));
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native int add(int a,int b);
}
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jint JNICALL
Java_com_example_soprogram_MainActivity_add(
        JNIEnv* env,
        jobject /* this */,
        jint a,
        jint b
        ) {
    return a+b;
}

javac已经替代了javah

要进到java目录下

javac -h . myJNI.java

IDA破解so

首先利用apktool进行解包

apktool d 解包。

apktool_2.5.0.jar  b -o new.apk app-debug 

打包完毕之后用Andriod Killer进行签名

但是有点奇怪的是加载的是armeabi-v7a目录下的lib

不过我的cpu是arm-v8的。。

1|equuleus:/ $ cat /proc/cpuinfo
Processor       : AArch64 Processor rev 12 (aarch64)
processor       : 0
BogoMIPS        : 38.40

IDA爆破签名验证

签名验证:通过验证签名是否改变来判断程序是否被破解

so里对外调用函数在IDA种也可以找到,可以通过此定位关键点

尝试通过导入jni.h来设置结构体增强.so代码可读性

BNE: 数据跳转指令,标志寄存器中Z标志位不等于零时, 跳转到BNE后标签处 xx D1
BEQ: 数据跳转指令,标志寄存器中Z标志位等于零时, 跳转到BEQ后标签处 xx D0

xx=相差指令*2+4

IDA动态破解验证登陆

AndroidManifest.xml查看程序入口 这里 android:debuggable="true"表示此apk可以动态调试

首先将andriod_server push到手机/data/local/tmp下

端口转发之后开始调试,发现只存在system/bin/sh文件原因是真机没root权限

需要用夜神模拟器连接,不过夜神模拟器架构为x86,因此需要android_x86_server,同时IDA attach要选择Remote Linux Debugger

首先连接夜神模拟器

adb connect 127.0.0.1:62001

关闭Andriod_server

kill -9 pid

端口转发

adb forward tcp:23946 tcp:23946

静态分析反调试

dalvik是执行的时候编译+运行,安装比较快,开启应用比较慢,应用占用空间小
ART是安装的时候就编译好了,执行的时候直接就可以运行的,安装慢,开启应用快,占用空间大
fd文件描述符
  • 端口23946检测
  • 进程遍历检测
  • 父进程检测是否包含zygote
  • 自身进程名检测,是否为com.xxx的格式
  • 线程数量检测,一般有十几个线程,如果自己加载就一个
  • /proc/pid/fd/检测文件数量
  • 信号处理机制,IDA会截获信号
  • tracepid:调试该进程的pid
  • 自带API反调试
  • ptrace自身看是否成功
  • hash检测
  • BKPT指令查询
  • 读取进程的status或stat来检测tracepid,TracePid字段就是跟踪进程的pid.调试状态下tracepid不为0
  • 单步调试陷阱,有点像Windows下的Debugger Blocker
  • 花指令
  • 时间差检测
  • 进程信息查询
第一种:
/proc/pid/status
/proc/pid/task/pid/status
TracerPid非0
statue字段中写入t(tracing stop)
第二种:
/proc/pid/stat
/proc/pid/task/pid/stat
第二个字段是t(T)
第三种:
/proc/pid/wchan
/proc/pid/task/pid/wchan
ptrace_stop
  • 可以通过Inotify系列api来监控mem或pagemap的打开或访问事件, 一旦发生时间就结束进程来阻止dump。

没有找到关键函数名称可能是由于JNI_OnLoad来动态注册

找到JNI_OnLoad函数,导入头文件结构体

此时可以看到一处反调试为遍历进程反调试

动态注册函数在.data.rel.ro.local 区段中

找到一处端口检测反调试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uOuBInfB-1618733777075)(https://raw.githubusercontent.com/p1aymaker/picture/master/20210128025853.png)]

再看下.init_array创建了一个线程,线程功能如下

同样是一处反调试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sRLCGB5q-1618733777076)(https://raw.githubusercontent.com/p1aymaker/picture/master/20210128030158.png)]

xpose模块

参考:

https://www.kancloud.cn/a6260362/study-android-and-web/1646986

分别用不同版本来进行Hook

Android 4.0.3-4.4:Dalvik
Android 5.0以上:ART

其中踩了一个坑load moudle出了问题导致Hook失败

https://blog.csdn.net/OneT1me/article/details/93968206

需要将gradle中的东西给注释掉

  // implementation files('libs\\api-82.jar')
    compileOnly 'de.robv.android.xposed:api:82'
    compileOnly 'de.robv.android.xposed:api:82:sources'
  • 编译:javac HelloWorld.java
  • 打包:一个包内的所有class文件打包为一个jar文件

conpileonly:只在编译时有效,不会参与打包

implementation:依赖的库将会参与编译和打包,该依赖方式所依赖的库不会传递,只会在当前module中生效

public class HookMain implements IXposedHookLoadPackage {
    public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {
         //固定格式
        findAndHookMethod(
                "android.telephony.TelephonyManager",  //要hook的包名+类名
                lpparam.classLoader,                   //classLoader固定
                "getDeviceId",                         //要hook的方法名
                                                       //方法参数 没有就不填
                new XC_MethodHook() {
                    @Override
                    //方法执行前执行
                    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    }
                    //方法执行后执行,改方法的返回值一定要在方法执行完毕后更改
                    protected void afterHookedMethod(MethodHookParam param)
                            throws Throwable {
                        param.setResult("355888888888888");
 
                    }
                }
        );
 
 
    }
}

一般是先运行程序,再加载Xposed模块

游戏进行Hook

import android.content.Context;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.XposedHelpers;

public class HookMain implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        // XposedBridge.log("=========Loaded app: " + lpparam.packageName);
        if (lpparam.packageName.equals("com.jimmy.beauty.pick")) {
            XposedHelpers.findAndHookMethod("com.jimmy.beauty.pick.Util", lpparam.classLoader, "getMoney",
                    Context.class,
                    XC_MethodReplacement.returnConstant(100));
        }
    }
}

Xposed原理

Android进程的父进程——Zygote(孵化)进程,该进程的启动配置在/init.rc脚本中,而Zygote进程对应的执行文件是/system/bin/app_process

用自己实现的app_process替换掉了系统原本提供的app_process**,加载一个额外的jar包,然后入口从原来的com.android.internal.osZygoteInit.main()被替换成了de.robv.android.xposed.XposedBridge.main()

检测

https://tech.meituan.com/2018/02/02/android-anti-hooking.html

  • PackageManager的API来遍历系统中App的安装情况来辨别是否有安装Xposed Installer相关的软件包
  • 自造异常读取栈检测是否存在Xposed调用方法
  • java方法有没有变为Native JNI方法
  • XposedHelper
  • "/proc/self/maps"检测
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值