GKLBB

当你经历了暴风雨,你也就成为了暴风雨

导航

应用安全 --- apk加固 之 防止截屏

package com.iran.SmaliHelper;

import android.app.Activity;
import android.app.Application;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.Window;
import java.util.Objects;

public class com.gklbb extends ContentProvider implements Application.ActivityLifecycleCallbacks {
   
    public com.gklbb() {
        super();
    }
   
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }
   
    @Override
    public String getType(Uri uri) {
        return null;
    }
   
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }
   
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        Window window = activity.getWindow();
        window.setFlags(0x2000, 0x2000); // FLAG_SECURE
    }
   
    @Override
    public void onActivityDestroyed(Activity activity) {
        // Empty implementation
    }
   
    @Override
    public void onActivityPaused(Activity activity) {
        // Empty implementation
    }
   
    @Override
    public void onActivityResumed(Activity activity) {
        // Empty implementation
    }
   
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        // Empty implementation
    }
   
    @Override
    public void onActivityStarted(Activity activity) {
        Window window = activity.getWindow();
        window.setFlags(0x2000, 0x2000); // FLAG_SECURE
    }
   
    @Override
    public void onActivityStopped(Activity activity) {
        // Empty implementation
    }
   
    @Override
    public boolean onCreate() {
        Context context = Objects.requireNonNull(getContext());
        Application application = (Application) context.getApplicationContext();
        application.registerActivityLifecycleCallbacks(this);
        return false;
    }
   
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                       String[] selectionArgs, String sortOrder) {
        return null;
    }
   
    @Override
    public int update(Uri uri, ContentValues values, String selection,
                     String[] selectionArgs) {
        return 0;
    }
}

 

对抗

(const(.*) ([pv]\d+), 0x.*)\s*(invoke-*.* \{([pv]\d+), ([pv]\d+), ([pv]\d+)\}, Landroid/view/Window;->setFlags\(II\)V)

替换
const$2 $3, 0x0

$4

逐个部分解释


1. (const(.*) ([pv]\d+), 0x.*)


作用:匹配const指令行


  • const - 匹配字面量"const"

  • (.*) - 组2:匹配const操作符的后缀

    • 如:/16/high16/4/wide

    • 示例:const/16const/high16

  • ([pv]\d+) - 组3:匹配寄存器名

    • [pv] - 匹配p或v

    • \d+ - 匹配一个或多个数字

    • 示例:v0p1v15

  • , 0x.* - 匹配十六进制数值

    • 0x - 十六进制前缀

    • .* - 匹配任意十六进制数字

    • 示例:, 0x1000, 0x80000


2. \s*


作用:匹配空白字符


  • 匹配零个或多个空白字符(空格、制表符、换行符等)

  • 用于连接const指令和invoke指令


3. (invoke-*.* \{([pv]\d+), ([pv]\d+), ([pv]\d+)\}, Landroid/view/Window;->setFlags\(II\)V)


作用:匹配invoke指令行


  • invoke- - 匹配字面量"invoke-"

  • *.* - 匹配方法调用类型

    • 如:virtualdirectstaticinterface

    • 示例:invoke-virtualinvoke-direct

  • \{([pv]\d+), ([pv]\d+), ([pv]\d+)\} - 匹配寄存器列表

    • 组5:第一个寄存器 - Window对象实例

    • 组6:第二个寄存器 - flags参数

    • 组7:第三个寄存器 - mask参数

  • , Landroid/view/Window;->setFlags\(II\)V - 匹配方法签名

    • Landroid/view/Window; - Window类的完整路径

    • ->setFlags - 方法名

    • (II)V - 方法参数和返回类型(两个int参数,void返回)


完整匹配示例


匹配的代码:


text
const/16 v0, 0x1000
invoke-virtual {v1, v0, v2}, Landroid/view/Window;->setFlags(II)V

各组捕获的内容:


  • 组1: const/16 v0, 0x1000 (整个const指令)

  • 组2: /16 (const操作符后缀)

  • 组3: v0 (寄存器名)

  • 组4: invoke-virtual {v1, v0, v2}, Landroid/view/Window;->setFlags(II)V (整个invoke指令)

  • 组5: v1 (Window对象实例)

  • 组6: v0 (flags参数)

  • 组7: v2 (mask参数)


替换操作


const$2 $3, 0x0 会将const指令的值改为0,从而在setFlags调用时传入0作为flags参数,达到清除所有窗口标志的效果。

 


(invoke-*.* \{([pv]\d+), ([pv]\d+)\}, Landroid/view/Window;->addFlags\(I\)V)替换 #$0
 
 

好的,我来解释这个替换操作:

正则表达式解释

(invoke-*.* \{([pv]\d+), ([pv]\d+)\}, Landroid/view/Window;->addFlags\(I\)V)

作用:匹配Window.addFlags(I)方法调用

  • invoke- - 匹配方法调用指令的开头

  • *.* - 匹配调用类型(如virtualdirect等)

  • \{([pv]\d+), ([pv]\d+)\} - 匹配两个寄存器

    • 组2:第一个寄存器 - Window对象实例

    • 组3:第二个寄存器 - flags参数(要添加的标志)

  • , Landroid/view/Window;->addFlags\(I\)V - 匹配方法签名

    • 单参数方法,用于向窗口添加标志

替换操作解释

#$0

作用:注释掉整行invoke指令

  • # - 在Smali中表示注释符号

  • $0 - 引用整个匹配的文本(即整个invoke指令)

实际效果示例

原始代码:

smali
invoke-virtual {v1, v0}, Landroid/view/Window;->addFlags(I)V

替换后:

smali
#invoke-virtual {v1, v0}, Landroid/view/Window;->addFlags(I)V

功能意义

这个替换操作会:

  1. 禁用addFlags调用:通过注释掉该方法调用

  2. 阻止添加窗口标志:原本要添加到窗口的任何标志(如全屏、沉浸模式等)都不会被设置

  3. 保持代码结构完整:只是注释掉,不会删除代码,便于后续调试或恢复

常见addFlags用途

addFlags(I)方法通常用于添加以下窗口标志:

  • FLAG_FULLSCREEN - 全屏模式

  • FLAG_KEEP_SCREEN_ON - 保持屏幕常亮

  • FLAG_SECURE - 防止截屏

  • FLAG_LAYOUT_NO_LIMITS - 布局无限制

  • FLAG_TRANSLUCENT_STATUS - 透明状态栏

通过注释掉这个调用,这些功能效果都会被禁用。

 
 
 

使用场景

  • 用第一个操作:当你想要清除所有窗口标志时

  • 用第二个操作:当你想要阻止添加特定标志时

两者可以结合使用,实现完全禁用窗口特殊效果的目的。

 
 

 

posted on 2025-09-08 07:43  GKLBB  阅读(7)  评论(0)    收藏  举报