国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁 > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

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

0
分享至


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

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

作者主頁:

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

一、前言

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

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

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

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

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

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

Android系統(tǒng)的數(shù)據(jù)基本都能通過讀各種文件實(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)境下編寫一個(gè)動(dòng)態(tài)庫(kù)so文件,這個(gè)腳本利用Java調(diào)試服務(wù)加載我們自己的庫(kù)。這也是RenderDoc、?LoliProfiler、Matrix用的方式,需要應(yīng)用Debug權(quán)限,或者root開全局調(diào)試,或者使用APKTool,解包修改AndroidManifest文件的Debug權(quán)限。


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

這個(gè)腳本用Python封裝了注入過程,在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í)行,我們就可以干自己想干的事情了,這只是打開大門的第一步。

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ù)劫持,兩種常見Hook手段為PLT Hook、Inline Hook。

三、PLT Hook

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


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


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++代碼通過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ù)說xHook的作者后續(xù)開發(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),它是通過對(duì)目標(biāo)函數(shù)地址插入跳轉(zhuǎn)指令實(shí)現(xiàn),理論上可以Hook住任意內(nèi)部函數(shù),功能更為強(qiáng)大,由于涉及到在不同CPU架構(gòu)上的運(yùn)行狀態(tài)機(jī)器碼修改,看起來很復(fù)雜,其實(shí)一點(diǎn)也不簡(jiǎn)單,雖兼容性不如PLT Hook,不推薦在生產(chǎn)環(huán)境使用,但作為測(cè)試環(huán)境中的性能工具還是很強(qiáng)的。

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


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

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

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

但是我們常見的libunity.so、libil2cpp.so的符號(hào)表是分離的,可以嘗試用llvm-objcopy合并回去,這里更推薦另一種做法,ShadowHook也可以直接通過函數(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è)地址加起來就行。

動(dòng)態(tài)庫(kù)基地址每次進(jìn)程啟動(dòng)都不一樣,需要我們?cè)诔绦蛑袆?dòng)態(tài)獲取,可以通過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ù)地址

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

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

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

這里以AddComponent函數(shù)為例,做一個(gè)Demo,然后嘗試使用Hook把觸發(fā)的GameObject、組件名字都打印出來,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 ();

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


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

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


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

接下來,我們需要在代理函數(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ù)地址存起來,直接調(diào)用,我管這叫“他山之石,可以攻玉”。


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

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

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

     "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ù)詳情,利用這些信息,接下來就可以做很多事情了,我們現(xiàn)在可以幾乎Hook任意函數(shù)!


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

七、?;厮?/blockquote>

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


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

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

    // ?;厮萆舷挛慕Y(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()); }

?;厮莸牟襟E雖然看起來繁瑣,但只要經(jīng)過封裝后,使用起來其實(shí)和在C# 里面一樣方便,下一步我們來試一下。

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

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


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

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

參考

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


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

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

近期精彩回顧

【學(xué)堂上新】

【學(xué)堂上新】

【學(xué)堂上新】

【萬象更新】

特別聲明:以上內(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)推薦
成龍承認(rèn)現(xiàn)在最怕的不是死,是手機(jī)不響,表示兒子3年沒有聯(lián)系

成龍承認(rèn)現(xiàn)在最怕的不是死,是手機(jī)不響,表示兒子3年沒有聯(lián)系

阿廢冷眼觀察所
2026-01-09 14:12:26
“浙BA”八強(qiáng)格局已定:縣隊(duì)為何能與設(shè)區(qū)市隊(duì)平分席位?

“浙BA”八強(qiáng)格局已定:縣隊(duì)為何能與設(shè)區(qū)市隊(duì)平分席位?

澎湃新聞
2026-01-09 13:38:27
每體:巴薩冬窗可能外租貝爾納爾讓他獲得時(shí)間,赫羅納最積極

每體:巴薩冬窗可能外租貝爾納爾讓他獲得時(shí)間,赫羅納最積極

懂球帝
2026-01-10 02:51:31
哈佛發(fā)現(xiàn):高血脂不用治,治好都是誤診?告訴您5個(gè)血脂真相!

哈佛發(fā)現(xiàn):高血脂不用治,治好都是誤診?告訴您5個(gè)血脂真相!

岐黃傳人孫大夫
2026-01-08 10:06:20
全線爆發(fā)!油價(jià)直線拉升,白銀大漲,美股集體飄紅!

全線爆發(fā)!油價(jià)直線拉升,白銀大漲,美股集體飄紅!

證券時(shí)報(bào)e公司
2026-01-09 23:38:37
周六007亞洲杯 23:伊朗 U23 對(duì)陣烏茲別克 U23,強(qiáng)強(qiáng)對(duì)決分析!

周六007亞洲杯 23:伊朗 U23 對(duì)陣烏茲別克 U23,強(qiáng)強(qiáng)對(duì)決分析!

一瓶卸妝水就足以毀你容
2026-01-10 05:40:03
快船迎來沖附加賽的最佳時(shí)機(jī),未來10場(chǎng)賽程輕松,保10爭(zhēng)9

快船迎來沖附加賽的最佳時(shí)機(jī),未來10場(chǎng)賽程輕松,保10爭(zhēng)9

摸神drose
2026-01-09 20:37:00
交易正式完成后,奇才隊(duì)特雷·楊展示了他將來會(huì)穿著的新球衣

交易正式完成后,奇才隊(duì)特雷·楊展示了他將來會(huì)穿著的新球衣

好火子
2026-01-10 02:05:41
高中生扶老人被訛50萬,15年后老人孫子考上清華,在校門口跪下求饒

高中生扶老人被訛50萬,15年后老人孫子考上清華,在校門口跪下求饒

紅豆講堂
2025-07-14 17:21:43
如果3年內(nèi)沒有離開股市的打算,那就買這一種股票,賺到盆滿缽滿

如果3年內(nèi)沒有離開股市的打算,那就買這一種股票,賺到盆滿缽滿

股經(jīng)縱橫談
2026-01-09 17:42:31
關(guān)于現(xiàn)在的女人是否太開放?為什么給男人戴綠帽的越來越多?

關(guān)于現(xiàn)在的女人是否太開放?為什么給男人戴綠帽的越來越多?

戶外小阿隋
2026-01-10 04:21:55
扣押油輪,英美捅了馬蜂窩,土耳其政客:世界將見證中俄伊土聯(lián)盟

扣押油輪,英美捅了馬蜂窩,土耳其政客:世界將見證中俄伊土聯(lián)盟

觸摸史跡
2026-01-09 20:58:43
北京樓市,亦莊標(biāo)桿金茂府已跌破發(fā)行價(jià)

北京樓市,亦莊標(biāo)桿金茂府已跌破發(fā)行價(jià)

焦點(diǎn)直擊
2026-01-09 08:57:35
美橄欖球明星的隱私部位尺寸,被模特前妻公開討論,怒而對(duì)簿公堂

美橄欖球明星的隱私部位尺寸,被模特前妻公開討論,怒而對(duì)簿公堂

譯言
2026-01-07 10:33:38
被曝光后才明白,中國(guó)的錢,究竟去了哪里?

被曝光后才明白,中國(guó)的錢,究竟去了哪里?

復(fù)轉(zhuǎn)這些年
2025-12-27 23:56:37
一夜間,特朗普連發(fā)五道金牌,把“中美博弈”的遮羞布撕得粉碎!

一夜間,特朗普連發(fā)五道金牌,把“中美博弈”的遮羞布撕得粉碎!

百態(tài)人間
2026-01-09 17:11:06
南通最狂黑老大,當(dāng)場(chǎng)有多狂,現(xiàn)在有多涼

南通最狂黑老大,當(dāng)場(chǎng)有多狂,現(xiàn)在有多涼

特特農(nóng)村生活
2026-01-09 12:54:58
楊利偉“成名”背后:妻子做出巨大犧牲,女兒已離世

楊利偉“成名”背后:妻子做出巨大犧牲,女兒已離世

老特有話說
2025-12-14 17:53:35
果然在春曉油田動(dòng)手了!日本對(duì)中方強(qiáng)烈抗議,要求馬上談判!

果然在春曉油田動(dòng)手了!日本對(duì)中方強(qiáng)烈抗議,要求馬上談判!

達(dá)文西看世界
2026-01-09 08:09:34
韓專家金在吉:中國(guó)文化歷史不是上下5000年,韓國(guó)古代屬于中國(guó)

韓專家金在吉:中國(guó)文化歷史不是上下5000年,韓國(guó)古代屬于中國(guó)

史之銘
2025-11-27 03:21:50
2026-01-10 06:27:00
侑虎科技UWA incentive-icons
侑虎科技UWA
游戲/VR性能優(yōu)化平臺(tái)
1538文章數(shù) 986關(guān)注度
往期回顧 全部

科技要聞

市場(chǎng)偏愛MiniMax:開盤漲42%,市值超700億

頭條要聞

媒體稱委內(nèi)瑞拉代總統(tǒng)計(jì)劃13日訪問華盛頓 委方回應(yīng)

頭條要聞

媒體稱委內(nèi)瑞拉代總統(tǒng)計(jì)劃13日訪問華盛頓 委方回應(yīng)

體育要聞

金元時(shí)代最后的外援,來中國(guó)8年了

娛樂要聞

關(guān)曉彤鹿晗風(fēng)波后露面 不受影響狀態(tài)佳

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

投資必看!瑞銀李萌給出3大核心配置建議

汽車要聞

助跑三年的奇瑞 接下來是加速還是起跳?

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

健康
房產(chǎn)
手機(jī)
家居
數(shù)碼

這些新療法,讓化療不再那么痛苦

房產(chǎn)要聞

66萬方!4755套!三亞巨量房源正瘋狂砸出!

手機(jī)要聞

vivo X200T詳細(xì)參數(shù)曝光,X300 Ultra待發(fā)布

家居要聞

木色留白 演繹現(xiàn)代自由

數(shù)碼要聞

銘凡CES 2026新聞稿提及英特爾酷睿Ultra 9 290HX Plus處理器

無障礙瀏覽 進(jìn)入關(guān)懷版