首页
社区
课程
招聘
[原创] 初窺NP手遊保護
发表于: 2025-9-15 20:56 6748

[原创] 初窺NP手遊保護

2025-9-15 20:56
6748

某天在應用商店挑選「幸運兒」時,一不小心選到了NP保護的,我想這便是天意。

自那天起便開啟了這段漫長的分析之旅,數以百次的調試,最後留下本文。

樣本: anAuZ29vZHNtaWxlLnRvdWhvdWxvc3R3b3JkX2FuZHJvaWQ=

NP的關鍵so為libcompatible.solibstub.solibengine.so,三者之間環環相扣,先看libcompatible.so

通過readelf找到.init_proc0x154028

發現.init_proc被一些導出符號分割了,導致IDA無法F5。

用乐佬那篇文章的解決思路,手動把位於.init_proc範圍內的導出符號置空即可。

patch後就能順利F5了,發現.init_proc中有如下虛假控制流。

bcf的解決思路可參考oacia大佬的這篇文章:a42K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2j5h3y4A6j5g2)9J5k6h3c8W2N6W2)9J5c8X3!0D9L8s2k6E0i4K6u0V1M7%4c8#2k6s2W2Q4x3V1j5`.

計算獲取libcompatible.so的基址,保存在libcompatible_base中。然後調用give_load_seg_rwx()

give_load_seg_rwx()的實現如下,根據libcompatible_base解析 & 遍歷phdr,記錄最後一個loadable seg的結束位置,記為last_loadseg_end

last_loadseg_end對齊內存頁大小後的值作為mprotect()的size,保證基本上全部代碼段、數據段都有rwx權限。

回到.init_proc繼續向下看。

調用了mmap系統調用,映射了一頁rwx權限的內存,記為這片內存為mmap_buf

調用decrypt_something1(),解密了一些數據,結果存放在data_from_dec中。

調用decrypt_something2(),根據data_from_dec來解密args[1]。記解密後的數據為data_from_dec2

然後會根據data_from_dec2來對mmap_buf賦值。

由於mmap_buf有執行權,因此嘗試將賦予mmap_buf的數據解析為代碼,發現是svc。

之後svc會被保存到全局變量中。

完成svc的賦值後,調用了cache_maintenance()來更新mmap_buf的cache緩存。

調用decrypt_some_str()解密了一些字符串,保存在全局變量中。

它的字符串解密邏輯如下:

解密了一些ro.屬性,大概是在做兼容。

之後獲取了當前so的.dynamic段。

解析.dynamic,獲取重定向相關信息,如RELA表,JMPREL表等。

清空重定向表。

最後會分別調用I1 ~ I3這3個導出函數( 是在上面被解密的 ),調用後會把函數加密回去( 那些異或操作一開始以為是解密,後來才發現是加密 )。

簡單看了下I1I2,沒有太特別的地方,重點在I3這個導出函數。

sub_7A635BF48C()設置了某些導出符號的其中幾個字節,不知在干什麼。

之後mmap了一片rw權限的內存,記為mmap_buf2

mmap_buf2進行賦值。

之後會來到下圖的地方,若F7單步步入紅框慢慢跟,IDA似乎會crash,而F8直接步過則不會?

把某個函數賦給了some_func1變量

之後就來到第1處fla,顯然是關鍵邏輯處。

簡單看看這個fla。

這個地方在解密一段代碼,把v144指向的地址減去基址,得到的偏移記為off

從dump出來的libcompatible.so中搜off,發現offJNI_OnLoad()中,由此可知上述解密的代碼正是JNI_OnLoad()

第2處解密JNI_OnLoad()的地方,由此可知JNI_OnLoad()是分段解密的。

第3處解密JNI_OnLoad()的地方。

JNI_OnLoad()的解密應該只分成了3段,解密完後會調用cache_maintenance(),似乎每次解密完代碼後都會調用該函數做cache相關的處理。

cache_maintenance()args[0]是被解密代碼的起始地址,args[1]是結束地址,這個地址範圍中包含多個解密後的函數。

然後就是第2處fla,記為fla2

同樣是一段代碼解密邏輯,解密的是0xF70D0處的代碼。

解密後發現只是一個功能函數。

fla2中第2處代碼解密邏輯。

fla2中第3處代碼解密邏輯。

注:上述的代碼解密邏輯可能會被交替調用來對同一個函數進行解密。

解密完成後,同樣調用了cache_maintenance()

然後調用了check_something()進行一些檢測,其中又大概可分成check1() ~ check5()5個小檢測。

先看check1(),一開始調用了prctl("PR_SET_DUMPABLE"),不知為何。

然後調用newfstatat系統調用獲取/proc/<pid>/environ相關信息。

statbuf設置為struct stat statbuf類型後,可以看出調用newfstatat()是為了獲取時間戳來實現時間檢測。

接下來看check2()

解密了"magisk",然後調用openat系統調用打開"/proc/self/mounts",顯然是在檢測magisk。

調用read系統調用讀取/proc/self/mounts,每次讀2048字節,其中包含換行符,要手動處理。

處理完後就是檢查/proc/self/mounts每行是否包含magisk字樣,以此來檢測magisk。

然後check3()是經典的root檢測。

check4()是動調檢測。

最後是check5()

check5_func1()打開了/proc/self/maps,解密了解析maps文件的格式化字符串,保存在a1中。

check5_func2()調用read系統調用讀取maps文件,同樣手動處理換行符後,調用自實現的sscanf解析maps信息,最後保存到a1中。

調用完check5_func2()後,解密出了"/system/bin/app_process"字串,然後與maps_lib_path對比。

這裡是為了匹配maps中的/system/bin/app_process

匹配成功後,調用process_app_process()

process_app_process()會遍歷內存中的/system/bin/app_process64,看看其中是否存在magisk字串。

process_app_process()檢查完之後,會調用check5_func3()

check5_func3()同樣是一些magisk檢測,如下:

至此分析完check_something()

回到I3函數向下看。

有個while循環不斷從一個類似函數列表的地方取函數並調用,這個函數列表大概就是解密後的.init_array

.init_array[0]中調用了unsetenv("LD_PRELOAD"),這大概是一種反注入的機制。unsetenv()還會再遍歷一次PATH環境變量,確保LD_PRELOAD真的被unset掉,否則會直接exit()

除了.init_array[0]外,其他.init_array函數似乎都與檢測無關。

由上述分析可知,I3函數執行完後,JNI_OnLoad()也被解密完成。因此在那時機下斷點跳過去分析JNI_OnLoad()

開始分析JNI_OnLoad()

調用了mprotect系統調用,賦予某片內存rwx的權限。

保存了JNI_OnLoad的前0x10字節,暫時未知用來做什麼。

然後就是熟悉的控制流。

同樣是一些函數解密的邏輯。

最終同樣會調用cache_maintenance()

之後調用了sub_777F32BB58(),其中會間接調用a1 + 48指向的函數。

跟進去後發現是GetEnv()

然後又判斷了一次package name是否以_zygote結尾。

之後調用了JNI_OnLoad_func1()進行一些檢測。

JNI_OnLoad_func1()中解密了以下字符串:( 都是模擬器的特徵 )

檢測的邏輯同樣是按上述方式解析/proc/self/maps後,看看是否存在這些so,是則代表是模擬器。

之後反射調用了一個Java層的函數。

發現只是一個固定返回true函數?

然後動態注冊了一些JNI函數。

第1個register_natives()注冊了以下Java類的native函數:

第2個register_natives()注冊了以下Java類的native函數:

然後又解密了一個函數( 下圖的sub_777E313F98() ) ,記該函數為JNI_OnLoad_decfunc1()

進行了一些運算後,調用了KM4PI0Z7J8QMILO5G6P6()

KM4PI0Z7J8QMILO5G6P6()記錄了以下目錄的「最後存取時間」之和,但不知有什麼用。

之後又在一處fla中解密了某個函數,記該函數為big_func()

之所以叫big_func(),是因為該函數的F5偽代碼有六千多行。

一開始解密了一些與libc相關的字串,通過sprintf()組裝後傳入了parse_libc()

parse_libc()先從/proc/self/maps獲取libc.so的相關信息,然後調用do_parse_libc()進行解析。

do_parse_libc()開頭解析了libc的dynamic。

do_parse_libc()最後分別調用了get_libc_info()來將ELF GNU Hash Table和dynamic等信息保存在args[0]中。

然後調用save_some_libc_sym()獲取了libc中的一些符號偏移,如clone()__libc_sysinfo_ZL13g_thread_list

回到big_func()繼續向下看。之後調用了lookup_libc_sym()

lookup_libc_sym()中調用了find_symbol_by_name()來根據函數名獲取對應的符號地址( 原理是gnu hash ),保存在全局變量g_libc_funcs中。

之後又解密了一些函數來加載自己的libc,主要邏輯在load_mylibc()中,加載後的libc記為mylibc

load_mylibc()主要干了以下事情:

注:分析過程中會發現在LoadSection()ClearShdr()最後都有以下函數調用,其args[3]似乎就代表了所在函數的功能。

load_mylibc()執行完之後,從mylibc獲取了一些函數單獨保存下來,如malloccallocrealloc等等。

之後調用prepare_for_inline_hook()來保存指定mylibc函數的前0x32字節,結果保存在args[0]中,然後傳入inline_hook()進行hook。

以mylibc的calloc()為例,在inline_hook()後,前0x10字節被改為跳到原libc的calloc()

之後又繼續從mylibc獲取了一堆函數單獨保存到全局變量中,不一一列出了。

但獲取的目的並不是為了像上面那樣inline hook,而大概是之後會用到,所以提前保存下來。

big_func()執行完後,回到JNI_OnLoad_decfunc1()

同樣的形式解密了一段代碼。

check_xposed()中遍歷了maps,看看是否存在XposedBridge.jar

之後會來到一個反調試的函數,記為anti_debugging()

調用mylibcpthread_create()創建了一個線程。

調用mylibcfork()創建了兩個子線程,之後調用signal(17, 1)忽略子線程結束時送出的SIGCHILD信號。

嘗試動調此處邏輯,但總會發生一些非預期的結果,因此無法詳細分析anti_debugging()的具體實現原理。

唯一確定的是它調用了兩次mylibc的fork(),使得此時機後將IDA無法attach,記這種反調試為三進程保護。

之後調用mylibc裡的pthread_create()創建一個線程,線程回調函數記為JOdf1_pthread_func3()

一開始調用了check5() ( 上面已經分析過該函數,不再重複 )。

然後調用NativeBridge_check()進行NativeBridge注入檢測。

NativeBridge注入檢測的原理參考這篇文章,檢測流程如下:

JNI_OnLoad_decfunc1()執行完後,回到JNI_OnLoad(),又調用了mylibcpthread_create()創建了線程。

之後會間接調用一個不正常地址導致SIGSEV?但pass to app後可以繼續執行,過段時間後才會真正crash?

要先bypass掉libcompatible.so的反調試,也能繼續動調後面的libstub.so

嘗試直接patch掉anti_debugging()

但報了SIGSEGV的錯,報錯時的PC在0x7130,十分奇怪。

用frida + IDA動調後發現報錯點在下圖這裡。

這種情況有兩種可能性:

而情況1基本可以排除掉,因為直接動調( 沒有patch anti_debugging() ),走到上圖位置時同樣是0x7130,而且用trace排查時,顯示的也是0x7130

因此大概率是情況2,而且調用的大概率也是mylibcsigaction

嘗試hook mylibc的sigaction(),但沒有觸發。

改為hook原libc的sigaction,反而有觸發,看來NP無法使用mylibc的sigaction()來注冊信號回調?

輸出如下,0xb正是SIGSEGV,信號回調函數在libcompatible.so!0xaa994

0xaa994如下,記為SIGSEGV_cb()

sub_187310()中可以看到0x7130

SIGSEGV_cb()最終會根據fault address分發不同的函數,之後會看到。

在bypass掉三進程保護後,終於可以動調分析後續的流程,首先是libstub.so的加載。

libstub.so的.init_proc中會調用libcompatible.so!SoLibraryStart()來解密。

SoLibraryStart()中的qword_1B41E0固定是0x4580,因此必然會觸發SIGSEGV的信號回調SIGSEGV_cb()

SIGSEGV_cb()會根據導致異常的地址來執行對應的函數,如0x4580會執行func_4580()

打斷點跳到func_4580()進行分析。

調用了check_and_decrypt_libstub()

check_and_decrypt_libstub()中會先調用check_enc_flag()確定libstub.so是加密的。

check_enc_flag()具體實現如下,打開本地的libstub.so並檢查最後20字節是否與固定的加密標誌相等。

decrypt_libstub_data()一開始先獲讀取了libstub[0:0xB758],然後再讀取libstub[0x1CAA8: 0x1CAA8 + 0x3EFEE],記為後者為libstub_enc_data1

注:從010可知0x1CAA8正好在section header後面。

第1處解密libstub_enc_data1的地方。

第2處解密libstub_enc_data1的地方。

第3處解密libstub_enc_data1的地方。

調用LZ4_decompress_fast()對解密後的libstub_enc_data1進行解壓。

解壓後的數據如下,可以看到包含一些重定向信息,記為dec_data1

讀取了libstub[0x5BA96:0x5BA96 + 0x15C0],記為libstub_enc_data2,然後解密,再解壓。

解壓後的數據如下,可以看出應該是符號表,記為sym

讀取了libstub[0x5D056:0x5D056+ 0x1230],記為libstub_enc_data3,然後解密,再解壓。

解壓後的數據如下,可以看出是字符串表,記為strtab

讀取了libstub[0x5E286:0x5E286 + 0x29B0],記為libstub_enc_data4,然後解密,再解壓。

解壓後的數據如下,可以看到同樣是一些重定向信息( 403重定向 ),記為relocate1

讀取了libstub[0x60C36:0x60C36 + 0x4F0],記為libstub_enc_data5,然後解密,再解壓。

解壓後的數據如下,可以看到同樣是一些重定向信息( 402重定向 ),記為relocate2

讀取了libstub[0x61126:0x61126 + 0x30],記為libstub_enc_data6,然後解密,再解壓…

解壓後的數據如下,可以看出是libstub.so的依賴庫。

最後讀取了libstub[0x61146:0x61146 + 0x20],但似乎沒有用到,大概只是加密數據的結束標誌?

至此大致分析完check_and_decrypt_libstub()。回到func_4580()

調用set_w_perm_to_libstub()賦予libstub.so可寫的權限。dlopen_needs()會調用dlopen()加載libstub.so的所有DT_NEED庫。

MEMORY[0x7510]()會觸發SIGSEGV_cb(),然後跳到func_7510()

看到"ldrRestoreDynSymInfo",見名知意,大概是在恢復libstub.so的一些動態符號信息。

忽略前面一些不太知道在干什麼的邏輯後,來到下圖這裡,解密了一些符號名。

然後會對比libstub.so的字符串表( 上面解密出來的那個 ),若包含上述的符號名,則會把對應函數( 如下圖的some_func2(),它是libcompatible.so的函數 )保存到某個地方。

猜測是libstub.so之後會用到libcompatible.so中的一些函數,因而用這種方式提前保存函數地址到某處。

func_7510()之後,回到func_4580()會執行重定向的邏輯,然後調用.init_array的函數。

一開始解密了"dlopen""dlsym""il2cpp.so"等字符串,不知道干什麼。

然後就是熟悉的重定向操作:

注:重定向的對象並非maps中的libstub.so,而是內存中的libstub.so

通過maps查看內存中的libstub.so範圍,然後把這片內存dump下來,記為libstub_dump.so

調用libstub.so.init_array函數。

.init_array的偏移為0x8FDE0

dec_data1 dump下來會發現,其中包含了relocate1relocate2,還有.dynamic信息。

至於解密後的代碼段和數據段,應該已經在libstub_dump.so中,但libstub_dump.so中並不包含strtabsym和.dynamic的信息。

也不包含shdr和shstrtab字符串表,這兩者可從原libstub.so中獲取,前者在修復時直接覆蓋到原位置,後者隨便寫到最後的一片空區域即可。

從原libstub.so提取shstrtab

section修複,大概只有.dynstr.dynamic.shstrtab是必要的,第0個section要為0,拉入IDA時才不會報錯。

把修復後的libstub.so拉入IDA,發現只有少量的符號。

大概只有第1個.init_array函數是檢測的邏輯,同樣也是對環境變量的檢測,具體做法是在unsetenv("LD_PRELOAD")後,遍歷environ數組,若發現其中仍有LD_PRELOAD則直接exit()

保存了一些libdl.solibc.so的函數到某個全局變量中。

嘗試尋找"com/inca/security/DexProtect/SecureApplication"類,但在本例會返回0

動態注冊了"com/inca/security/Native/AppGuardAssistantNative""com/inca/security/AppGuard/TestCase"中的一些JNI函數。

第1處register_func()動態注冊了9個JNI函數,如startEngine()stopEngine()等等。

第2處register_func()動態注冊了4個JNI函數,如下圖所示。

最後創建了兩個線程,暫時不知有什麼用。

startEngine()被控制流混淆了,如下所示。

同時其中充斥著大量的空函數,或許也是一種混淆。

分析的思路是,忽略上面這樣的空函數,關注那些有內容的函數,下斷點跳過去調試。

最終可把stratEngine()分成三部份,第一部份如下。

第二部份。

第三部份。

在這三個部份中,都會調用某片匿名內存中的函數,一開始沒有多想,直接單步跟了進去調試,後來才想起這會不會就是libengine.so

記那片匿名內存為mem_libengine,對比mem_libenginelibengine.so後發現,它們前面的字節的確是一樣的。( 本以為startEngine()會是加載libengine.so的邏輯,其實不然 )。

知道了mem_libengine就是libengine.so後,以此作為入手點,分析哪裡加載的。

libstub.so!JNI_OnLoad leave時機,maps中仍未有mem_libengine。在getVersionsetContext時,maps中有mem_libengine

而在上面的分析中提過,libstub.so!JNI_OnLoad最後創建了一些線程,最終確定大概率是在sub_53AC4中加載的libengine.so

通過frida stalker確定了sub_53AC4中會調用libcompatible.so!0xA1990

接下來看看libcompatible.so!0xA1990是怎麼加載libengine.so的。

首先調用了LoadEngineLibrary(),其中一開始拼接了libengine.so的絕對路徑。

然後調用sys_mmap()映射一片匿名內存,調用sys_lseek() + sys_read()讀取libengine.so

LoadEngineLibrary()之後會來到熟悉的解密函數( 在上方被我命名為check_and_decrypt_libstub )。

注:邏輯基本相同,不再重複分析,將所需數據dump下來。


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 27
支持
分享
最新回复 (43)
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
2
題外話:最近我的Pixel6抽風了, 一開frida就會進入類似關機的狀態, 有無高手知道為什麼?!!!
2025-9-15 20:57
0
雪    币: 132
活跃值: (6362)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
乐佬太顶了
2025-9-15 21:09
0
雪    币: 815
活跃值: (5317)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
ngiokweng 題外話:最近我的Pixel6抽風了, 一開frida就會進入類似關機的狀態, 有無高手知道為什麼?!!!
selinux 
2025-9-15 21:18
0
雪    币: 10
活跃值: (844)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5

感谢分享

最后于 2025-9-15 23:03 被青椒土豆编辑 ,原因:
2025-9-15 21:35
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
6
一只笨猫 selinux
OK, 我明明試試看
2025-9-15 23:03
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
7
青椒土豆 感谢分享
文章最開頭給了包名了, 遊戲版本是1.56.1
2025-9-15 23:04
1
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
8
New对象处 乐佬太顶了
確實
2025-9-15 23:05
0
雪    币: 22
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
大手子太强了
2025-9-15 23:21
0
雪    币: 100
活跃值: (401)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
prctl("PR_SET_DUMPABLE")应该是为了能成功 inotify /proc/mem
2025-9-15 23:23
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
11
mb_bvvcoitr prctl("PR_SET_DUMPABLE")应该是为了能成功 inotify /proc/mem
學到了
2025-9-15 23:53
0
雪    币: 494
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12

尝试去dump了一下它的符号信息,发现有ptrace占坑但是直接用我写的内核模块就能绕过了,然后就顺利dump

2025-9-15 23:54
1
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
13
安卓逆向test 尝试去dump了一下它的符号信息,发现有ptrace占坑但是直接用我写的内核模块就能绕过了,然后就顺利dump
大佬牛逼
2025-9-15 23:57
0
雪    币: 4596
活跃值: (5884)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
14
喜欢  
2025-9-16 01:10
0
雪    币: 4596
活跃值: (5884)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
15
想问一下,楼主 用的 ida 几, 不知道为啥 我的 ida 老是奔溃
2025-9-16 01:13
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
16
逆天而行 想问一下,楼主 用的 ida 几, 不知道为啥 我的 ida 老是奔溃
經典的7.7, 崩可能是被反調試了
2025-9-16 09:33
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
17
一只笨猫 selinux
我setenforce 0後也還是不行
2025-9-16 09:36
0
雪    币: 815
活跃值: (5317)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
ngiokweng 我setenforce 0後也還是不行[em_006]
frida 更改selinux注入规则
2025-9-16 12:47
0
雪    币: 184
活跃值: (437)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
佬考虑开一个游戏安全的交流群吗?
2025-9-16 15:48
0
雪    币: 104
活跃值: (7189)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
ngiokweng 題外話:最近我的Pixel6抽風了, 一開frida就會進入類似關機的狀態, 有無高手知道為什麼?!!!

优先试第2种方法. 我之前也遇到过类似的问题. 不晓得是否对你有帮助.
1.清除【/data/apex/active/】目录下的【art】关键词的文件重启手机即可恢复正常,有重要数据先备份一下再试。
2.adb卸载adb uninstall com.google.android.art

记得重启手机

最后于 2025-9-16 17:04 被Imxz编辑 ,原因:
2025-9-16 17:04
2
雪    币: 1404
活跃值: (6863)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
21
因为你登陆了google账号 还开了vpn google服务会自动更新art 现在frida不支持最新版本的art,最简单的方法就是刷机
2025-9-16 18:04
2
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
22
Imxz ngiokweng 題外話:最近我的Pixel6抽風了, 一開frida就會進入類似關機的狀態, 有無高手知道為什麼?!!! 优 ...
第2種方法可以, 太感謝了!!!!!!!!
2025-9-16 18:52
0
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
23
method 因为你登陆了google账号 还开了vpn google服务会自动更新art 现在frida不支持最新版本的art,最简单的方法就是刷机
原來如此, 還在想它為什麼突然抽風
2025-9-16 18:53
1
雪    币: 6620
活跃值: (5665)
能力值: ( LV12,RANK:280 )
在线值:
发帖
回帖
粉丝
24
fei3ei 佬考虑开一个游戏安全的交流群吗?
可以啊, 之後搞一個
2025-9-16 18:54
0
雪    币: 146
活跃值: (671)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
ngiokweng 可以啊, 之後搞一個[em_065]
期待一下
2025-9-16 23:45
0
游客
登录 | 注册 方可回帖
返回