<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-12 16:01:33

    APP開發的背景知識的介紹

    APP開發遵循邏輯和視圖分離的思想:我們創建一個activity,android studio會自動生成其對應的xml文件。

    注意,任何的activity都要在AndroidManifest.xml中定義。(一般androidstudio會自動完成)

    視圖

    視圖在xml中定義:可以直接可視化移動一個按鈕進視圖,也可以用代碼編寫。每個元素都會有一個id留給activity去調用。比如按鈕A對應一個id,按鈕B對應一個Id。

    在xml中:

    @id/id_name表示引用這個id。

    @+id/button1 表示定義一個id。

    邏輯

    邏輯在activity中定義:activty要加載上面定義的視圖,即布局,要調用setContentView(布局文件的id)。(項目添加的任何資源都會在R文件中生成一個資源id,這里布局文件的id即為對應xml文件的id)

    如果要對布局進行一些操作,也是在activity中定義。比如說監聽按鈕的點擊事件,在Java中要使用findviewByID()方法獲取布局文件中定義的元素,然后再定義該元素的函數的內容,比如按鈕元素的話就可以定義其setonclicklistener函數。

    而Kotlin不需要使用findviewbyID(),直接使用元素的名字就可以調用該元素了。

    (1)邏輯間如何跳轉---intent

    在activity中按鈕的listen函數中定義

    intent = Intet(this,另一個activity)startactivity(intent)
    

    即可實現跳轉頁面。

    (2)隱式intent

    不指定跳轉到哪個activity,而是指定跳轉動作和類型,讓系統來選擇合適的activity。我們可以在AndroidManifest.xml中設置activity的可以相應的動作和類型、相應的協議類型(scheme)。

    intent不僅可以打開activity,也可以打開網頁。

    intent = Intet(intent.action_view)intent.data = uri.parse('www.baidu.com')startactivity(intent)
    

    甚至可以通過intent向下一個或者上一個頁面傳遞數據。

    (3)常用UI控件---textview

    在activity的xml中定義,顯示文字。

    width和height有三個可選值:

    1、match_parent:和父布局大小一樣(即和手機屏幕大小一樣)

    2、wrap_content:恰好包住里面內容。

    3、固定值。

    還有其他的屬性可以選:是否居中,文字顏色,文字大小。

    APP逆向過程

    目標:給一個APK反匯編出java源代碼。

    流程:

    1、先用壓縮包提取classes.dex文件。

    2、用dex2jar提取出jar文件,并將這個文件拷至dex2jar工具存放目錄下。

    打開控制臺,使用cd指令進入到dex2jar工具存放的目錄下。進入到dex2jar目錄下后,輸入“d2j-dex2jar.bat classes.dex”指令運行。

    執行完畢,查看dex2jar目錄,會發現生成了classes.dex.dex2jar.jar文件。

    3、將jar文件導入jd.gui看java源碼

    上一步中生成的classes.dex.dex2jar.jar文件,可以通過JD-GUI工具直接打開查看jar文件中的代碼。

    查找某個字符串在哪個頁面出現的小trick

    res/values/string.xml存了APK的字符串。

    同目錄下的public.xml有其對應的id,查找當前目錄下包含0x7f10002f的文件。

    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
    

    賭球APP分析實戰

    定位第一個APP界面

    我們用apktool解析出apk的文件夾如下:(安裝apktool前要先安裝java1.8.關于apktool如何安裝參考https://www.jianshu.com/p/b027856d55ac

    安裝完并配置好環境變量后,用以下命令反編譯輸出到baz目錄。  

    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>
    

    所以第一個主頁面是com.happy.roulette.activity.SplashActivity,以下便是第一個界面:

    我們從com.happy.roulette.activity.SplashActivity.class的oncreate函數開始看(因為Oncreate函數是進入到一個新頁面后要執行的第一個函數)。

    protected void onCreate(@Nullable 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();}
    

    我們繼續看checkLocalHost()函數,每次啟動第一個界面都會檢查一下host。

    private final void checkLocalHost() {  String str = HostManager.INSTANCE.loadHostUrl();//先取出url  HostManager.INSTANCE.setNeedGetHost(true);  checkAppMaintain(str, true); //然后驗證url是否能連接}
    

    loadHostUrl函數會先取出url, 我們繼續跟蹤loadHostUrl。

    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", "");  }
    

    發現使用了sharepreferences存儲這個url在本地,以下想在本地找到保存這個url的文件。

    在模擬器上運行該APP,打印出APP的package和當前頁面的acitivy,以下為APP在主頁面時運行命令得到的結果。

    C:\Users\Administrator>adb shell dumpsys window | findstr mCurrentFocus  mCurrentFocus=Window{b007190 u0 com.cxinc.app.n9h/com.happy.roulette.activity.MainActivity}
    

    以下為APP在登錄頁面時運行命令得到的結果:

    C:\Users\Administrator>adb shell dumpsys window | findstr mCurrentFocus  mCurrentFocus=Window{ae65cbc u0 com.cxinc.app.n9h/com.happy.roulette.activity.login.LoginActivity}
    

    通過 run-as 命令進入APP的文件目錄下:

    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
    

    發現無法進入這個APP的目錄,因為不是debug版本的APP。所以后面會通過抓包來獲取這個url。

     

    我們繼續看checkLocalHost函數,上面我們無法分析出loadHostUrl在本地哪個文件獲取url。

    我們繼續看后面的函數調用過程,通過loadHostUrl函數獲取到url后,會調用checkAppMaintain來檢查這個url。

    private final void checkAppMaintain(String paramString, boolean paramBoolean) {    this.mHostApi.checkUrl(paramString, new SplashActivity$checkAppMaintain$1(paramString, paramBoolean));  }
    

    一直跟蹤下去,發現這里會請求這個url。發現會在這個url后拼接/api/checkAppWh.do,然后發送請求。

    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);}
    

    tcpdump抓包

    tcpdump是常用的一個抓包工具,linux或android環境下已經默認安裝好。

    當用android studio自帶的模擬器啟動APP后,在電腦終端輸入adb shell進入模擬器終端:

    C:\Users\Administrator>adb shell
    

    進入模擬器終端后用tcpdump命令進行抓包,包保存在/sdcard/capture.pcap

    emulator64_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中斷后即可以保存文件。

    我們在PC終端中把模擬器的抓取的包拿回來本地D盤,在本地終端執行。

    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)
    

    通過wireshark分析如下:

    首先會進行DNS請求,獲取這個域名對應的IP:發現請求9h.app00app.com這個域名,且IP為204.11.56.48。

    checkmaintain執行完后會跳到下面這個回調函數里,即請求服務器后會回到以下函數。

    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.html            JumpUtil.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(); //將服務器返回的參數用來設置APP            return;          }          break;      }      onError(new ErrorOutput());    }  }
    

    發現請求這個IP,連接不上。所以會執行上面Onerror函數去獲取另外一個域名。

    Onerror函數會調用gethost()

    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());}
    

    看getNextServerUrl,它會將“https://9h.”拼接域名list中一個域名。

    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 "";  }
    

    跟蹤SERVER_URL_LIST,發現這是一個域名的list,包含以下域名。猜測這種讀博網站域名經常被封,所以要多準備幾個域名。

    public static final List<String> SERVER_URL_LIST = Arrays.asList(new String[] { "app00app.com", "app66app.com", "app99app.vip", "app66app.vip", "app88app.vip" });
    

    獲取到域名之后,又會繼續去執行checkAppMaintain這個函數去檢測域名,即重復上面步驟,直到找到一個可以連接的域名,然后會進入上面的Onresult函數的case48。

    通過抓包分析,這里請求了上面域名list中的第二個域名app66app.com

    然后與得到的IP地址進行TCP連接,以下為三次握手和密鑰協商過程。

    為了學習TLS協議,下面我們分析一下協議的過程。

    可以看到是TLS1.3協議,先看看Client hello這條消息。

    我們可以看到Transport layer Security就是傳輸層安全(TLS),

    TLS1.3總共有兩層,分別是握手協議(handshake protocol)和記錄協議(record protocol),握手協議在記錄協議的上層,記錄協議是一個分層協議。其中握手協議中還包括了警告協議(alert protocol)。

    (圖來自https://blog.csdn.net/SkyChaserYu/article/details/104716229#t3,以下部分轉自該博客)

    接下來看一下Handshake protocol:Hello中的內容:

    Handshake Type:ClientHello,表示握手消息類型,此處是ClientHello

    Length:508,即長度為508。

    Version:TLS1.2(0x0303),表示版本號為1.2,TLS1.3中規定此處必須置為0x0303,即TLS1.2,起到向后兼容的作用。1.3版本用來協商版本號的部分在擴展當中,而之前的版本就在此處進行。

    Random,隨機數,是由安全隨機數生成器生成的32個字節。

    Session ID Length:會話ID的長度。

    Session ID,會話ID,TLS 1.3之前的版本支持“會話恢復”功能,該功能已與1.3版本中的預共享密鑰合并。為了兼容以前的版本,該字段必須是非空的,因此不提供TLS 1.3之前會話的客戶端必須生成一個新的32字節值。該值不必是隨機的,但應該是不可預測的,以避免實現固定在特定值,否則,必須將其設置為空。

    Cipher Suites Length,即下面Cipher Suites的長度。

    Cipher Suites是密碼套件,表示客戶端提供可選擇的加密方式,如圖所示:

    每個加密套件都包含,密鑰交換,簽名算法,加密算法,哈希算法。

    Compression Methons (1 method)表示壓縮方法,長度為1,內容為空

    Exentisons擴展部分,是TLS1.3才開始使用,是TLS1.3的顯著特征。每一個擴展都包含類型(type),長度(length)和數據(data)三個部分。

    下面分析幾個相對重要的擴展:

    1)key_share

    key_share 是橢圓曲線類型對應的公鑰,如圖所示:

    此處包含一個KeyShareEntry,是x25519曲線組,這是客戶端生成的代表自己支持的DH組,具體數據在KeyExchange字段中;每個KeyShareEntry都代表一組密鑰交換參數,對于有限域DH來說是g和p的值,對于橢圓域DH是橢圓曲線和基點的值,很明顯這里是用了橢圓曲線的DH。

    同選定加密組件一樣,TLS 1.3定義了幾組gp值,雙方只需要協商想要使用的gp對即可。具體實施過程,為每個組生成一個DH密鑰交換的參數,將其組名和參數值封裝在key_share擴展中,服務端選定DH組后,返回一個封裝好的key_share,雙方根據交換的公鑰參數和自己持有的私鑰參數計算出DH最終密鑰。

    理論上,客戶端應該將所有與密鑰協商有關的擴展(pre_shared_key、shared_key)都發送給服務端,服務端選定哪一種,再將對應選定的擴展返還給客戶端,如果服務端同時使用兩種密鑰協商,則返還所有擴展,

    然后我們來看下EXDH的密鑰協商過程,首先EC的意思是橢圓曲線,這個EC提供了一個很厲害的性質,你在曲線上找一個點P,給定一個整數k,求解另外一個點Q=kP很容易,給定兩個點P,Q,知道Q =kP,求k卻是個難題。

    在這個背景下,給定一個大家都知道的大數G,client在每次需要和server協商秘鑰時,生成一段隨機數a,然后發送A=aG給server,server收到這段消息(aG)后,生成一段隨機數b,然后發送B=bG給client,然后server端計算(aG)b作為對稱秘鑰,client端收到后bG后計算a(Gb),因為(aG)b = a(Gb),所以對稱秘鑰就是aGb。

    攻擊者只能截獲A=aG和B=bG,由于橢圓曲線難題,知道A和G是很難計算a和b的,也就無法計算aGb了(當然,實際上的計算過程和原理證明不是這么簡單的,中間還有一個取模的過程,以及取模過程的交換律和結合律證明,但是本質思想和這個是差不多的)。留意下TLS1.3圖中的key_share,這段的功能就是直接記錄了aG,然后包含在client_hello中。然后server收到后在server_hello的key_share段中記錄bG。所以TLS1.3一個RTT就搞定握手了。

    參考:https://blog.csdn.net/zk3326312/article/details/80245756

    2)signature_algorithms

    Signature_algorithms擴展是,客戶端提供簽名算法,讓服務器選擇

    以第一個簽名算法為例,ecdsa_secp256r1_sha256,使用sha256作為簽名中的哈希,簽名算法為ecdsa。

    3)psk_key_exchange_modes

    TLS 1.3 與之前的協議有較大差異,相比過去的的版本,引入了新的密鑰協商機制 — PSK。TLS 1.3支持DH、PSK兩種密鑰協商機制,也支持同時使用兩者進行密鑰協商。

    psk_key_exchange_modes表示psk密鑰交互模式選擇

    此處的PSK模式為(EC)DHE下的PSK(貌似就是使用上面的ECDHE進行密鑰協商),客戶端和服務器必須提供KeyShare。

    如果是僅PSK模式,則服務器不需要提供KeyShare。

    下面分析server hello:

    可以看到Record layer下面有三個協議:

    1、握手協議:確定了加密套件為TLS_AES_128_GCM_SHA256,確定了密鑰協商的隨機數bG

    2、密鑰交換協議

    3、應用數據協議-https

    4、SNI Service name indication

    由于服務器能力的增強,在一臺物理服務器上部署多個虛擬主機已經成為十分流行的做法了。在過去的 HTTP 時代,解決基于名稱的主機同一 ip 地址上托管多個網站的問題并不難。

    當一個客戶端請求某特定網站時,把請求的域名作為主機頭(host)放在 http header 中,從而服務器根據域名可以知道把該請求引向哪個域名服務,并把匹配的網站傳送給客戶端。但是此方式到 https 就失效了,因為 SSL 在握手的過程中,不會有 host 信息,所以服務端通常返回配置中的第一個可用證書,這就導致不同虛擬主機上的服務不能使用不同證書(但在實際中,證書通常是與服務對應。)

    所以通過這個字段我們有可能能識別出APP對應的服務是什么。

    參考:https://blog.csdn.net/u010217394/article/details/121713758

    當APP檢測到請求成功,即網站還能被訪問時,會調用getAppConfig()。

    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());  }
    

    繼續跟蹤this.mHomeApi.getAppConfig,發現它向服務器請求了一個json文件,猜測會將服務器返回的配置信息用來配置APP。

    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);}
    

    抓包如下:

    發現本地請求的數據是TLS傳輸,下面能看到數據是加密的數值。

    請求完之后進入回調函數如下:

    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配置給APP      AppConfigOutput 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;    }  }}
    

    跟蹤judgeSkin:

    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();  }
    

    跟蹤goHomePage:這里就會跳轉到mainactivity,即APP的主頁面MainActivity.class,并且結束當前頁面。

    private final void goHomePage() {  if (!isFinishing()) {    startActivity(new Intent((Context)this, MainActivity.class));    finish();  }
    

    以下即跳入主頁面:

    以下我們看看MainActivity.class的oncreate函數:

    protected void onCreate(@Nullable Bundle paramBundle) {    super.onCreate(paramBundle);    setContentView(2131492931); //設置布局    initFragment();    initNavigation(); //設置導航欄    setNavigationListener(); //設置導航欄的監聽    if (HostManager.INSTANCE.isNeedGetHost())      getHost();  }
    

    其gethost函數會執行以下函數:

    private final void getHost() {  (new HostApi()).getHost(new MainActivity$getHost$1());}
    

    繼續跟蹤getHost:

    public void getHost(BaseWebApi.ResultListener paramResultListener) {    this.i = 0;    this.mClientResultListener = paramResultListener;    sendGetHostRequest(getNextServerUrl());  }}
    

    跟蹤getNextServerUrl,這里是請求服務器去獲取/api/getAppConfig.do這個配置文件(上面是獲取/static/data/config.json文件)。

    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”);    }  }}
    

    下面我又點擊了導航欄,跳轉到其他頁面。

    通過抓包發現,它又請求了其他的域名,并且后面和該域名進行了TCP連接,并且傳輸了加密的數據。

    此時server name與上面不同,后面又有client hello請求。

    又出現了新的server name。

    string預共享密鑰
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    APP開發的背景知識的介紹APP開發遵循邏輯和視圖分離的思想:我們創建一個activity,android studio會自動生成其對應的xml文件。視圖視圖在xml中定義:可以直接可視化移動一個按鈕進視圖,也可以用代碼編寫。
    服務器的相關信息(真實ip,系統類型,版本,開放端口,WAF等) 網站指紋識別(包括,cms,cdn,證書等),dns記錄 whois信息,姓名,備案,郵箱,電話反查(郵箱丟社工庫,社工準備等) 子域名收集,旁站,C段等 google hacking針對化搜索,pdf文件,中間件版本,弱口令掃描等 掃描網站目錄結構,爆后臺,網站banner,測試文件,備份等敏感文件泄漏等 傳輸協議,通用漏洞,ex
    ?上整理的?試問題?全,有些 HW ?試的題,已經收集好了,提供給?家。
    2020年08月11日,Windows官方發布了 NetLogon 特權提升漏洞的風險通告,該漏洞編號為CVE-2020-1472,漏洞等級:嚴重,漏洞評分:10分,該漏洞也稱為“Zerologon”,2020年9月11日,Secura高級安全專家Tom Tervoort和技術總監Ralph Moonen發表了漏洞相關的博文和白皮書,分享了Zerologon漏洞的細節,表示攻擊者在通過NetLogon協議與AD控建立安全通道時,可利用該漏洞將AD控的計算機賬號密碼置為空,從而控制控服務器,之后相關的EXP也就被開發出來了。
    滲透技巧總結
    2022-01-28 21:33:52
    聲明以下技巧不應用于非法用途Tips 1. 手動端口探測nmap的-sV可以探測出服務版本,但有些情況下必須手動探測去驗證使用Wireshark獲取響應包未免大材小用,可通過nc簡單判斷eg.對于8001端口,nc連接上去,隨便輸入一個字符串,
    內橫向移動技術就是在復雜的內網攻擊中被廣泛使用的一種技術,尤其是在高級持續威脅中。攻擊者會利用該技術,以被攻陷的系統為跳板,訪問其他 內主機,擴大資產范圍(包括跳板機器中的文檔和存儲的憑證,以及通過跳板機器連接的數據庫、域控制器或其他重要資產)。
    如果找到了某個用戶的ntlm hash,就可以拿這個ntlm hash當作憑證進行遠程登陸了 其中若hash加密方式是 rc4 ,那么就是pass the hash 若加密方式是aes key,那么就是pass the key 注意NTLM和kerberos協議均存在PTH: NTLM自然不用多說 kerberos協議也是基于用戶的client hash開始一步步認證的,自然也會受PTH
    很多人把這個原因歸結于KB2871997補丁,實際上不然,這個事情的成因實際是UAC在搗亂。RID為500的賬戶和屬于本地administrators組的用戶在通過網絡遠程鏈接時,默認就是高權限令牌。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类