<tr id="tp1vn"><td id="tp1vn"><dl id="tp1vn"></dl></td></tr>
  1. <p id="tp1vn"></p>
  2. <sub id="tp1vn"><p id="tp1vn"></p></sub>
    <u id="tp1vn"><rp id="tp1vn"></rp></u>
    <meter id="tp1vn"></meter>
      <wbr id="tp1vn"><sup id="tp1vn"></sup></wbr>
      日韩第一页浮力,欧美a在线,中文字幕无码乱码人妻系列蜜桃 ,国产成人精品三级麻豆,国产男女爽爽爽免费视频,中文字幕国产精品av,两个人日本www免费版,国产v精品成人免费视频71pao
      網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

      游戲性能優(yōu)化與逆向分析技術(shù)

      0
      分享至


      【USparkle專欄】如果你深懷絕技,愛(ài)“搞點(diǎn)研究”,樂(lè)于分享也博采眾長(zhǎng),我們期待你的加入,讓智慧的火花碰撞交織,讓知識(shí)的傳遞生生不息!

      這是侑虎科技第1878篇文章,感謝作者其樂(lè)陶陶供稿。歡迎轉(zhuǎn)發(fā)分享,未經(jīng)作者授權(quán)請(qǐng)勿轉(zhuǎn)載。如果您有任何獨(dú)到的見(jiàn)解或者發(fā)現(xiàn)也歡迎聯(lián)系我們,一起探討。(QQ群:793972859)

      作者主頁(yè):

      https://www.zhihu.com/people/jun-yan-76-80

      一、前言

      一直以來(lái)性能優(yōu)化的工作,非常依賴于工具,從結(jié)果反推過(guò)程,采集產(chǎn)品運(yùn)行時(shí)信息,反推生產(chǎn)環(huán)節(jié)中的問(wèn)題,性能問(wèn)題的定位其實(shí)就是在做各種逆向。

      不同的工具有不同的檢測(cè)面,一般會(huì)按照由粗及細(xì)的順序使用,直到找到問(wèn)題的答案。

      • 粗粒度的工具,可大致定位到問(wèn)題是出在哪個(gè)硬件上,比如發(fā)熱問(wèn)題,可能的負(fù)載點(diǎn)在于CPU、GPU、其它硬件(屏幕、傳感器、網(wǎng)絡(luò)),一般應(yīng)該是系統(tǒng)級(jí)的工具,常用的有Perfetto、Xcode、GamePerf、PerfDog。

      • 細(xì)粒度的工具,檢測(cè)面較窄,但能提供更深入的信息,比如:定位到是CPU的問(wèn)題時(shí),可使用Unity Profiler、Simpleperf看問(wèn)題堆棧;當(dāng)定位到是GPU的問(wèn)題時(shí),則使用RenderDoc、SnapdragonProfiler、Arm Graphics Analyzer截幀。

      打個(gè)比喻,粗粒度的工具好比地鐵,能帶你到大致的區(qū)域范圍,更細(xì)粒度的工具幫你解決最后一公里路,在實(shí)際情況中,“打通”一公里的問(wèn)題往往是卡點(diǎn),通用性質(zhì)的工具可能滿足不了需求,常常做一些定制化的東西,通過(guò)一定積累,形成強(qiáng)大的工具鏈以應(yīng)對(duì)各種突發(fā)問(wèn)題,本文主要對(duì)于這些底層的技術(shù)棧做一些總結(jié)。

      二、動(dòng)態(tài)庫(kù)注入

      Android系統(tǒng)的數(shù)據(jù)基本都能通過(guò)讀各種文件實(shí)現(xiàn)(統(tǒng)計(jì)線程,讀取CPU利用率/頻率),但有嚴(yán)格的權(quán)限限制,非root環(huán)境下,只能讀取自己進(jìn)程相關(guān)的文件、內(nèi)存信息。

      我們注入到目標(biāo)進(jìn)程的動(dòng)態(tài)庫(kù),就好像我們派出的“間諜”一樣,利用目標(biāo)進(jìn)程的身份執(zhí)行我們自己的代碼。

      使用JDWP Shellifier是最常用的方式,我們用C++在NDK環(huán)境下編寫(xiě)一個(gè)動(dòng)態(tài)庫(kù)so文件,這個(gè)腳本利用Java調(diào)試服務(wù)加載我們自己的庫(kù)。這也是RenderDoc、?LoliProfiler、Matrix用的方式,需要應(yīng)用Debug權(quán)限,或者root開(kāi)全局調(diào)試,或者使用APKTool,解包修改AndroidManifest文件的Debug權(quán)限。


      https://github.com/IOActive/jdwp-shellifier

      這個(gè)腳本用Python封裝了注入過(guò)程,在onCreate函數(shù)觸發(fā)時(shí),加載我們的庫(kù)。

      jdwp_start("127.0.0.1", 500, "android.app.Activity.onCreate", None, libname)


      控制臺(tái)輸出顯示注入成功

      當(dāng)動(dòng)態(tài)庫(kù)注入成功時(shí),C++側(cè)入口函數(shù)JNI_OnLoad會(huì)被執(zhí)行,我們就可以干自己想干的事情了,這只是打開(kāi)大門(mén)的第一步。

      JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {     (void)reserved;     LOGI("JNI_OnLoad");     JNIEnv *env;     LOGI("------------------ 4000 : %d", (int)JNI_VERSION_1_6);     if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)     {         LOGI("JNI version not supported");         return JNI_ERR; // JNI version not supported.     }     else     {         LOGI("JNI init complete");     } }

      下一步介紹Hook技術(shù),俗稱鉤子,能對(duì)特定函數(shù)劫持,兩種常見(jiàn)Hook手段為PLT Hook、Inline Hook。

      三、PLT Hook

      先大概講一下程序調(diào)用動(dòng)態(tài)鏈接庫(kù)中函數(shù)的流程,以libunity.so中調(diào)用libc.so的Open函數(shù)為例子:會(huì)先訪問(wèn)PLT(Procedure Linkage Table),第一次訪問(wèn)它會(huì)使用動(dòng)態(tài)連接器查找libc.so中Open函數(shù)的地址,然后地址保存到GOT(Global Offset Table)地址表,之后的調(diào)用就直接查GOT表了,如下:


      所謂的PLT Hook就是在這個(gè)過(guò)程做文章、鉆空子,比如xHook就是修改GOT表的函數(shù)地址為我們的自定義函數(shù)實(shí)現(xiàn)攔截,xHook是一個(gè)常用的庫(kù),較多運(yùn)用于各種工具底層實(shí)現(xiàn),我們可以直接使用它,同時(shí)它也是開(kāi)源的,我們可以參考它里面的很多代碼。


      https://github.com/iqiyi/xHookgithub.com/iqiyi/xHook

      PLT Hook比較適合去Hook一些公用庫(kù)的調(diào)用,不管上層怎么變,IO的行為最終落地到對(duì)Open、Close、Read、Wirte的調(diào)用,實(shí)際項(xiàng)目中主要用于IO、內(nèi)存分配、線程、網(wǎng)絡(luò)等行為的監(jiān)控,但它的局限性在于不能Hook內(nèi)部函數(shù),比如引擎內(nèi)部的函數(shù)調(diào)用。

      四、實(shí)戰(zhàn):打印引擎啟動(dòng)時(shí)的IO調(diào)用

      隨便創(chuàng)建一個(gè)空的Demo,打包APK,將下面C++代碼通過(guò)NDK編譯成動(dòng)態(tài)庫(kù)后,使用JDWP注入運(yùn)行。

      這里在JNI_OnLoad函數(shù)創(chuàng)建一個(gè)新的線程,延遲3秒后再執(zhí)行Hook的動(dòng)作,是因?yàn)闀r(shí)機(jī)太早libunity.so未加載會(huì)導(dǎo)致失敗(據(jù)說(shuō)xHook的作者后續(xù)開(kāi)發(fā)了一個(gè)新的庫(kù)叫bHook,改進(jìn)了這一點(diǎn))。

           "xhook/xhook.h"         int MyOpen(const char *pathname, int flags, mode_t mode) {     int ret = open(pathname, flags, mode);     __android_log_print(ANDROID_LOG_INFO, "TestHook", "unity open %s %d", pathname, ret);     return ret; } void TestHook() {     // 延遲3秒,等待Unity加載完成     std::this_thread::sleep_for(std::chrono::seconds(3));     // 對(duì)Open函數(shù)Hook注冊(cè)     xhook_register("libunity.so", "open", (void *)MyOpen, nullptr);     // 執(zhí)行Hook     xhook_refresh(0); } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {     JNIEnv *env;     if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)     {         return JNI_ERR; // JNI version not supported.     }     std::thread(TestHook).detach();     return JNI_VERSION_1_6; }

      這樣我們可以觀察到Unity啟動(dòng)時(shí)加載的一些東西:

      正在加載obb文件


      正在加載il2cpp.so

      五、Inline Hook

      前面提到,PLT Hook不能Hook到庫(kù)內(nèi)部的函數(shù)調(diào)用,這個(gè)時(shí)候就應(yīng)該輪到Inline Hook出場(chǎng),它是通過(guò)對(duì)目標(biāo)函數(shù)地址插入跳轉(zhuǎn)指令實(shí)現(xiàn),理論上可以Hook住任意內(nèi)部函數(shù),功能更為強(qiáng)大,由于涉及到在不同CPU架構(gòu)上的運(yùn)行狀態(tài)機(jī)器碼修改,看起來(lái)很復(fù)雜,其實(shí)一點(diǎn)也不簡(jiǎn)單,雖兼容性不如PLT Hook,不推薦在生產(chǎn)環(huán)境使用,但作為測(cè)試環(huán)境中的性能工具還是很強(qiáng)的。

      ShadowHook是我常用的庫(kù),可以將它的C++源碼下載下來(lái),和自己庫(kù)一起編譯。


      https://github.com/bytedance/android-inline-hook

      如果Hook的目標(biāo)庫(kù)是帶符號(hào)表的,可以通過(guò)函數(shù)名hook,像這樣:

      stub = shadowhook_hook_sym_name(                "libart.so",                "_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc",                (void *)proxy,                (void **)&orig);

      但是我們常見(jiàn)的libunity.so、libil2cpp.so的符號(hào)表是分離的,可以嘗試用llvm-objcopy合并回去,這里更推薦另一種做法,ShadowHook也可以直接通過(guò)函數(shù)地址進(jìn)行Hook

      void *shadowhook_hook_func_addr(     void *func_addr,     void *new_addr,     void **orig_addr);

      這里的func_addr函數(shù)地址是絕對(duì)地址,為動(dòng)態(tài)庫(kù)基地址、函數(shù)偏移地址之和,找到這兩個(gè)地址加起來(lái)就行。

      動(dòng)態(tài)庫(kù)基地址每次進(jìn)程啟動(dòng)都不一樣,需要我們?cè)诔绦蛑袆?dòng)態(tài)獲取,可以通過(guò)dl_iterate_phdr(Android 5.0以上)獲取,也可以讀/proc/self/maps實(shí)現(xiàn)(Android 4.0版本以上),之前介紹的xHook有源碼可以抄一下。


      /proc/self/maps能查詢到動(dòng)態(tài)庫(kù)基地址

      而函數(shù)的偏移地址可以使用NDK下llvm-readelf -s指令,讀取符號(hào)表獲取到:


      readelf讀取出的引擎內(nèi)部函數(shù)地址

      接下來(lái),對(duì)函數(shù)Hook后,需要對(duì)參數(shù)進(jìn)行內(nèi)存分析提取里面的有用信息,如果有源碼,就是開(kāi)卷考試,按照其內(nèi)存布局定義出來(lái);沒(méi)源碼,我們也可以通過(guò)一些技巧把信息提取出來(lái),下面以實(shí)戰(zhàn)說(shuō)明一下。

      六、實(shí)戰(zhàn):統(tǒng)計(jì)引擎內(nèi)部調(diào)用

      我曾經(jīng)在《使用Simpleperf+Timeline診斷游戲卡頓》[1]這一篇文章中提到過(guò),一些常見(jiàn)的卡頓歸因,能通過(guò)Simpleperf識(shí)別,但我們只知道觸發(fā)堆棧,今天我們更進(jìn)一步。

      這里以AddComponent函數(shù)為例,做一個(gè)Demo,然后嘗試使用Hook把觸發(fā)的GameObject、組件名字都打印出來(lái),C# 測(cè)試代碼如下:

      // New Game Object節(jié)點(diǎn)添加一些Unity內(nèi)置組件 var go = newGameObject(); go.AddComponent (); go.AddComponent (); go.AddComponent (); // 相機(jī)節(jié)點(diǎn)添加一個(gè)自定義腳本組件 gameObjet.AddComponent ();

      通過(guò)Simpleperf鎖定我們的目標(biāo)函數(shù)為AddComponent(GameObject&, Unity::Type const*, ScriptingClassPtr, core::basic_string >*)


      Simpleperf-Timeline查看命中的native函數(shù)

      接下來(lái)通過(guò)llvm-readelf -s指令,查詢函數(shù)在符號(hào)表中的位置,名字稍微和Simpleperf中的顯示形式有點(diǎn)區(qū)別,但是我們還是能認(rèn)出它,它的地址就是0x5126a4。


      搜索符號(hào)表內(nèi)AddComponent函數(shù)地址

      接下來(lái),我們需要在代理函數(shù)里面,對(duì)函數(shù)參數(shù)做一些解析,從函數(shù)簽名可以看到,參數(shù)有4個(gè):void *go、void *unitytype、void *scriptclassptr和void *error。

      我們的目標(biāo)是獲取節(jié)點(diǎn)名和組件名,解析前3個(gè)就行,主要有兩種方案:

      1. 在符號(hào)表里多收集一些工具函數(shù)地址,比如獲取GameObject名字的方法0x435010,這個(gè)方法傳入GameObject對(duì)象指針作為參數(shù),返回名字字符串,所以可以把這個(gè)函數(shù)地址存起來(lái),直接調(diào)用,我管這叫“他山之石,可以攻玉”。


      獲取GameObject名字的方法地址能輕易搜索到

      2. 針對(duì)另外兩個(gè)參數(shù),可以將結(jié)構(gòu)直接定義出來(lái)使用,比如ScriptClass前兩個(gè)參數(shù)是指針,第三個(gè)就是C字符串。這些工作,在有相關(guān)源碼的情況下會(huì)容易很多,如果沒(méi)有的話,只能通過(guò)LLDB無(wú)源碼動(dòng)態(tài)調(diào)試之類的手段來(lái)獲取其內(nèi)存布局,會(huì)涉及到一些二進(jìn)制分析手段、工具。

      有了這些準(zhǔn)備工作,就可以開(kāi)始編碼了:

           "shadowhook.h"          classScriptclass {     public:         void *placeholder1;         void *placeholder2;         constchar *name; }; classUnityType {     public:         void *placeholder1;         void *placeholder2;         constchar *name; }; uintptr_t baseaddr = 0; int callback(struct dl_phdr_info *info, size_t size, void *data) {     constchar *target = (constchar *)data;     // Check if the current shared library is the target library     if (strstr(info->dlpi_name, target))     {         __android_log_print(ANDROID_LOG_INFO, "TestHook", "Base address of %s: 0x%lx\n", target, (unsigned long)info->dlpi_addr);         baseaddr = info->dlpi_addr;         return1; // Return 1 to stop further iteration     }     return0; // Continue iteration } void *old_AddComponent = nullptr; typedef void *(*AddComponentFunc)(void *go, void *unitytype, void *scriptclassptr, void *error); typedef constchar*(*GameObjectGetNameFunc)(void *ptr); void *MyAddComponent(void *go, void *unitytype, void *scriptclassptr, void *error) {     constchar *goName = nullptr;     constchar *typeName = nullptr;     if(go != nullptr)     {         // 計(jì)算GameObjectGetName的地址         uintptr_t addr = baseaddr + 0x435010;          // 調(diào)用GameObjectGetName獲取名稱         GameObjectGetNameFunc func = (GameObjectGetNameFunc)(addr);         goName = func(go);     }     if (scriptclassptr != nullptr)     {         Scriptclass *t = (Scriptclass *)scriptclassptr;         typeName = t->name;     }     elseif (unitytype != nullptr)     {         UnityType *t = (UnityType *)unitytype;         typeName = t->name;     }     if(goName == nullptr)         goName = "null";     if(typeName == nullptr)         typeName = "null";     __android_log_print(ANDROID_LOG_INFO, "TestHook", "UnityAddComponent: %s %s\n", goName, typeName);     return ((AddComponentFunc)old_AddComponent)(go, unitytype, scriptclassptr, error); } void TestHook() {     // 延遲3秒,等待Unity加載完成     std::this_thread::sleep_for(std::chrono::seconds(3));     // 查詢libunity的基地址     constchar *library_name = "libunity.so";     dl_iterate_phdr(callback, (void *)library_name);     // 計(jì)算AddComponent的函數(shù)地址     uintptr_t addr = baseaddr + 0x5126a4;     // 執(zhí)行Hook并保存原函數(shù)地址到old_AddComponent     void *stub = shadowhook_hook_func_addr((void *)addr, (void *)MyAddComponent, (void **)&old_AddComponent);     if (stub == nullptr)     {         int err_num = shadowhook_get_errno();         constchar *err_msg = shadowhook_to_errmsg(err_num);         __android_log_print(ANDROID_LOG_INFO, "TestHook", "hook error %d - %s\n", err_num, err_msg);     }     else     {         __android_log_print(ANDROID_LOG_INFO, "TestHook", "hook success\n");     } } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {     JNIEnv *env;     if (vm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK)     {         return JNI_ERR; // JNI version not supported.     }     // 初始化Shadowhook     int ret = shadowhook_init(SHADOWHOOK_MODE_UNIQUE, true);     if (ret != 0)     {         constchar *err_msg = shadowhook_to_errmsg(shadowhook_get_init_errno());         __android_log_print(ANDROID_LOG_INFO, "TestHook", "init error %d - %s\n", shadowhook_get_init_errno(), err_msg);     }     else     {         __android_log_print(ANDROID_LOG_INFO, "TestHook", "init success\n");     }     std::thread(TestHook).detach();     return JNI_VERSION_1_6; }

      和前面PLT Hook的例子一樣,使用JDWP注入執(zhí)行,最終可以輸出Demo中調(diào)用AddComponet的參數(shù)詳情,利用這些信息,接下來(lái)就可以做很多事情了,我們現(xiàn)在可以幾乎Hook任意函數(shù)!


      控制臺(tái)最終能正常輸出節(jié)點(diǎn)、組件名

      七、棧回溯

      在棧上每個(gè)函數(shù)都有自己的儲(chǔ)存空間,被稱之為棧幀(Frame),上面保存了部分參數(shù)、局部變量。當(dāng)調(diào)用其它函數(shù)時(shí),會(huì)將這個(gè)函數(shù)返回后的下一行指令地址也保存在棧幀,棧回溯就是分析這些棧上面函數(shù)地址,還原函數(shù)運(yùn)行軌跡的過(guò)程。


      函數(shù)A調(diào)用函數(shù)B,0x40056a是函數(shù)B結(jié)束后返回的地址

      棧回溯經(jīng)常和Hook一起配合,當(dāng)Hook住某個(gè)函數(shù)后,輸出它的調(diào)用棧,能更進(jìn)一步分析問(wèn)題歸因,如果對(duì)性能要求不高,可以直接使用libunwind庫(kù),它在不需要開(kāi)-fno-omit-frame-pointer編譯選項(xiàng)、dwarf調(diào)試信息的情況下,也能輸出函數(shù)地址,然后我們通過(guò)符號(hào)表將函數(shù)名解析出來(lái)。

          // 棧回溯上下文結(jié)構(gòu) struct BacktraceState {     void **current;     void **end; }; static _Unwind_Reason_Code UnwindCallback(struct _Unwind_Context *context, void *arg) {     BacktraceState *state = static_cast (arg);     uintptr_t pc = _Unwind_GetIP(context);     if (pc)     {         if (state->current == state->end)         {             return _URC_END_OF_STACK;         }         else         {             *state->current++ = reinterpret_cast
      
       (pc);         }     }     return _URC_NO_REASON; } size_t CaptureBacktrace(void **buffer, size_t max) {     BacktraceState state = {buffer, buffer + max};     _Unwind_Backtrace(UnwindCallback, &state);     return state.current - buffer; } void DumpBacktrace(std::ostream &os, void **buffer, size_t count) {     for (size_t idx = 0; idx < count; ++idx)     {         constvoid *addr = buffer[idx];         constchar *symbol = "";         Dl_info info;         if (dladdr(addr, &info) && info.dli_sname)         {             symbol = info.dli_sname;         }         // 這里將函數(shù)的絕對(duì)地址轉(zhuǎn)換為相對(duì)地址         uintptr_t relative = (uintptr_t)addr - (uintptr_t)info.dli_fbase;         os << "  #" << std::setw(2) << idx << ": " << info.dli_fname << " " << (void *)relative << "\n";     } } // 經(jīng)封裝后的打印函數(shù) void PrintStacktrace(const size_t count) {     void* buffer[count];     std::ostringstream oss;     DumpBacktrace(oss, buffer, CaptureBacktrace(buffer, count));     __android_log_print(ANDROID_LOG_INFO, "TestHook", oss.str().c_str()); }
      

      棧回溯的步驟雖然看起來(lái)繁瑣,但只要經(jīng)過(guò)封裝后,使用起來(lái)其實(shí)和在C# 里面一樣方便,下一步我們來(lái)試一下。

      八、實(shí)戰(zhàn):為IO調(diào)用加入棧統(tǒng)計(jì)

      沿用之前的PLT Hook的例子,這次我們將調(diào)用堆棧打印出來(lái):


      調(diào)用封裝好的PrintStacktrace


      現(xiàn)在打印日志里多了調(diào)用棧函數(shù)地址

      使用NDK目錄下的addr2line.exe對(duì)這些地址進(jìn)行解析,最終得到我們想要的結(jié)果。

      LocalFileSystemPosix::Open(FileEntryData&, FilePermission, FileAutoBehavior) zip::CentralDirectory::Enumerate(bool (*)(FileSystemEntry const&, FileAccessor&, char const*, zip::CDFD const&, void*), void*) VerifyAndMountObb(char const*) MountObbs() UnityPause(int) UnityPlayerLoop() nativeRender(_JNIEnv*, _jobject*)

      九、結(jié)語(yǔ)

      本文從以性能優(yōu)化分析目的入手,介紹了常用的逆向分析手段 —— 注入、Hook、堆棧回溯,這里只是淺顯地聊了一下運(yùn)用場(chǎng)景,事實(shí)上每一個(gè)坑都能挖到很深,比如注入與反注入,如何對(duì)競(jìng)品進(jìn)行注入,Hook的相關(guān)調(diào)試方法、內(nèi)存分析、更高性能的棧回溯、聚合顯示(火焰圖)等等。

      之所以總結(jié)此文,是因?yàn)槲以诮诘墓ぷ髦懈杏X(jué)到,了解一點(diǎn)逆向分析的知識(shí),對(duì)性能優(yōu)化、程序調(diào)試方面很有好處,也不局限于游戲開(kāi)發(fā)領(lǐng)域,技多不壓身。

      參考

      [1] 使用Simpleperf+Timeline診斷游戲卡頓


      https://zhuanlan.zhihu.com/p/666443120

      文末,再次感謝其樂(lè)陶陶 的分享, 作者主頁(yè):https://www.zhihu.com/people/jun-yan-76-80, 如果您有任何獨(dú)到的見(jiàn)解或者發(fā)現(xiàn)也歡迎聯(lián)系我們,一起探討。(QQ群: 793972859 )。

      近期精彩回顧

      【學(xué)堂上新】

      【學(xué)堂上新】

      【學(xué)堂上新】

      【萬(wàn)象更新】

      特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

      Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

      相關(guān)推薦
      熱點(diǎn)推薦
      黎家盈 75 歲父母來(lái)北京探望她,丈夫放棄香港事業(yè),家人付出有多

      黎家盈 75 歲父母來(lái)北京探望她,丈夫放棄香港事業(yè),家人付出有多

      樂(lè)天閑聊
      2026-05-26 02:56:39
      女干部的金耳環(huán)!

      女干部的金耳環(huán)!

      新動(dòng)察
      2026-05-25 16:18:44
      身高僅1米6!比NBA平均矮42公分,他憑什么在巨人聯(lián)盟打14年?

      身高僅1米6!比NBA平均矮42公分,他憑什么在巨人聯(lián)盟打14年?

      青梅侃史啊
      2026-05-25 22:11:43
      阿根廷天塌了?梅西世界杯前18天突遭傷退,大腿不適牽動(dòng)舉國(guó)心

      阿根廷天塌了?梅西世界杯前18天突遭傷退,大腿不適牽動(dòng)舉國(guó)心

      田先生籃球
      2026-05-25 11:12:57
      血虧!曼聯(lián) 8600 萬(wàn)回購(gòu)格林伍德!當(dāng)初親手趕走,現(xiàn)在跪著求回來(lái)

      血虧!曼聯(lián) 8600 萬(wàn)回購(gòu)格林伍德!當(dāng)初親手趕走,現(xiàn)在跪著求回來(lái)

      奶蓋熊本熊
      2026-05-26 04:28:06
      與女星同居12年,多次求婚被拒,轉(zhuǎn)身娶世界冠軍定居香港兒女雙全

      與女星同居12年,多次求婚被拒,轉(zhuǎn)身娶世界冠軍定居香港兒女雙全

      白面書(shū)誏
      2026-05-25 20:34:59
      互相出軌各玩各的!結(jié)婚32年后,蔣雯麗夫婦隱居美國(guó)活成了這樣

      互相出軌各玩各的!結(jié)婚32年后,蔣雯麗夫婦隱居美國(guó)活成了這樣

      阿斚田侃故事
      2026-05-25 14:10:56
      紀(jì)實(shí):河南“惡魔首富”吳天喜,年近60卻死性不改,是噩夢(mèng)般的存在

      紀(jì)實(shí):河南“惡魔首富”吳天喜,年近60卻死性不改,是噩夢(mèng)般的存在

      卡西莫多的故事
      2025-01-06 10:41:00
      鹿晗關(guān)曉彤分手了?知名經(jīng)紀(jì)人曝兩人感情內(nèi)幕,說(shuō)出不官宣原因

      鹿晗關(guān)曉彤分手了?知名經(jīng)紀(jì)人曝兩人感情內(nèi)幕,說(shuō)出不官宣原因

      可愛(ài)的巴比龍
      2026-05-26 03:12:26
      沖上熱榜!鄭欽文慘敗產(chǎn)生連鎖反應(yīng):排名跌出百大+或淪為中國(guó)6姐

      沖上熱榜!鄭欽文慘敗產(chǎn)生連鎖反應(yīng):排名跌出百大+或淪為中國(guó)6姐

      大秦壁虎白話體育
      2026-05-25 19:49:55
      樂(lè)極生悲,莫斯科斯巴達(dá)球員在奪得俄羅斯杯慶祝時(shí)不慎打碎獎(jiǎng)杯

      樂(lè)極生悲,莫斯科斯巴達(dá)球員在奪得俄羅斯杯慶祝時(shí)不慎打碎獎(jiǎng)杯

      懂球帝
      2026-05-26 00:52:34
      U17國(guó)足奪亞,沒(méi)想到日本隊(duì)集體做出同一舉動(dòng),原來(lái)范志毅沒(méi)說(shuō)錯(cuò)

      U17國(guó)足奪亞,沒(méi)想到日本隊(duì)集體做出同一舉動(dòng),原來(lái)范志毅沒(méi)說(shuō)錯(cuò)

      以茶帶書(shū)
      2026-05-25 20:06:00
      周杰倫代言汽車(chē)品牌!

      周杰倫代言汽車(chē)品牌!

      電動(dòng)知家
      2026-05-25 19:25:24
      中國(guó)將迎來(lái)前所未有的死亡高峰,專家得出答案:是這些因素導(dǎo)致的

      中國(guó)將迎來(lái)前所未有的死亡高峰,專家得出答案:是這些因素導(dǎo)致的

      老稝科普君
      2026-05-24 19:19:21
      庫(kù)里:NBA真正影響全世界的只有4個(gè)人,我還不夠資格!

      庫(kù)里:NBA真正影響全世界的只有4個(gè)人,我還不夠資格!

      錢(qián)說(shuō)體育
      2026-05-25 13:00:31
      號(hào)稱是“凈化靈魂”的地方,卻暗藏罪惡,布達(dá)拉宮里面有什么?

      號(hào)稱是“凈化靈魂”的地方,卻暗藏罪惡,布達(dá)拉宮里面有什么?

      抽象派大師
      2026-05-17 02:15:03
      庾澄慶《歌手》首場(chǎng)遭淘汰,洪濤回應(yīng):難以理喻,請(qǐng)他是證明“姜還是老的辣”而不是爆冷;節(jié)目沒(méi)有黑幕

      庾澄慶《歌手》首場(chǎng)遭淘汰,洪濤回應(yīng):難以理喻,請(qǐng)他是證明“姜還是老的辣”而不是爆冷;節(jié)目沒(méi)有黑幕

      新民周刊
      2026-05-25 12:27:42
      選秀順位急劇下滑!張子宇從榜眼跌出首輪 她為何被WNBA看衰?

      選秀順位急劇下滑!張子宇從榜眼跌出首輪 她為何被WNBA看衰?

      大嘴爵爺侃球
      2026-05-25 17:04:54
      要打?奉陪到底!中方出手,拒絕收回港口租約,澳防長(zhǎng)咬死裝委屈

      要打?奉陪到底!中方出手,拒絕收回港口租約,澳防長(zhǎng)咬死裝委屈

      激情與榮耀并存
      2026-05-25 11:16:33
      秦志戩動(dòng)真格!4大老將遭棄用,3大新星強(qiáng)勢(shì)上位,洛奧風(fēng)向大變

      秦志戩動(dòng)真格!4大老將遭棄用,3大新星強(qiáng)勢(shì)上位,洛奧風(fēng)向大變

      領(lǐng)悟看世界
      2026-05-26 01:16:58
      2026-05-26 05:12:49
      侑虎科技UWA incentive-icons
      侑虎科技UWA
      游戲/VR性能優(yōu)化平臺(tái)
      1578文章數(shù) 987關(guān)注度
      往期回顧 全部

      科技要聞

      華為:沒(méi)有先進(jìn)光刻機(jī)也能造出高端芯片

      頭條要聞

      伊朗媒體披露最高領(lǐng)袖就醫(yī)情況

      頭條要聞

      伊朗媒體披露最高領(lǐng)袖就醫(yī)情況

      體育要聞

      如果不好好守門(mén),他可能早就繼承家業(yè)了

      娛樂(lè)要聞

      李晨鄭愷跑男停宣:12年元老被邊緣化

      財(cái)經(jīng)要聞

      起底煤礦“暗面”:假整改、假數(shù)據(jù)

      汽車(chē)要聞

      啟境GT7定檔5月29日預(yù)售 提供三電機(jī)版本

      態(tài)度原創(chuàng)

      藝術(shù)
      家居
      健康
      時(shí)尚
      軍事航空

      藝術(shù)要聞

      于東來(lái)計(jì)劃建小區(qū),建筑設(shè)計(jì)用材都公開(kāi),地產(chǎn)界震動(dòng)?

      家居要聞

      生與命相依 舊公寓改造

      幾百塊一瓶的外泌體精華,涂臉上是“智商稅”嗎?

      Bella的戛納之旅,次次“神級(jí)”表現(xiàn)

      軍事要聞

      俄軍出動(dòng)“榛樹(shù)”導(dǎo)彈襲擊烏克蘭

      無(wú)障礙瀏覽 進(jìn)入關(guān)懷版 主站蜘蛛池模板: 天堂在线V| 午夜天堂精品一区二区| 国产在线无码精品无码| 国产亚洲精品VA片在线播放 | 韩国精品一区二区三区四区| 国产成人精品高清不卡在线| 91艹逼| a毛片在线播放| 久热这里有精品视频在线| 曰韩三级无码久久探| 成人欧美一区二区三区在线| 国产乱人乱偷精品视频a人人澡| 国产精品亚洲综合久久小说| 人妻无码av中文系列久| 开心一区二区三区激情| 午夜福利小视频400| 色色午夜天| 曰韩高清砖码一二区视频| 狠狠色综合一区二区| 艳妇乳肉豪妇荡乳| 久久精品国产一区二区三区| 无码人妻少妇色欲av一区二区| 998av资源影音先锋| 在线无码国产精品亚洲а∨| 黃色一级毛片9299步免费| 平邑县| 2020精品极品国产色在线观看| 蜜桃臀av一区二区三区| 天天躁日日躁狠狠躁av麻豆| 欧美粗大猛烈老熟妇| avav我爱色| 久久久精品午夜免费不卡| 真人性囗交视频| 性爽交免费视频| 国产麻豆精品手机在线观看| av手机版天堂网免费观看| 久久久久久久综合综合狠狠| 中文字幕无码日韩欧免费软件 | 秘密教学57薇娅求子豪免费 | 青青草无码免费一二三区| 伊人久久大香线蕉成人|