包名:com.fock.lock
MD5值:0c298c0f5a8847753dd6d352d7a30be8
文件大小:936.80 KB
来源:某三楼
用到的工具
- 模拟器+Xposed
- android studio(看日志和运算结果)
- jeb或者任何可以反编译apk工具
入口分析
- 从 AndroidManifest.xml 分析入口以及服务 主启动页面是 MainActivity 进去看看
<application
android:allowBackup="true"
android:debuggable="true"
android:icon="@drawable/MT_Bin"
android:label="@string/MT_Bin"
android:theme="@style/MT_Bin">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:enabled="true" android:exported="true" android:name=".MyService"/>
<receiver android:exported="true" android:name=".AutoBroadcast">
<intent-filter android:priority="2147483647">
<action android:name="com.fock.lock.js"/>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
<action android:name="android.intent.action.DATA_ACTIVITY"/>
<action android:name="android.intent.action.DATA_STATE"/>
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.server.checkin.FOTA_CANCEL"/>
<action android:name="android.intent.action.MEDIABUTTON"/>
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_STARTED"/>
<action android:name="android.intent.action.MEDIA_SCANNER_FINISHED"/>
<action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.TIME_TICK"/>
<action android:name="android.intent.action.UMS_CONNECTED"/>
<action android:name="android.intent.action.WALLPAPER_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.SCREEN_OFF"/>
<action android:name="android.intent.action.SCREEN_ON"/>
<action android:name="android.intent.action.SERVICE_STATE"/>
<action android:name="android.intent.action.SIG_STR"/>
<action android:name="android.intent.category.ALTERNATIVE"/>
<action android:name="android.intent.action.SETTINGS"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"/>
<action android:name="android.net.wifi.STATE_CHANGE"/>
<action android:name="android.intent.action.REBOOT"/>
<action android:name="android.intent.action.USER_PRESENT"/>
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</receiver>
</application>
- MainActivity 里面就启动一个服务,到 MyService 这个服务里面看看
public class MainActivity extends Activity {
@Override // android.app.Activity
protected void onCreate(Bundle bundle0) {
LogCatBroadcaster.start(this);
super.onCreate(bundle0);
this.startService(new Intent(this, MyService.class));
}
@Override // android.app.Activity
protected void onDestroy() {
super.onDestroy();
}
}
- MyService 的 onCreate 函数 执行了 L 方法,发现这个就是第一层的代码
@Override // android.app.Service
public void onCreate() {
super.onCreate();
this.fv = new FloatView(this.getApplicationContext());
this.L();
}
第一层分析
-
先看初始化了哪些东西
-
到点击事件分析,发现解锁算法用到了两个参数
@Override // android.view.View$OnClickListener
public void onClick(View view0) {
if(MyService.this.lp.getText().toString().trim().length() == 0) {
return;
}
// 解锁算法
if(MyService.this.lp.getText().toString().equals("" + (MyService.this.ck / this.val$Admin ^ MyService.sb(Integer.parseInt(this.val$清))))) {
MyService.this.fv.removeView();
MyService.this.Z();
return;
}
MyService.this.密码错误.setVisibility(0);
MyService.this.密码错误.setText("密码错误联系半支烟QQxxxxxxxx解锁");
Runnable runnable0 = MyService.this.runn;
MyService.this.hand.postDelayed(runnable0, 2000L);
}
- 使用 YukiHookAPI(Xposed) Hook 获取关键参数
// 类名
findClass("com.fock.lock.MyService\$100000012").hook {
injectMember {
method {
// 方法名
name = "onClick"
// 参数
param(ViewClass)
// 返回值
returnType = UnitType
}
// 方法执行后
afterHook {
// 反射获取
val admin = instance.getParam<Int>("val\$Admin")
val 清 = instance.getParam<String>("val\$清")
打印结果
loggerE(msg = "admin: $admin\n清: $清")
}
}
}
// Kotlin 写法
private fun 第一层() {
// 识别码
val ck = 56983
// 参数1
val arg1 = 14
// 参数2
val arg2 = sb(7)
// 识别码 除以 参数1 异或运算 参数2
val pass = ck / arg1 xor arg2
"第一层密码: $pass".logd()
}
第二层分析
@Override // android.view.View$OnClickListener
public void onClick(View view0) {
int v15;
int[][] arr2_v = {new int[]{4, 6, 8, 10, 13, 16, 17, 18, 21, 23, 27, 29, 0x1F, 33, 41, 45, 52, 54, 56, 61, 67, 69, 71, 73, 74, 76, 78, 80, 82, 84, 85, 86}};
int[][] arr2_v1 = new int[arr2_v[0].length][arr2_v.length];
int v;
for(v = 0; v < arr2_v.length; ++v) {
int v1;
for(v1 = 0; v1 < arr2_v[0].length; ++v1) {
arr2_v1[v1][v] = arr2_v[v][v1];
}
}
int[][] arr2_v2 = {new int[]{14, 16, 18, 19, 23, 24, 28, 29, 0x1F, 35, 37, 39, 41, 43, 0x2F, 0x30, 49, 51, 53, 57, 59, 62, 0x40, 66, 69, 73, 76, 0x4F, 81, 83, 85, 87, 0x6F, 0x83, 0x9C}};
int[][] arr2_v3 = new int[arr2_v2[0].length][arr2_v2.length];
int v2;
for(v2 = 0; v2 < arr2_v2.length; ++v2) {
int v3;
for(v3 = 0; v3 < arr2_v2[0].length; ++v3) {
arr2_v3[v3][v2] = arr2_v2[v2][v3];
}
}
int v4;
for(v4 = 0; v4 < arr2_v1.length; ++v4) {
int v5 = MyService.this.b + arr2_v1[MyService.this.b][MyService.this.b];
MyService.this.c = v5;
int v6;
for(v6 = 0; v6 < arr2_v3[arr2_v1[MyService.this.b][MyService.this.b]][MyService.this.b]; ++v6) {
int v7 = MyService.this.d + arr2_v1[MyService.this.b][MyService.this.b] + arr2_v3[arr2_v3[MyService.this.b][MyService.this.b]][MyService.this.b];
MyService.this.d = v7;
}
}
int v8 = 2 * MyService.this.po1;
int v9 = MyService.this.a;
int v10 = 11 + 4 * MyService.this.b + v9;
int v11 = MyService.this.a * 6 ^ v10;
int v12 = MyService.this.po1 - v8 + v11;
MyService.this.po2 = v12;
int v13 = MyService.this.po2;
int v14 = MyService.this.b;
if(MyService.this.po1 >= v14 + arr2_v3[MyService.this.b][MyService.this.b]) {
v15 = MyService.sb(MyService.this.po2);
}
else {
int v16 = MyService.this.c;
int v17 = 5 + 2 * MyService.this.po2 + v16;
v15 = MyService.this.po2 ^ v17;
}
int v18 = v13 + v15 + MyService.this.a ^ 25 >> MyService.sb(20 - MyService.this.b >> 99);
int v19 = Integer.parseInt("" + (MyService.this.cl ^ MyService.sb(16 * v18 ^ 3))) / 999;
if(MyService.this.lp.getText().toString().equals("" + (v19 * 2 ^ MyService.this.cl))) {
MyService.this.fv.removeView();
MyService.this.X();
}
}
- 先使用 Xposed Hook 反射获取用到 MyService 里面的几个参数
// 同上
findClass("com.fock.lock.MyService\$100000024").hook {
injectMember {
method {
name = "onClick"
param(ViewClass)
returnType = UnitType
}
afterHook {
val myService = instance.getParam<Any>("this\$0")
myService?.let {
val a = it.getParam<Int>("a")
val b = it.getParam<Int>("b")
val c = it.getParam<Int>("c")
val d = it.getParam<Int>("d")
val cl = it.getParam<Int>("cl")
val po1 = it.getParam<Int>("po1")
val po2 = it.getParam<Int>("po2")
loggerE(msg = "a: $a\nb: $b\nc: $c\nd: $d\ncl: $cl\npo1: $po1\npo2: $po2")
}
}
}
}
public class IntArray {
public static int[][] arr2_v = {new int[]{4, 6, 8, 10, 13, 16, 17, 18, 21, 23, 27, 29, 0x1F, 33, 41, 45, 52, 54, 56, 61, 67, 69, 71, 73, 74, 76, 78, 80, 82, 84, 85, 86}};
public static int[][] arr2_v1 = new int[arr2_v[0].length][arr2_v.length];
public static int[][] arr2_v2 = {new int[]{14, 16, 18, 19, 23, 24, 28, 29, 0x1F, 35, 37, 39, 41, 43, 0x2F, 0x30, 49, 51, 53, 57, 59, 62, 0x40, 66, 69, 73, 76, 0x4F, 81, 83, 85, 87, 0x6F, 0x83, 0x9C}};
public static int[][] arr2_v3 = new int[arr2_v2[0].length][arr2_v2.length];
static int d = 37536;
private static final int po1 = 0;
private static final int a = 0;
private static int po2 = 0;
private static int c = 4;
static {
int v;
for (v = 0; v < arr2_v.length; ++v) {
int v1;
for (v1 = 0; v1 < arr2_v[0].length; ++v1) {
arr2_v1[v1][v] = arr2_v[v][v1];
}
}
int v2;
for (v2 = 0; v2 < arr2_v2.length; ++v2) {
int v3;
for (v3 = 0; v3 < arr2_v2[0].length; ++v3) {
arr2_v3[v3][v2] = arr2_v2[v2][v3];
}
}
int v4;
for (v4 = 0; v4 < arr2_v1.length; ++v4) {
int v5 = 0 + arr2_v1[0][0];
c = v5;
int v6;
for (v6 = 0; v6 < arr2_v3[arr2_v1[0][0]][0]; ++v6) {
int v7 = d + arr2_v1[0][0] + arr2_v3[arr2_v3[0][0]][0];
d = v7;
}
}
Log.d("xihantest", "\nd: " + d);
int v8 = 2 * po1;
int v9 = a;
int v10 = 11 + 4 * 0 + v9;
int v11 = a * 6 ^ v10;
int v12 = po1 - v8 + v11;
po2 = v12;
int v13 = po2;
int v14 = 0;
int v15;
if(po1 >= v14 + arr2_v3[0][0]) {
v15 = sb(po2);
}else {
int v16 = c;
int v17 = 5 + 2 * po2 + v16;
v15 = po2 ^ v17;
}
int v18 = v13 + v15 + a ^ 25 >> sb(20 - 0 >> 99);
Log.d("xihantest", "v18: " + v18);
}
}
- 获取到最终固定的的v18 = 658,运算方法也显而易见了
private fun 第二层() {
// 识别码
val cl = 44722
// (识别码 异或运算 658) 除以 999
val v19 = (cl xor 658) / 999
// v19 乘以 2 异或运算 识别码
val pass = v19 * 2 xor cl
"第二层密码: $pass".logd()
}
第三层分析
- 初始化控件和第二层一样,直接来到点击事件这里分析,这里解锁的关键是获取 v1 的值
@Override // android.view.View$OnClickListener
public void onClick(View view0) {
// 使用了 aes 加密
byte[] arr_b = MyService.this.aes.cipher("Android SignApk".getBytes());
StringBuffer stringBuffer0 = new StringBuffer();
int v;
for(v = 0; v < 16; ++v) {
if((arr_b[v] & 0xFF) > 15) {
stringBuffer0.append(String.format("%x", new Byte(arr_b[v])));
}
else {
stringBuffer0.append(String.format("0%x", new Byte(arr_b[v])));
}
stringBuffer0.append(" ");
}
// 获取到这个值 离解锁就差一步
int v1 = MyService.this.letterToNumber(((String)"" + stringBuffer0.subSequence(3, 36))) / 3000;
if(MyService.this.lp.getText().toString().trim().length() == 0) {
return;
}
// 解锁方式1: 会强行重启配合开机自启服务再坑一波钱
if(MyService.this.lp.getText().toString().equals("6" + (v1 ^ MyService.this.cz))) {
MyService.this.fv.removeView();
new Timer().schedule(new 100000036(this), 1500L);
return;
}
// 解锁方式2: 直接删除当前view 也就是可以回到桌面卸载应用
if(MyService.this.lp.getText().toString().equals("" + (v1 ^ MyService.this.cz))) {
MyService.this.fv.removeView();
return;
}
MyService.this.解锁.setVisibility(0);
MyService.this.解锁.setText("密码错误,手机恢复正常失败/nManifest-Version: 1.0Created-By: 1.0 (Android SignApk)");
Runnable runnable0 = MyService.this.runn3;
MyService.this.hand3.postDelayed(runnable0, 2000L);
}
- Aes类就是用dex转jar大法,把这个jar以及代码复制过来修一修
// 这是我写的 Kotlin 函数 直接获取结果
fun aes(): Int {
val aes = Clown(Clown.KeySize.Bits192, keys)
val arr_b = aes.cipher("Android SignApk".toByteArray())
val stringBuffer0 = StringBuffer()
var v = 0
while (v < 16) {
if (arr_b[v].toInt() and 0xFF > 15) {
stringBuffer0.append(String.format("%x", arr_b[v]))
} else {
stringBuffer0.append(String.format("0%x", arr_b[v]))
}
stringBuffer0.append(" ")
++v
}
val v1 = letterToNumber("" + stringBuffer0.subSequence(3, 36)) / 3000
return v1
}
private fun 第三层() {
// 识别码
val cz = 158718
// 上面获取到的 v1 异或运算 识别码
val pass = "${aes() xor cz}"
"第三层密码: $pass".logd()
}
样本下载地址:https://xihan.lanzouv.com/iRgfI0dt60ed 解压密码:52pj