这个APP需要通过直接去输入卡号,通过卡号付费实现虚拟定位的操作,同时虚拟定位的功能是在java层的静态代码块中实现的,所以直接去HOOK掉对应的检测卡密的过程就可以了
分析:
JEB实现反编译过程,通过搜索字符串('登录'),发现可以直接去查看到对应的函数位置
public void run() {
if(local.mCount != null && local.syms != null) {
local.mCount = (long)(((long)local.mCount) + 1L);
if(((long)local.mCount) > ((long)local.syms)) {
if(!"dqgb".equals("dqgb")) {
return;
}
System.exit(0);
return;
}
local.djsdx.postDelayed(this, 1000L);
return;
}
local.djsdx.postDelayed(this, 1000L);
}
};
local.zx = new Runnable() {
@Override
public void run() {
local.message = new Message();
local.message.arg1 = 4;
local.strpost("name=apk_z&c1=10002&c2=&c4=&c6=1");
local.djsdx.postDelayed(this, ((long)(((int)local.xhjcfzs) * 60000)));
}
};
这里去复写了两个run()的执行函数,同时会去设置事件的同时,提交字符串
local.strpost("name=apk_z&c1=10002&c2=&c4=&c6=1");
这里是对应的strpost的函数实现,可以看到这里是有远程服务的网址的,其实可以考虑到是输入卡密的过程中,通过远程去实现卡密的检测,同时将这里的远程网址进行提交了之后会直接去判断,提交的网址进行local.load
!
这里load的代码我直接就copy到上面
public static void load(Context arg16) {
local.context = arg16;
local.jqm = local.getjqm();
local.uuid = local.getuuid();
local.ycuuid = local.getini("ycuuid.txt");
Long v0 = (long)System.currentTimeMillis();
AlertDialog v1 = local.dialog;
if(v1 != null) {
v1.dismiss();
local.dialog = null;
}
AlertDialog.Builder v1_1 = new AlertDialog.Builder(local.context);
v1_1.setTitle(local.title);
v1_1.setCancelable(false);
local.user = local.getini("card.txt");
EditText v4 = new EditText(local.context);
local.editText = v4;
v4.setText(local.user);
local.editText.setHint("请输入卡号...");
v1_1.setView(local.editText);
v1_1.setNegativeButton("解绑", null);
v1_1.setPositiveButton("登录", null);
v1_1.setNeutralButton("试用", null);
AlertDialog v2 = v1_1.create();
local.dialog = v2;
v2.setCanceledOnTouchOutside(false);
Long v2_1 = null;
String v4_1 = local.getini("logintime.txt");
if(!v4_1.isEmpty()) {
v2_1 = (long)(((long)v0) - ((long)(((long)Long.parseLong(v4_1)))));
}
if(!local.jcdlzt().booleanValue()) {
if(local.user.length() > 5) {
Message v3 = new Message();
local.message = v3;
v3.arg1 = 1;
local.message.arg2 = 2;
local.strpost("name=apk_login&c1=" + local.rjbh + "&c2=" + local.user + "&c4=" + local.bbh + "&c5=" + local.jqm);
return;
}
local.xsdlck();
local.handler.obtainMessage();
Message v6 = new Message();
local.message = v6;
v6.arg1 = 0;
local.strpost("name=apk_qr&c1=" + local.rjbh + "&c2=");
return;
}
if(((long)v2_1) > ((long)(((int)local.xhjcfzs) * 60 * 1000))) {
Message v3_1 = new Message();
local.message = v3_1;
v3_1.arg1 = 1;
local.message.arg2 = 2;
local.strpost("name=apk_login&c1=" + local.rjbh + "&c2=" + local.user + "&c4=" + local.bbh + "&c5=" + local.jqm);
}
}
// Detected as a lambda impl.
public static void openBrowser(Context arg4, String arg5) {
try {
Intent v0_1 = new Intent();
v0_1.setAction("android.intent.action.VIEW");
v0_1.setData(Uri.parse(arg5));
if(v0_1.resolveActivity(arg4.getPackageManager()) != null) {
v0_1.resolveActivity(arg4.getPackageManager());
arg4.startActivity(Intent.createChooser(v0_1, "请选择浏览器"));
return;
}
arg4.startActivity(v0_1);
}
catch(Exception v0) {
Toast.makeText(arg4.getApplicationContext(), "打开浏览器异常:" + v0.toString(), 0).show();
}
}
我们可以找到这里的对应的创建对话提示框的位置(输入卡号的位置)
AlertDialog.Builder v1_1 = new AlertDialog.Builder(local.context);
v1_1.setTitle(local.title);
v1_1.setCancelable(false);
local.user = local.getini("card.txt");
EditText v4 = new EditText(local.context);
local.editText = v4;
v4.setText(local.user);
local.editText.setHint("请输入卡号...");
v1_1.setView(local.editText);
v1_1.setNegativeButton("解绑", null);
v1_1.setPositiveButton("登录", null);
v1_1.setNeutralButton("试用", null);
AlertDialog v2 = v1_1.create();
local.dialog = v2;
v2.setCanceledOnTouchOutside(false);
Long v2_1 = null;
String v4_1 = local.getini("logintime.txt");
其实这里我们可以试试直接去HOOK这个load方法了,看看能不能不去创建这个对话框,直接进入程序
Java.perform(function()
{
var local = Java.use("yz.local");
local.load.implementation=function(){
console.log("----------------Hook--------------------");
return;
}
})
frida -U -f xu.ux.zheror -l demo.js
其实发现可以直接过检测了
或者python来实现frida
import frida
import sys
jsCode ="""
Java.perform(function()
{
var local = Java.use("yz.local");
local.load.implementation=function(){
console.log("----------------Hook--------------------");
return;
}
});
"""
def on_message(message,date):
print(message)
device = frida.get_usb_device()
app_name ='xu.nx.zheror'
pid = device.spawn([app_name])
process = device.attach(pid)
script = process.create_script(jsCode)
script.on('message',on_message)
script.load()
device.resume(pid)
sys.stdin.read()
这里一样是可以实现去检测的
重解包,硬改smali,重签名打包
搞完直接重打包,先解包
java -jar apktool.jar d app.apk
改smail代码
找到对应的yz.local的源码位置 具体的位置是在 apktool\suwukong\smali_classes9\yz\locla.smail 的smail代码
.method public static load(Landroid/content/Context;)V
.locals 16
return-void
.end method
把load里面全部删了,就留个返回
生成APK
java -jar apktool.jar b 对应的文件夹
重签名
keytool -genkey -v -keystore .\abc.keystore -alias new_name -keyalg RSA -keysize 2048 -validity 10000
输入密钥库口令:
您的名字与姓氏是什么?
[Unknown]: chen
您的组织单位名称是什么?
[Unknown]: chen
您的组织名称是什么?
[Unknown]: chen
您所在的城市或区域名称是什么?
[Unknown]: chen
您所在的省/市/自治区名称是什么?
[Unknown]: chen
该单位的双字母国家/地区代码是什么?
[Unknown]: chen
CN=chen, OU=chen, O=chen, L=chen, ST=chen, C=chen是否正确?
[否]: y
正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 10,000 天):
CN=chen, OU=chen, O=chen, L=chen, ST=chen, C=chen
输入 <new_name> 的密钥口令
(如果和密钥库口令相同, 按回车):
#这里有写对应的别名 new_name
#补上签名:
jarsigner -verbose -keystore .\abc.keystore -signedjar new.apk apktool\apktool\suwukong\dist\瀛欒鑰�.apk new_name
这里生成的APK就可以直接使用了
通过百度网盘分享的文件:孙行者.apk
链接:https://pan.baidu.com/s/1PH29tMyYuRPw4Ww_uQw0PQ?pwd=asdk
提取码:asdk
--来自百度网盘超级会员V4的分享