案例:某APP打开时提示更新
思路:想这是查壳看看有没有加壳,没有就去反编译按照提示搜索下,结果却是没有加壳反编译了下搜索,搜索不到,后来想到是不是网络传过来的,那这样是不是就要先获取本身APP的版本号,然后传输后发现版本过低发送过来这么一句话弹出个窗口,想到这里我就去抓了个包看看是不是确实有也确实传输了信息,所以我下了他们最新版本的APP看了下版本,对比了下去把旧版本里面涉及到版本地方全部改成和新版本一样,从新编译打包安装想着你就是那这些对比的我给了最新的版本号不该提示了吧,打开发现还是会提示晕了,没办法搜索有搜索不了看源代码一点点找如大海捞针。
唯一的线索就是这个弹窗了从一个开发者角度去想问题,这个弹窗用了安卓那个弹窗的类,那就hook去吧,先利用objection 内存搜索以加载类看看用了那个弹窗类。
objection -g com.xx.xx.xx explore (注入)
android heap search instances android.app.AlertDialog (存在)
最后确定有这个 AlertDialog 那就去hook这个类吧
android hooking watch class android.app.AlertDialog
这个读取顺序是从下往上,所以看到了 on.Create 走喽去创建他的地方看一看,由于啊她这个是一开APP就显示了所以要以swpan注入
直接用objection:objection -g com.xxx.xxx explore -s "android hooking watch class_method android.app.AlertDialog.onCreate --dump-args --dump-backtrace --dump-return"
前3个都是弹窗类的实现看着也不太像 我们直接从NativeUIFeatureImpl.a 开始看
objection -g com.xxx.xxx explore -s "android hooking watch class_method io.dcloud.feature.ui.nativeui.NativeUIFeatureImpl.a --dump-args --dump-backtrace --dump-return"
哦吼出来了,去反编译看看源码 有兴趣的自己看下 反正就是说 第一个switch 判断到了 str.equals("alert") 这个去给执行了这个 c2 = '\r'; ,然后 第二个switch 又判断了c2 = ‘\r’ 去调用方法a:a((byte) 0, JSONUtil.getString(createJSONArray, 2), null, JSONUtil.getString(createJSONArray, 0), new String[]{JSONUtil.getString(createJSONArray, 3)}, null, iWebview, JSONUtil.getString(createJSONArray, 1));
看了看 a 方法里面是坐窗口创建展示文字的,具体的就不展示了,接下来你可以 hook 这个 execute 方法判断 str 等不等于 alert 然后嘛嘿嘿不用不说了,当然这里也有可能其他地方用到,你可以再往下追到 a 方法我看了看他也有个大判断 判断参数里面那个数字 是几操作哪里,也可以从这里做。
public String execute(IWebview iWebview, String str, String[] strArr) {
char c2;
String[] strArr2;
boolean z;
IActivityHandler iActivityHandler;
String optString;
c cVar;
String[] strArr3;
IActivityHandler iActivityHandler2;
a remove;
c remove2;
IApp obtainApp = iWebview.obtainApp();
int i2 = 0;
String str2 = strArr.length >= 1 ? strArr[0] : null;
JSONArray createJSONArray = strArr.length >= 2 ? JSONUtil.createJSONArray(strArr[1]) : null;
str.hashCode();
switch (str.hashCode()) {
case -2071870705:
if (str.equals("closeToast")) {
c2 = 0;
break;
}
c2 = 65535;
break;
case -1774127679:
if (str.equals("hideMenu")) {
c2 = 1;
break;
}
c2 = 65535;
break;
case -1727401845:
if (str.equals("closePreviewImage")) {
c2 = 2;
break;
}
c2 = 65535;
break;
case -1383206285:
if (str.equals("previewImage")) {
c2 = 3;
break;
}
c2 = 65535;
break;
case -1055312317:
if (str.equals("WaitingView_setTitle")) {
c2 = 4;
break;
}
c2 = 65535;
break;
case -979805852:
if (str.equals("prompt")) {
c2 = 5;
break;
}
c2 = 65535;
break;
case -739906705:
if (str.equals("pickDate")) {
c2 = 6;
break;
}
c2 = 65535;
break;
case -739422578:
if (str.equals("pickTime")) {
c2 = 7;
break;
}
c2 = 65535;
break;
case -339042820:
if (str.equals("showMenu")) {
c2 = '\b';
break;
}
c2 = 65535;
break;
case -228775627:
if (str.equals("closeWaiting")) {
c2 = '\t';
break;
}
c2 = 65535;
break;
case -160355144:
if (str.equals("getTitlebarHeight")) {
c2 = '\n';
break;
}
c2 = 65535;
break;
case -92053387:
if (str.equals("setTitlebarVisible")) {
c2 = 11;
break;
}
c2 = 65535;
break;
case -49471494:
if (str.equals("_NativeObj_close")) {
c2 = '\f';
break;
}
c2 = 65535;
break;
case 92899676:
if (str.equals("alert")) {
c2 = '\r';
break;
}
c2 = 65535;
break;
case 110532135:
if (str.equals("toast")) {
c2 = 14;
break;
}
c2 = 65535;
break;
case 235955885:
if (str.equals("isTitlebarVisible")) {
c2 = 15;
break;
}
c2 = 65535;
break;
case 951117504:
if (str.equals("confirm")) {
c2 = 16;
break;
}
c2 = 65535;
break;
case 988815851:
if (str.equals("WaitingView_close")) {
c2 = 17;
break;
}
c2 = 65535;
break;
case 1572298953:
if (str.equals("actionSheet")) {
c2 = 18;
break;
}
c2 = 65535;
break;
case 2141060722:
if (str.equals("WaitingView")) {
c2 = 19;
break;
}
c2 = 65535;
break;
default:
c2 = 65535;
break;
}
switch (c2) {
case 0:
b.a(obtainApp.obtainAppId());
break;
case 1:
PlatformUtil.invokeMethod("io.dcloud.appstream.actionbar.StreamAppActionBarUtil", "hideMenu", null, new Class[]{Activity.class, String.class}, new Object[]{iWebview.getActivity(), iWebview.obtainApp().obtainAppId()});
if (!(iWebview == null || iWebview.getActivity() == null || (iActivityHandler = DCloudAdapterUtil.getIActivityHandler(iWebview.getActivity())) == null)) {
iActivityHandler.sideBarHideMenu();
break;
}
break;
case 2:
Activity activity = RuningAcitvityUtil.getActivity("io.dcloud.feature.nativeObj.photoview.PhotoActivity");
if (activity != null) {
activity.onBackPressed();
break;
}
break;
case 3:
JSONArray jSONArray = JSONUtil.getJSONArray(createJSONArray, 0);
JSONObject jSONObject = JSONUtil.getJSONObject(createJSONArray, 1);
if (jSONArray != null) {
ArrayList arrayList = new ArrayList();
ArrayList arrayList2 = new ArrayList();
for (int i3 = 0; i3 < jSONArray.length(); i3++) {
try {
String string = jSONArray.getString(i3);
arrayList.add(!PdrUtil.isNetPath(string) ? iWebview.obtainApp().convert2AbsFullPath(iWebview.obtainFullUrl(), string) : string);
arrayList2.add(string);
} catch (JSONException e2) {
e2.printStackTrace();
}
}
Intent intent = new Intent();
intent.setClassName(obtainApp.getActivity().getPackageName(), "io.dcloud.feature.nativeObj.photoview.PhotoActivity");
intent.putExtra("image_urlList", arrayList);
intent.putExtra("original_image_urlArray", arrayList2);
if (jSONObject != null) {
intent.putExtra("image_current_index", jSONObject.optInt("current", 0));
if (jSONObject.has("background")) {
intent.putExtra("image_backgroud_color", PdrUtil.stringToColor(jSONObject.optString("background")));
}
if (jSONObject.has("loop")) {
intent.putExtra("image_loop", jSONObject.optBoolean("loop"));
}
if (jSONObject.has(WXBasicComponentType.INDICATOR)) {
intent.putExtra("image_indicator", jSONObject.optString(WXBasicComponentType.INDICATOR));
}
}
intent.putExtra("image_photo", true);
if (!(createJSONArray == null || createJSONArray.length() <= 2 || (optString = createJSONArray.optString(2)) == null)) {
intent.putExtra("preview_callback", optString);
LongClickEventManager.getInstance().addOnlongClickListener(optString, new c(this, iWebview, optString));
}
intent.putExtra("screen_orientation", obtainApp.getRequestedOrientation());
obtainApp.getActivity().startActivity(intent);
obtainApp.getActivity().overridePendingTransition(17432576, 17432577);
break;
}
break;
case 4:
HashMap<String, c> hashMap = this.a;
if (!(hashMap == null || (cVar = hashMap.get(str2)) == null)) {
cVar.b(JSONUtil.getString(createJSONArray, 0));
break;
}
break;
case 5:
String string2 = JSONUtil.getString(createJSONArray, 0);
String string3 = JSONUtil.getString(createJSONArray, 1);
String string4 = JSONUtil.getString(createJSONArray, 2);
String string5 = JSONUtil.getString(createJSONArray, 3);
JSONArray jSONArray2 = JSONUtil.getJSONArray(createJSONArray, 4);
if (jSONArray2 != null) {
int length = jSONArray2.length();
String[] strArr4 = new String[length];
while (i2 < length) {
strArr4[i2] = JSONUtil.getString(jSONArray2, i2);
i2++;
}
strArr3 = strArr4;
} else {
strArr3 = null;
}
a((byte) 2, string4, null, string2, strArr3, string5, iWebview, string3);
break;
case 6:
a(iWebview, JSONUtil.getString(createJSONArray, 0), JSONUtil.getJSONObject(createJSONArray, 1));
break;
case 7:
b(iWebview, JSONUtil.getString(createJSONArray, 0), JSONUtil.getJSONObject(createJSONArray, 1));
break;
case '\b':
PlatformUtil.invokeMethod("io.dcloud.appstream.actionbar.StreamAppActionBarUtil", "showMenu", null, new Class[]{Activity.class, String.class, String.class, String.class, IWebview.class, String.class}, new Object[]{iWebview.getActivity(), iWebview.obtainApp().obtainAppId(), JSONUtil.getString(createJSONArray, 0), JSONUtil.getString(createJSONArray, 1), iWebview, JSONUtil.getString(createJSONArray, 2)});
if (!(iWebview == null || iWebview.getActivity() == null || (iActivityHandler2 = DCloudAdapterUtil.getIActivityHandler(iWebview.getActivity())) == null)) {
iActivityHandler2.sideBarShowMenu(JSONUtil.getString(createJSONArray, 0), JSONUtil.getString(createJSONArray, 1), iWebview, JSONUtil.getString(createJSONArray, 2));
break;
}
break;
case '\t':
HashMap<String, c> hashMap2 = this.a;
if (hashMap2 != null) {
for (c cVar2 : hashMap2.values()) {
cVar2.a();
}
this.a.clear();
break;
}
break;
case '\n':
Object invokeMethod = PlatformUtil.invokeMethod("io.dcloud.appstream.actionbar.StreamAppActionBarUtil", "getTitlebarHeight", null, new Class[]{Activity.class}, new Object[]{iWebview.getActivity()});
return Deprecated_JSUtil.wrapJsVar(String.valueOf(invokeMethod instanceof Integer ? Integer.valueOf(invokeMethod.toString()).intValue() : 0), false);
case 11:
try {
z = createJSONArray.getBoolean(0);
} catch (Exception e3) {
e3.printStackTrace();
z = true;
}
PlatformUtil.invokeMethod("io.dcloud.appstream.actionbar.StreamAppActionBarUtil", "setTitlebarVisible", null, new Class[]{Activity.class, String.class, Boolean.TYPE}, new Object[]{iWebview.getActivity(), iWebview.obtainApp().obtainAppId(), Boolean.valueOf(z)});
return null;
case '\f':
HashMap<String, a> hashMap3 = this.b;
if (!(hashMap3 == null || (remove = hashMap3.remove(str2)) == null)) {
remove.a(-1);
remove.b.onItemClick(-1);
break;
}
break;
case '\r':
a((byte) 0, JSONUtil.getString(createJSONArray, 2), null, JSONUtil.getString(createJSONArray, 0), new String[]{JSONUtil.getString(createJSONArray, 3)}, null, iWebview, JSONUtil.getString(createJSONArray, 1));
break;
case 14:
a(obtainApp, iWebview, JSONUtil.getString(createJSONArray, 0), JSONUtil.getJSONObject(createJSONArray, 1));
break;
case 15:
Object invokeMethod2 = PlatformUtil.invokeMethod("io.dcloud.appstream.actionbar.StreamAppActionBarUtil", "isTitlebarVisible", null, new Class[]{Activity.class, String.class}, new Object[]{iWebview.getActivity(), iWebview.obtainApp().obtainAppId()});
return Deprecated_JSUtil.wrapJsVar(String.valueOf(invokeMethod2 instanceof Boolean ? Boolean.valueOf(invokeMethod2.toString()).booleanValue() : false), false);
case 16:
try {
String string6 = JSONUtil.getString(createJSONArray, 0);
String string7 = JSONUtil.getString(createJSONArray, 1);
Object obj = createJSONArray.get(2);
if (!(obj instanceof JSONObject)) {
if (obj instanceof String) {
String str3 = (String) obj;
JSONArray jSONArray3 = JSONUtil.getJSONArray(createJSONArray, 3);
if (jSONArray3 != null) {
int length2 = jSONArray3.length();
String[] strArr5 = new String[length2];
while (i2 < length2) {
strArr5[i2] = JSONUtil.getString(jSONArray3, i2);
i2++;
}
strArr2 = strArr5;
} else {
strArr2 = null;
}
a((byte) 1, str3, null, string6, strArr2, null, iWebview, string7);
break;
} else {
a((byte) 1, null, null, string6, null, null, iWebview, string7);
break;
}
} else {
a((byte) 1, string6, (JSONObject) obj, iWebview, string7);
break;
}
} catch (JSONException e4) {
e4.printStackTrace();
break;
}
case 17:
HashMap<String, c> hashMap4 = this.a;
if (!(hashMap4 == null || (remove2 = hashMap4.remove(str2)) == null)) {
remove2.a();
break;
}
break;
case 18:
String string8 = JSONUtil.getString(createJSONArray, 2);
a a2 = a(string8, JSONUtil.getJSONObject(createJSONArray, 0), JSONUtil.getString(createJSONArray, 1), iWebview);
if (!PdrUtil.isEmpty(string8) && !PdrUtil.isEmpty(a2)) {
if (this.b == null) {
this.b = new HashMap<>();
}
this.b.put(string8, a2);
break;
}
break;
case 19:
String string9 = JSONUtil.getString(createJSONArray, 0);
JSONObject jSONObject2 = JSONUtil.getJSONObject(createJSONArray, 1);
String string10 = JSONUtil.getString(createJSONArray, 2);
Activity topRuningActivity = RuningAcitvityUtil.getTopRuningActivity(iWebview.getActivity());
if (!topRuningActivity.isDestroyed()) {
c cVar3 = new c(this, iWebview, string9, jSONObject2, string10, topRuningActivity);
if (this.a == null) {
this.a = new HashMap<>();
}
cVar3.f = str2;
this.a.put(str2, cVar3);
break;
}
break;
}
return null;
}