本文为看雪论坛优秀文章
看雪论坛作者ID:bigeast
分析要用到的工具:
1
APP开发的背景知识的介绍
intent = Intet(this,另一个activity)startactivity(intent)
intent = Intet(intent.action_view)intent.data = uri.parse('www.baidu.com')startactivity(intent)
在activity的xml中定义,显示文字。
2
APP逆向过程
findstr.exe /s /i "0x7f10002f" *.*outdir\res\values\public.xml: <public type="string" name="activity_alipay_real_name_hint" id="0x7f10002f" />outdir\smali\com\happy\roulette\R$string.smali:.field public static final activity_alipay_real_name_hint:I = 0x7f10002f
3
赌球APP分析实战
apktool d xxx.apk -o baz从AndroidManifest.xml搜索android.intent.action.MAIN"定位到如下:
-<activity android:name="com.happy.roulette.activity.SplashActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar.FullScreen" android:screenOrientation="portrait">-<intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity>
protected void onCreate( Bundle paramBundle) {super.onCreate(paramBundle);setContentView(2131492944);//加载定义好的布局TextView textView = (TextView)_$_findCachedViewById(R.id.tv_version_info); //设置文字Intrinsics.checkExpressionValueIsNotNull(textView, "tv_version_info");textView.setText("37_2.2.40"); //设置文字checkLocalHost();}
private final void checkLocalHost() {String str = HostManager.INSTANCE.loadHostUrl();//先取出urlHostManager.INSTANCE.setNeedGetHost(true);checkAppMaintain(str, true); //然后验证url是否能连接}
public final class HostManager {public final String loadHostUrl() {mSharedPreferencesManager = new SharedPreferencesManager(MyApplication.getAppContext());SharedPreferencesManager sharedPreferencesManager = mSharedPreferencesManager;if (sharedPreferencesManager == null)Intrinsics.throwUninitializedPropertyAccessException("mSharedPreferencesManager");return sharedPreferencesManager.get("key-host-url", "");}
C:\Users\Administrator>adb shell dumpsys window | findstr mCurrentFocusmCurrentFocus=Window{b007190 u0 com.cxinc.app.n9h/com.happy.roulette.activity.MainActivity}
C:\Users\Administrator>adb shell dumpsys window | findstr mCurrentFocusmCurrentFocus=Window{ae65cbc u0 com.cxinc.app.n9h/com.happy.roulette.activity.login.LoginActivity}
C:\Users\Administrator>adb devicesList of devices attachedemulator-5554 deviceC:\Users\Administrator>adb -s emulator-5554 shellemulator64_x86_64:/ $ run-as com.cxinc.app.n9hrun-as: package not debuggable: com.cxinc.app.n9h
private final void checkAppMaintain(String paramString, boolean paramBoolean) {this.mHostApi.checkUrl(paramString, new SplashActivity$checkAppMaintain$1(paramString, paramBoolean));}
public void checkUrl(String paramString, BaseWebApi.ResultListener paramResultListener) {this.mAppUrl = paramString;StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(this.mAppUrl);stringBuilder.append("/api/checkAppWh.do");StringRequest stringRequest = createStringRequest(0, stringBuilder.toString(), null, paramResultListener);getRequestQueue().add((Request)stringRequest);}
C:\Users\Administrator>adb shellemulator64_x86_64:/ # tcpdump -i any -p -n -s 0 -w /sdcard/capture.pcap-i是指定网卡为any;
-w表示保存为pacp;
s 0 : tcpdump 默认只会截取前 96 字节的内容,要想截取所有的报文内容,可以使用 -s number, number 就是你要截取的报文字节数,如果是 0 的话,表示截取报文全部内容。
-p : 不让网络接口进入混杂模式。默认情况下使用 tcpdump 抓包时,会让网络接口进入混杂模式。一般计算机网卡都工作在非混杂模式下,此时网卡只接受来自网络端口的目的地址指向自己的数据。当网卡工作在混杂模式下时,网卡将来自接口的所有数据都捕获并交给相应的驱动程序。如果设备接入的交换机开启了混杂模式,使用 -p 选项可以有效地过滤噪声。
抓包结束后按Cltr+C中断后即可以保存文件。
C:\Users\Administrator>adb pull /sdcard/capture.pcap d:/capture.pcap/sdcard/capture.pcap: 1 file pulled, 0 skipped. 2.6 MB/s (108623 bytes in 0.040s)
public static final class SplashActivity$checkAppMaintain$1 implements BaseWebApi.ResultListener {SplashActivity$checkAppMaintain$1(String param1String, boolean param1Boolean) {}//如果请求失败了调用OnError,说明当前请求的域名失效了public void onError(@NotNull ErrorOutput param1ErrorOutput) {Intrinsics.checkParameterIsNotNull(param1ErrorOutput, "error");Log.e("SplashActivity", "APP );if (this.$isFailToGetHost) {SplashActivity.this.getHost(); //调用这个获取新的url,然后发送请求:是https://9h.开头的return;}SplashActivity.this.showErrorRetryDialog(");}//如果请求成功了:以下代码有两个case:case49,case48。public void onResult(@NotNull String param1String) {Context context;Intrinsics.checkParameterIsNotNull(param1String, "response");Log.i("SplashActivity", "APP );switch (param1String.hashCode()) {case 49:if (param1String.equals("1")) {context = (Context)SplashActivity.this;StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(WebServerUrl.getBaseUrl());stringBuilder.append("/wh.html"); //通过wh.html可以看出wh是维护的缩写,且下面也标识了“维护中”,//所以推测这是服务器维护时会返回一个code,此时会执行下面代码的跳转,//比如跳转到9h.app00app.com/wh.htmlJumpUtil.ToWeb(context, stringBuilder.toString(), "维护中“);SplashActivity.this.finish();return;}break;case 48:if (context.equals("0")) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("Selected host url: ");stringBuilder.append(this.$selectedHostUrl);Log.i("SplashActivity", stringBuilder.toString());WebServerUrl.setBaseUrl(this.$selectedHostUrl);SplashActivity.this.getAppConfig(); //将服务器返回的参数用来设置APPreturn;}break;}onError(new ErrorOutput());}}
private final void getHost() {this.mHostApi.getHost(new SplashActivity$getHost$1());}
public void getHost(BaseWebApi.ResultListener paramResultListener) {this.i = 0;this.mClientResultListener = paramResultListener;sendGetHostRequest(getNextServerUrl());}
private String getNextServerUrl() {try {WebServerUrl.setCurrentServerUrl(WebServerUrl.SERVER_URL_LIST.get(this.i));StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("https://9h.");stringBuilder.append(WebServerUrl.SERVER_URL_LIST.get(this.i));stringBuilder.append("/api/getAppConfig.do");return stringBuilder.toString();} catch (Exception exception) {exception.printStackTrace();return "";}
public static final List<String> SERVER_URL_LIST = Arrays.asList(new String[] { "app00app.com", "app66app.com", "app99app.vip", "app66app.vip", "app88app.vip" });每个加密套件都包含,密钥交换,签名算法,加密算法,哈希算法。
可以看到Record layer下面有三个协议:
private final void getAppConfig() {TextView textView = (TextView)_$_findCachedViewById(R.id.tv_progress_msg);Intrinsics.checkExpressionValueIsNotNull(textView, "tv_progress_msg");textView.setText("正在获取平台配置,请稍等“);this.mHomeApi.getAppConfig(new SplashActivity$getAppConfig$1());}
public void getAppConfig(BaseWebApi.ResultListener paramResultListener) {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append(WebServerUrl.getBaseUrl());stringBuilder.append("/static/data/config.json");StringRequest stringRequest = createStringRequest(0, stringBuilder.toString(), null, paramResultListener);getRequestQueue().add((Request)stringRequest);}
public static final class SplashActivity$getAppConfig$1 implements BaseWebApi.ResultListener {//请求失败public void onError(@NotNull ErrorOutput param1ErrorOutput) {Intrinsics.checkParameterIsNotNull(param1ErrorOutput, "error");Log.e("SplashActivity", "Gat App Config );SplashActivity.this.showErrorRetryDialog(");}//请求成功,则这里传进来的参数param1String即为服务器返回的响应。public void onResult(@NotNull String param1String) {Intrinsics.checkParameterIsNotNull(param1String, "response");Log.i("SplashActivity", "Gat App Config );try {//把获取到json配置给APPAppConfigOutput appConfigOutput = (AppConfigOutput)(new Gson()).fromJson(param1String, AppConfigOutput.class);AppConfigManager.INSTANCE.setAppConfig(appConfigOutput);SplashActivity splashActivity = SplashActivity.this;String str = appConfigOutput.defaultSkin;Intrinsics.checkExpressionValueIsNotNull(str, "appConfigOutput.defaultSkin");//这里就会跳转到mainactivity,即APP的主页面splashActivity.judgeSkin(str);return;} catch (Exception exception) {exception.printStackTrace();onError(new ErrorOutput());return;}}}
private final void judgeSkin(String paramString) {if (AppConfigManager.INSTANCE.loadIsShowDefaultSkin()) {if (Intrinsics.areEqual(paramString, SystemSettingsManager.SkinStyle.BLUE.toString())) {SystemSettingsManager.INSTANCE.setColorSkin(SystemSettingsManager.SkinStyle.BLUE);} else if (Intrinsics.areEqual(paramString, SystemSettingsManager.SkinStyle.RED.toString())) {SystemSettingsManager.INSTANCE.setColorSkin(SystemSettingsManager.SkinStyle.RED);} else if (Intrinsics.areEqual(paramString, SystemSettingsManager.SkinStyle.DARK.toString())) {SystemSettingsManager.INSTANCE.setColorSkin(SystemSettingsManager.SkinStyle.DARK);}AppConfigManager.INSTANCE.saveIsShowDefaultSkin(false);}goHomePage();}
private final void goHomePage() {if (!isFinishing()) {startActivity(new Intent((Context)this, MainActivity.class));finish();}
protected void onCreate( Bundle paramBundle) {super.onCreate(paramBundle);setContentView(2131492931); //设置布局initFragment();initNavigation(); //设置导航栏setNavigationListener(); //设置导航栏的监听if (HostManager.INSTANCE.isNeedGetHost())getHost();}
private final void getHost() {(new HostApi()).getHost(new MainActivity$getHost$1());}
public void getHost(BaseWebApi.ResultListener paramResultListener) {this.i = 0;this.mClientResultListener = paramResultListener;sendGetHostRequest(getNextServerUrl());}}
private String getNextServerUrl() {try {WebServerUrl.setCurrentServerUrl(WebServerUrl.SERVER_URL_LIST.get(this.i));StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("https://9h.");stringBuilder.append(WebServerUrl.SERVER_URL_LIST.get(this.i));stringBuilder.append("/api/getAppConfig.do");return stringBuilder.toString();} catch (Exception exception) {exception.printStackTrace();return "";}}
public static final class MainActivity$getHost$1 implements BaseWebApi.ResultListener {public void onError(@NotNull ErrorOutput param1ErrorOutput) {Intrinsics.checkParameterIsNotNull(param1ErrorOutput, "error");Log.e("MainActivity", "Get Host );MainActivity.this.showErrorCloseDialog("获取服务器失败,请先检查网络“);}public void onResult(@NotNull String param1String) {Intrinsics.checkParameterIsNotNull(param1String, "resultAppUrl");Log.i("MainActivity", "Get Host );if ((Intrinsics.areEqual(param1String, HostManager.INSTANCE.loadHostUrl()) ^ true) != 0) {HostManager.INSTANCE.saveHostUrl(param1String);MainActivity.this.showErrorCloseDialog("线路有更新,需要重启APP”);}}}
4
总结
E N D
看雪ID:bigeast
https://bbs.pediy.com/user-home-859945.htm
# 往期推荐
1.内核漏洞学习-HEVD-NullPointerDereference
点击“阅读原文”了解更多