<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    某視頻app的學習記錄

    VSole2022-01-03 16:58:52

    一、軟硬件環境

    IDA 7.5

    Frida 14.2.2

    Gda3.86

    JEB

    jadx-gui

    unidbg

    LineageOs 17.1 (android 10)

    小米8

    二、坑(時間順序)

    1、截包相關   

    這個看見有人說有個版本開始不能截了,我這邊一直都是換證書的,沒感覺有影響,估計我下的是盜版,碰到再看了。

    2、之前看到so都是32位的,后來都換成64位的了。

    3、網絡請求相關

    之前就看到有使用Cronet模塊,想看下實現過程,下過源碼(https://github.com/hanpfei/chromium-net),一個是發現跟app使用的并不完全相同,再一個還要自己編譯模塊,就想到直接使用抖音的模塊。

    先新建一個自己的測試app,接著的工作就是搬代碼了,直接導出所有的反編譯代碼,結合源碼,首先就是這個包:

        com.ttnet.org.chromium.net
    

           

    這里插下搬代碼中的一些問題:

    首先就是反編譯代碼,幾個工具(jeb ,jadx, GDA)各有優劣,要結合使用, jadx得到的代碼可讀性更好,但是很多函數識別不出來,比如這種:

    GDA擅長處理疑難雜癥,其它2個識別不了的代碼,它這個都能識別,不過可讀性不好,基本不能直接編譯通過,需要看清楚邏輯后修復。

    再就是反編譯代碼中變量順序問題,也會影響編譯(初始化的變量放在后面了):

    代碼修復中有些類型的轉換,比如Bundle類型變量為null的,可能被還原成了int i=0; 然后條件判斷的時候,這個也會出現編譯錯誤。

    再就是Map.Entry這種,需要先用object遍歷,再轉換類型。

    if (!StringsKt.contains$default((CharSequence) name, (CharSequence) "__MACOSX", false, 2, (Object) null)) {
    

    kotlin相關也要修改:

    StringsKt.contains((CharSequence) str, (CharSequence) "?", false))
    

    還有下面這種繼承的:

    public final class FrontMethodFragment$onCreateFailed$1 extends Lambda implements Function0 {
    Lambda要帶上Lambda
    

    參考這個 cannot be inherited with different type arguments_PhilsphyPrgram的博客-CSDN博客。

    還有一些邏輯上的,少了break之類,就不是很好發現了,這個只有遇到后調試修復了。

    最后還有麻煩的就是缺少異常處理,java編譯是強制要求處理異常的,找過資料,想編譯時候忽略異常處理,發現是JAVA規范強制的,屏蔽不了,加這個也花了不少時間。

    總之,3個工具要結合使用,怎么方便怎么來。

    搬過來后,直接調用測試:

      // 初始化引擎                CronetEngine.Builder myBuilder = new CronetEngine.Builder(getApplicationContext());                CronetEngine cronetEngine = myBuilder.build();
                    // 創建請求線程                Executor executor = Executors.newSingleThreadExecutor();
                    // 創建UrlRequest                strUrl="http://10.0.0.217/about";                UrlRequest.Builder requestBuilder = cronetEngine.newUrlRequestBuilder(                        strUrl, new MyUrlRequestCallback(), executor);                requestBuilder.addHeader("testHeader","testValue");                UrlRequest request = requestBuilder.build();
                    // 發起請求                request.start();
    class MyUrlRequestCallback extends UrlRequest.Callback {    private static final String TAG = "ttttt MyUrlRequestCallback";
        @Override    public void onRedirectReceived(UrlRequest request, UrlResponseInfo info, String newLocationUrl) {        android.util.Log.i(TAG, "onRedirectReceived method called.");        // You should call the request.followRedirect() method to continue        // processing the request.        request.followRedirect();    }
        @Override    public void onResponseStarted(UrlRequest request, UrlResponseInfo info) {        //這個函數只會調用一次        android.util.Log.i(TAG, "onResponseStarted method called.");        // You should call the request.read() method before the request can be        // further processed. The following instruction provides a ByteBuffer object        // with a capacity of 102400 bytes to the read() method.        request.read(ByteBuffer.allocateDirect(102400));    }
        @Override    public void onFailed(UrlRequest urlRequest, UrlResponseInfo urlResponseInfo, CronetException cronetException) {
        }
        @Override    public void onReadCompleted(UrlRequest request, UrlResponseInfo info, ByteBuffer byteBuffer) {        //這個會調用多次        android.util.Log.i(TAG, "onReadCompleted method called.");        // You should keep reading the request until there's no more data.        request.read(ByteBuffer.allocateDirect(102400));    }
        @Override    public void onSucceeded(UrlRequest request, UrlResponseInfo info, String str) {        android.util.Log.i(TAG, "onSucceeded method called.");    }}
    

    測試發現本地服務器正常收到請求了,測試app也能正常收到回調:

    不過請求地址改成本地https的時候,發現崩潰,根據日志定位報錯線程: 

    發現是throw new UnsupportedOperationException("Method not decompiled造成的,那就是jadx代碼不全的問題,這個參考GDA補全。

    不過這里也看出是證書校驗問題,本地的證書不通過。

    // Certificate is not trusted due to non-trusted root of the certificate// chain.static int NO_TRUSTED_ROOT = -2;
    

    這里又熟悉了下https,查了下資料:HTTPS請求的整個過程的詳細分析_研究生生活、學習記錄-CSDN博客_https過程

    最后,由于非對稱加密的公鑰可以在網絡中傳輸,如何保證公鑰傳送到給正確的一方,這個時候使用了證書來驗證。證書不是保證公鑰的安全性,而是驗證正確的交互方。

    從這個流程圖來看,訪問本地網站就是驗證證書無效了。

    本地web服務器的file.crt文件:

    解密后:

    Len:625

    正好上面截圖對應測試程序調試中的certChain。

    搞清楚這個過程后,后面再進行干涉就有切入點了。

    到這里后,雖然可以調用Cronet了,但是發現跟抖音自己的接口調用路徑其實是不同的,比如某個接口的堆棧:

    明顯不是上面用的調用方式,那接著就是根據這個補代碼了。

    熟悉了上面這種注釋語法:

    最后找到下面這個:

    其實之前也看到過這個url,但是關聯不到怎么調用的,現在看是通過代理類方式使用的($Proxy84),這里是這個功能的類定義文件,單純靜態看確實不好看明白,通過動態調試才搞清楚整個過程。

    看見有鴻蒙相關:

    這里遇到個自己挖的坑,因為用了混淆的包名,導致hash這里跳過了,返回null了,會導致創建proxy類不成功:

    private  T getStaticServiceImplReal(Class cls) {     PatchProxyResult proxy = PatchProxy.proxy(new Object[]{cls}, this, changeQuickRedirect, false, 95671);     if (proxy.isSupported) {         return (T) proxy.result;     }
         int iHashCode=cls.getName().hashCode();     switch (iHashCode) {
    

    補完各種代碼后(中間確實各種報錯,各種補文件,最后備份的時候,發現有3000+文件,不過有的模塊,比如wx相關的基本拷過來就能用了,zfb的交叉太多了,花了不少時間修復,感覺這樣下去,可以編譯一個抖音出來了),使用下面方式調用接口:

    FeedActionApi.f71204b.diggItem("7018000130007633191", "7018000130007633191", 1, 0).get();
    

    運行調試:

    看起來點贊操作的類是創建成功了,跟hook看到的堆棧類似了。

    這里查了下代理類的資料:Java動態代理之InvocationHandler最簡單的入門教程 - 簡書 (jianshu.com)

    創建代理類相關:

    這個選擇不同的網絡模式,模擬器默認走第二種。

            if (C9859c.m21219a()) {            jSONObject.put("netClientType", "CronetClient");        } else {            jSONObject.put("netClientType", "TTOkhttp3Client");        }
    

    到這里后,終于在測試服務器收到請求了:

    到這里的時候,發現極速版更新到18.2了。

    Cront相關Native函數引入有變化:

    輸出jni函數的時候,發現有SPDY相關的:

    順便查了下SPDY相關資料:HTTP 的前世今生:一次性搞懂 HTTP、HTTPS、SPDY、HTT_請求 (sohu.com)

    后面看來要看下這個了。

    在16.6版本都測試程序上替換上18.2版本都so,測試報錯:

    看起來native函數引入混淆了:

    包裝了一層:

    對應修改后,就可以正常編譯運行了。

    看到檢查root相關代碼:

    算起來這次搬代碼,最難的是開始時候,加進來的代碼牽扯其它引用,一堆編譯錯誤,加入引用,可能又會引入新的引用依賴,很容易耐心磨沒了,這個時候就需要權衡取舍,不能把分支展得太開,還好堅持下來了,慢慢框架搭起來后,很多就是正向工作了。

    三、學習總結

    1、學習了JAV代理類使用,大廠設計模式。

    2、熟悉了Cronet模塊。

    感覺主要工作都是正向的,正向逆向不分家,有了正向的工作,逆向切入點也會更多。

    bytebuffer
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    獲取到類之后,我們就可以通過反射來間接調用里面的方法,獲取里面的變量等。
    給木馬帶雙眼睛
    2023-04-18 09:56:25
    近月,內存馬的技術也產生新的變化,如利用websocket進行通信,Executor內存馬進行socket通信。本文介紹利用Poller內存馬實現全流量監控,這樣,攻擊方可以實時監控經過系統的每一個請求,或者增加了釣魚等信息利用的便利。這也就是說注入Poller的內存馬一定是不能出任何bug的,一旦出了,整個服務直接崩潰。反向,Executor是一個任務類,創建后就執行一個線程任務,如果這次業務異常,最多這次的請求無法正常執行罷了。
    Jenkins Server 軟件中的一個嚴重漏洞CVE-2019-17638可能導致內存損壞并導致機密信息泄露。Jenkins是最受歡迎的開源自動化服務器,由CloudBees和Jenkins社區維護。“ Jenkins 至和LTS 至捆綁了帶有安全漏洞CVE-2019-17638的。此漏洞可能允許未經身份驗證的攻擊者獲得HTTP響應報頭,其中可能包含打算用于其他用戶的敏感數據。”該漏洞影響Jetty和Jenkins Core,該漏洞在Jetty版本中引入,用于處理大型HTTP響應報頭并防止緩沖區溢出。
    隨著Web應用攻擊手段變得復雜,基于請求特征的防護手段,已經不能滿足企業安全防護需求。在2012年的時候,Gartner引入了“Runtime application self-protection”一詞,簡稱為RASP,屬于一種新型應用安全保護技術,它將防護功能“ 注入”到應用程序中,與應用程序融為一體,使應用程序具備自我防護能力,當應用程序遭受到實際攻擊傷害時,能實時檢測和阻斷安全攻擊,而不需要進行人工干預。實現了在攻擊鏈路最關鍵的地方阻斷攻擊。
    官方下載地址: https://dbeaver.com/download/ultimate/
    線程切換效率低下:單機CPU核數固定,線程爆炸之后操作系統頻繁進行線程切換,應用性能急劇下降。
    某視頻app的學習記錄
    2022-01-03 16:58:52
    這個看見有人說有個版本開始不能截了,我這邊一直都是換證書的,沒感覺有影響,估計我下的是盜版,碰到再看了。先新建一個自己的測試app,接著的工作就是搬代碼了,直接導出所有的反編譯代碼
    Apache Log4j2從RCE到RC1繞過本文首發于先知社區:https://xz.aliyun.com
    RCE回顯技術在20年突然火爆全網,這里學習跟進一下。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类