修改android framework关掉app签名检查

https://android.googlesource.com/platform/frameworks/base/+/ccbf84f/services/java/com/android/server/pm/PackageManagerService.java

检查两个包的签名

    public int checkSignatures(String pkg1, String pkg2) {
        synchronized (mPackages) {
            final PackageParser.Package p1 = mPackages.get(pkg1);
            final PackageParser.Package p2 = mPackages.get(pkg2);
            if (p1 == null || p1.mExtras == null
                    || p2 == null || p2.mExtras == null) {
                return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
            }
            return compareSignatures(p1.mSignatures, p2.mSignatures);
        }
    }

如果是我们想豁免的包, 就不检查

   
public int checkUidSignatures(int uid1, int uid2) {
        // Map to base uids.
        uid1 = UserHandle.getAppId(uid1);
        uid2 = UserHandle.getAppId(uid2);
....
        return compareSignatures(s1, s2);
        }
    }

检查签名

    static int compareSignatures(Signature[] s1, Signature[] s2) {
        if (s1 == null) {
            return s2 == null
                    ? PackageManager.SIGNATURE_NEITHER_SIGNED
                    : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
        }
        if (s2 == null) {
            return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
        }
        HashSet set1 = new HashSet();
        for (Signature sig : s1) {
            set1.add(sig);
        }
        HashSet set2 = new HashSet();
        for (Signature sig : s2) {
            set2.add(sig);
        }
        // Make sure s2 contains all signatures in s1.
        if (set1.equals(set2)) {
            return PackageManager.SIGNATURE_MATCH;
        }
        return PackageManager.SIGNATURE_NO_MATCH;
    }

如果需要用Frida进行Hook , 请参考

Magsik模块开发

基础知识

脚本

在Magisk中,你可以在系统启动过程中下面两种模式运行脚本

post-fs-data模式: 阻塞式,启动过程等待执行完成或者执行时间超过10秒.

    好处是在Zygote开启之前就执行

     坏处是:执行有10秒的时间限制,会阻塞启动过程

late_start 服务模式:

   非阻塞式, 启动过程中,脚本并行运行

    好处: 没有时间限制,不会阻塞启动过程

    坏处: 脚本不像post-fs-data模式那样执行得早

脚本又分为两种类型

通用类型: 

   放在 $SECUre_DIR/post-fs-data.d 目录或者 $SECURE_DIR/service.d

脚本文件必须加上可执行权限( chmod +x)

放在 post-fs-data.d 目录下的脚本以 post-fs-data模式运行

   放在 seervice.d 目录下的脚本 以 late_start 模式运行

    将Magisk设置为 Core-Only模式时, 这些脚本也会执行

模块脚本:

    放在模块自己的目录

     只有模块启用时,才会执行

    post-fs-data.sh 运行在 post-fs-data模式

    service.sh 运行在 late_start 服务模式

    Magisk设置为Core-Only模式时, 这些脚本不会执行

注意: 所有的post-fs-data脚本和Magic Mount共享那10秒钟, 

  如果脚本脚本耗时过多, 可能会影响Magic Mount的效果

Frida gadget config

Frida gadget 试图载入一个同名的config文件

https://github.com/frida/frida-core/pull/156

https://github.com/frida/frida-core/blob/master/lib/gadget/gadget.vala

https://www.frida.re/docs/gadget/

简而言之,可执行文件格式包含了链接在可执行文件上的库。我们可以使用lddreadelf(Unix)列出这些库,或者是使用elf_reader.py

载入器会遍历这些库,并把它们映射到进程到的内存空间中去,并在加载之后调用它的构造方法。

添加frida-agent.so作为APK的native库的依赖。

import lief
 
libnative = lief.parse("libandroid.so")
libnative.add_library("libgadget.so") # Injection!
libnative.write("libgadget.so")
配置Frida Gadget

根据文档我们可以知道,Frida Gadgets可以使用配置文件作为参数来进行交互。

  • Listing:交互和frida-server一样
  • Script:使用配置文件中指定的JS脚本进行交互
  • ScriptDirectory:和Script一样,但可以指定多个应用和多个脚本
    Listing交互方式需要android.permission.INTERNET权限。我们可以通过修改manifest文件添加这个权限。不过,如果我们使用的是Script这种交互方式就不需要这一权限。

你能跟Gadget 取任意的文件名,因为有些app会检测自己加载的库里是否有frida字样

config是一个json文件:

interaction   描述交互方式, 默认值是 Listen

teardown 当library卸载时,是minmal还是full. 默认是minimal, 退出时不释放内部线程和内存,以及OS资源

runtime  值可谓 jit 或者 interpreter(默认)

code_signing 仅在iOS平台有意义

Listen模式,如同frida-server那样,gadget监听在localhost:27042

Scripting

{
  "interaction": {
    "type": "script",
    "path": "/home/oleavr/explore.js"
  }
}

参考文章:

https://lief.quarkslab.com/doc/latest/tutorials/09_frida_lief.html

译文:

https://bbs.pediy.com/thread-229970.htm

编译PixelExperience

https://github.com/PixelExperience-Devices/kernel_xiaomi_whyred
https://github.com/PixelExperience-Devices/device_xiaomi_whyred
https://github.com/PixelExperience-Devices/vendor_xiaomi_whyred

下载

repo init -u https://github.com/PixelExperience/manifest -b pie
repo sync -c -j$(nproc --all) --force-sync --no-clone-bundle --no-tags

编译

. build/envsetup.sh
lunch aosp_whyred-userdebug
mka bacon -j$(nproc --all)

设备

Dependency already present in manifest: vendor_xiaomi => vendor/xiaomi
Dependency already present in manifest: kernel_xiaomi_whyred => kernel/xiaomi/whyred
Dependency already present in manifest: LineageOS/android_packages_resources_devicesettings => packages/resources/devicesettings
Dependency already present in manifest: vendor_MiuiCamera => vendor/MiuiCamera

vendor/xiaomi/whyred 来自  https://github.com/PixelExperience-Devices/vendor_xiaomi_whyred

kernel/xiaomi/whyred 来自  https://github.com/PixelExperience-Devices/kernel_xiaomi_whyred

device/xiaomi/whyred 来自  https://github.com/PixelExperience-Devices/device_xiaomi_whyred

编译xposed

准备开发环境
aosp环境
参考 定制Android

perl环境
libconfig-inifiles-perl  (Config::IniFiles)
libfile-readbackwards-perl (File::ReadBackwards)
libfile-tail-perl     (File::Tail)
libarchive-zip-perl (Archive::Zip)

从文本中批量删除目录

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys
import shutil

with open('del.txt') as f:
    for line in f.readlines():
        w = line[:-1]
        print(w)
        shutil.rmtree(w + '.avd')
        os.remove(w + '.ini')

———————————
从文本文件中找到要删除的
——————————–

检测xposed的几种思路

一.调用xposed的API 1. XposedBridge.log(“sth”); 2. 加载XposedHelpers
ClassLoader.getSystemClassLoader().loadClass("de.robv.android.xposed.XposedHelpers");
3.检查XposedHelper的成员fieldCache,methodCache,constructorCache 二.检查xposed的文件 1.检查安装的包 2.检查 /system/lib 是否有 xposed文件     /system/lib/libxposed_art.so     /system/lib64/libxposed_art.so 3. 检查  XposedBridge.jar 文件 三.检查调用栈
try {
            throw new Exception();
}
 catch(Exception e) {
        StackTraceElement[] st = e.getStackTrace();
}
是否含有 de.robv.android.xposed.XposedBridge 之类的 检查 com.android.internal.os.ZygoteInit 是否出现了两次 并检查 Throwable.class.getDeclaredMethod(“getStackTrace” 是否为Native方法 四.检查环境变量 
System.getenv("CLASSPATH").contains("XposedBridge")
CLSAAPATH=/system/framework/XposdedBridge.jar 五.检查 /proc/self/maps

批量建立符号链接

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import sys

if len(sys.argv) != 3:
    exit("i need 2 args")

src_path = os.path.abspath(sys.argv[1])
dst_path = os.path.abspath(sys.argv[2])


files = [f for f in os.listdir(src_path) ] #if os.path.isfile(f)
for f in files:
    sss = src_path + '/' + f
    ddd = dst_path + '/' + f
    os.symlink(sss, ddd)

python3批量建立符号链接
用法:
link.py . /dev/shm

国美Fenmmy Note解锁bootloader

型号: 2018X38A
芯片: P23 (MT6763)

首先,在设置里打开允许oem解锁

进入bootloader模式

adb reboot bootloader

运行解锁命令

fastboot oem unlock

按照屏幕提示, 按一下 音量加

然后查一下解锁状态

$ fastboot getvar all
(bootloader) 	max-download-size: 0x8000000
(bootloader) 	partition-size:flashinfo: 1000000
(bootloader) 	partition-type:flashinfo: raw data
(bootloader) 	partition-size:userdata: 32000000
(bootloader) 	partition-type:userdata: ext4
(bootloader) 	partition-size:cache: 1b000000
(bootloader) 	partition-type:cache: ext4
(bootloader) 	partition-size:system: c0000000
(bootloader) 	partition-type:system: ext4
(bootloader) 	partition-size:vendor: 7d000000
(bootloader) 	partition-type:vendor: raw data
(bootloader) 	partition-size:tee2: 900000
(bootloader) 	partition-type:tee2: raw data
(bootloader) 	partition-size:tee1: 500000
(bootloader) 	partition-type:tee1: raw data
(bootloader) 	partition-size:odmdtbo: 1000000
(bootloader) 	partition-type:odmdtbo: raw data
(bootloader) 	partition-size:logo: 800000
(bootloader) 	partition-type:logo: raw data
(bootloader) 	partition-size:boot: 2000000
(bootloader) 	partition-type:boot: raw data
(bootloader) 	partition-size:lk2: 100000
(bootloader) 	partition-type:lk2: raw data
(bootloader) 	partition-size:lk: 100000
(bootloader) 	partition-type:lk: raw data
(bootloader) 	partition-size:nvram: 4000000
(bootloader) 	partition-type:nvram: raw data
(bootloader) 	partition-size:gz2: 1000000
(bootloader) 	partition-type:gz2: raw data
(bootloader) 	partition-size:gz1: 1000000
(bootloader) 	partition-type:gz1: raw data
(bootloader) 	partition-size:sspm_2: 100000
(bootloader) 	partition-type:sspm_2: raw data
(bootloader) 	partition-size:sspm_1: 100000
(bootloader) 	partition-type:sspm_1: raw data
(bootloader) 	partition-size:spmfw: 100000
(bootloader) 	partition-type:spmfw: raw data
(bootloader) 	partition-size:md1dsp: 1000000
(bootloader) 	partition-type:md1dsp: raw data
(bootloader) 	partition-size:md1img: 4000000
(bootloader) 	partition-type:md1img: raw data
(bootloader) 	partition-size:proinfo: 300000
(bootloader) 	partition-type:proinfo: raw data
(bootloader) 	partition-size:sec1: 200000
(bootloader) 	partition-type:sec1: raw data
(bootloader) 	partition-size:seccfg: 800000
(bootloader) 	partition-type:seccfg: raw data
(bootloader) 	partition-size:protect2: 978000
(bootloader) 	partition-type:protect2: ext4
(bootloader) 	partition-size:protect1: 800000
(bootloader) 	partition-type:protect1: ext4
(bootloader) 	partition-size:metadata: 2000000
(bootloader) 	partition-type:metadata: raw data
(bootloader) 	partition-size:nvdata: 4000000
(bootloader) 	partition-type:nvdata: ext4
(bootloader) 	partition-size:nvcfg: 2000000
(bootloader) 	partition-type:nvcfg: ext4
(bootloader) 	partition-size:frp: 100000
(bootloader) 	partition-type:frp: raw data
(bootloader) 	partition-size:expdb: 1400000
(bootloader) 	partition-type:expdb: raw data
(bootloader) 	partition-size:para: 80000
(bootloader) 	partition-type:para: raw data
(bootloader) 	partition-size:recovery: 2000000
(bootloader) 	partition-type:recovery: raw data
(bootloader) 	partition-size:boot_para: 100000
(bootloader) 	partition-type:boot_para: raw data
(bootloader) 	partition-size:preloader: 40000
(bootloader) 	partition-type:preloader: raw data
(bootloader) 	off-mode-charge: 1
(bootloader) 	warranty: no
(bootloader) 	unlocked: yes
(bootloader) 	secure: no
(bootloader) 	kernel: lk
(bootloader) 	product: GM18A
(bootloader) 	version-preloader: 
(bootloader) 	version: 0.5

brotli压缩的卡刷包提取

用Google的brotli解压缩

brotli -d system.new.dat.br -o system.new.dat

sda2img转化

sdat2img.py system.transfer.list system.new.dat system.ext4.img

然后mount

mount -t ext4 system.ext4.img /mnt/system

进 /mnt/system 就可以看到文件了