首页
社区
课程
招聘
14
[原创] 記一次對某韓遊的反反調試
发表于: 3天前 4385

[原创] 記一次對某韓遊的反反調試

3天前
4385

樣本:Y29tLndlbWFkZS5uaWdodGNyb3dz

聊點題外話,最近在找工作,一家公司說要搞NP,我果斷拒絕,還有一家公司給了一道面試題,內容是分析一款外掛( 針對他們家遊戲的 )和實現一個有效的外掛功能。當我興致勃勃下載好遊戲後,打開apk的lib目錄一看,發現libtprt.solibtersafe2.so的特徵就知道67了。

眾所周知這是tx的MTP,我自認水平有限是搞不定的了,但還是硬著頭皮分析了一下,主要想分析他的CRC檢測,找到了幾處CRC邏輯,但都不是主要的邏輯,直到最後看到疑似vm虛擬機的東西,感覺他的核心檢測邏輯可能是在vm裡?看之後有沒有機會再分析看看吧。

小小分析完libtprt.so後,道心破碎,於是打算找個簡單點的來玩玩,正好前段時間一位大佬分享了一個樣本,就決定是你的。這是個UE5遊戲,主要看看他的檢測邏輯。

frida注入後過1s左右會直接閃退,打印加載的so,看到只有一個libdxbase.so是APP本身的,顯然檢測邏輯在裡面。

libdxbase.so拉入IDA,沒有報錯,即so大概率沒有加固。

然後習慣先看看init_array,沒有太大發現,但看到decrypt1明顯是字符串解密函數,先記下來。

hook RegisterNatives,看到動態注冊了4個函數,遂一hook看看調用了哪個。

注:記d函數為reg_func_d,其他如此類推。

結果是調用了reg_func_d,但只有Enter而沒有Leave,因此檢測邏輯可能在reg_func_d中。

reg_func_d的邏輯有差不多2000行,懶得靜態一點一點分析了,直接動調看看是在哪裡crash的。

crash的位置是在exit_func(0xFFFFFFFE),而在調用exit_func前進行了一些time diff的操作,並根據time diff來決定是否走到exit_func那部份的邏輯。

本以為上面只是個普通的time diff調試檢測,但frida hook exit_func並打印調用棧後發現是同一個地方,即frida hook時同樣會走到上述位置,然後調用exit_func閃退。

深入分析上圖那部份邏輯,發現一旦走到上圖那位置後,最終必然會走向exit_func。( 原因:sub_8250返回固定值、time diff永遠大於v202 )。

從上圖位置向上尋找「生路」,看到goto LABEL_215,只要想辦法讓執行流進入任意一處goto LABEL_215的邏輯,就能避免走到上面那條「絕路」。

嘗試走紅框那裡的goto LABEL_215,條件1是*(_DWORD *)(import_data + 9972)0,先嘗試滿足這條件。

交叉引用找(_DWORD *)(import_data + 9972)賦值的地方,分析後可知v197是time diff,但具體是什麼東西之間的time diff,並不能從偽代碼裡直接看出。

只能從匯編視圖看,上圖的some_timestamp是由lstatbuf( x1 ) + 0x68賦值。( x0/sbin )

而且[buf + 0x68]的確是在調用lstat後才有值,但buf的結構為struct stat,大小似乎小於0x68,因此buf[0x68]正常來說並不屬於struct stat結構?猜測是內存對齊等原因導致的。

從內存分佈可以看出buf + 0x68的位置應該是struct stat最後一個屬性( struct stat最後3個屬性都是時間 ),代表指定目錄"上次狀態的更改時間"

0x67517B0D轉換下:

/sbinls -l顯示的日期一致。

用同樣方式找到time diff的另一個值,是0x676631AB

/system/libls -l顯示的日期一致。

計算這兩個時間的time diff目的是什麼?

以下是普通Magisk環境的xiaomi手機,可以看到兩者的日期差很遠。

sbin的日期比較近是因為其中有個shamiko文件,大概是啟用/關閉shamiko模塊時都會刷新其日期。

/system/lib的日期是一個超舊的時間。

小結:這部份計算的time diff是/system/lib/sbin之間的"上次狀態的更改時間" time diff,感覺這個time diff應該是在檢測Magisk之類的。

繼續向下看,判斷time diff是否大於0xF4240 sec,是則上述的條件1無法滿足。

0xF4240 sec → 277 hrs 46 min 40 sec,正常手機環境下的time diff應該不會大於這個值。

bypass腳本:直接hook lstat

bypass這處time diff檢測後,Magisk環境的xiaomi手機依然會退出,大概是條件2check1_res == 9 || !check1_res沒有滿足。

check1返回90都能滿足條件2。接下來看看check1都檢測了什麼。

root檢測1:popen("which su")

root檢測2:獲取了一堆可能存在su的路徑,然後調用check_exist_in_different_way檢測指定路徑是否存在。

check_exist_in_different_way內創建了pthread_func2_check_path_exist線程來處理。

其中用了以下方法來檢測傳入路徑是否存在:

openatsyscall(__NR_openat)scandirlstatstataccessreadlink

注:檢測的路徑大概有以下這些

root檢測3:判斷fingerprint中是否包含user-debugeng/Custom Phone

對應的bypass腳本:

上述地方都bypass後,frida終於不再閃退,但畫面上仍顯示ROOTED

j.rjshqqeirnhhbc.mq其實是Magisk隨機的包名,代表其實是Magisk被檢測到。

在bypass frida閃退後,hook decrypt1保存一份相對完整的解密字符串,用以配合分析,記為decrypt_str.log

再次hook那4個動態注冊的函數,會發現除了調用1次reg_func_d外,還不斷地在調用reg_func_preg_func_q,嘗試直接分析後2個函數,但沒有看出什麼。

改變思路,hook Java層的一些退出函數。

發現觸發了System.exit,調用棧如下,是由com.xshield.x.run類調用的。

Java層有混淆,用jeb打開可以默認去除一些簡單混淆( 如字符串混淆 ),方便分析。

com.xshield.x.run向上跟到call_exit_thread_xref2函數,看到"Scanrisk"字符串本以為是相關邏輯,但hook後發現v2 == 0,因此根本不會走任意一處"Scanrisk"

call_exit_thread_xref2u.call_exit_thread_xref1exit

嘗試直接讓call_exit_thread_xref2函數固定返回1,不走原本的邏輯。

結果是畫面不再顯示那個檢測介面,但過一段時間後同樣會退出,調用的是native層的exit_func

由此猜測call_exit_thread_xref2只是構建那個檢測介面的邏輯,真正檢測的地方在另一處。

call_exit_thread_xref2時機打印調用棧,繼續向上跟

com.xshield.k.run如下,被檢測時走的是else分支,嘗試讓它走if分支。

結果同樣是畫面不再顯示那個檢測介面,但過一段時間後同樣會退出。因此還是要從native層入手。

注:da.detectInfo是我手動修改的名字。

全局搜detectInfo ( 不要只按x找交叉引用,不太準 ),找到它是某次reg_func_q調用的返回值。

在其上方是一個while循環,根據特定的邏輯調用da.q ( 即reg_func_q )。

hook da.q,看到某次的result果然是detectInfo

同樣可以見到某次reg_func_q的參數是一堆包名,其中就包含j.rjshqqeirnhhbc.mq

因此可以猜測Magisk的檢測邏輯為:Java層收集安裝APP的包名、路徑等信息 → 調用da.q(ctx, 8, installed_app_info)進行檢查 → 發現j.rjshqqeirnhhbc.mq的某些特徵 → 判斷是Magisk。

根據猜測,嘗試置空da.q參數中的j.rjshqqeirnhhbc.mq,讓它不檢測j.rjshqqeirnhhbc.mq

結果是APP不再顯示那個檢測介面,也不會自動退出,成功bypass掉Magisk檢測。

由此確定了檢測邏輯的確是在da.q(ctx, 8, installed_app_info) ( 必須是args[1]8的情況,才是進行上述檢測 )。

回到native層的reg_func_q分析檢測邏輯的具體實現,動調case 8的情況。

一開始先將傳入的installed_app_info寫入cfdd35cd.dex

其中的內容如下:

最後會創建reg_func_q_pthread1線程,裡面才是真正檢測的地方。

不知什麼原因,動調時始終無法斷在reg_func_q_pthread1裡,因此只好通過hook和配合decrypt_str.log來進行分析( 主要依賴這兩者來確定執行流 )。

打開XXX/base.apk → fd反查( IO重定向檢測 ) → 解析.apk結構 → 獲取其AndroidManifest.xml

判斷AndroidManifest.xml中,是否包含以下權限:

而原版的Magisk正好包含上述的所有權限。

僅憑權限來判斷,不會出現誤殺的情況?答案是會的,我在搜索相關資料時就發現有一堆用戶因被誤殺而在某論壇訴苦的情況,不過那時是21年,現在都25年了這問題應該也改善了不少。

可以看到它加了一些白名單來防止誤殺那些具有上述權限的正常APP。

bypass腳本:hook openat,將/data/app/j.rjshqqeirnhhbc.mq-YbP-hQjkQs0g9MZDz9dD0w==/base.apk重定向為另一個正常apk。

注:這樣重向定不會被上述的fd反查檢測到,另一種Interceptor.replace才會。

上述腳本可以bypass Magisk檢測,但奇怪的是在hook_openat之後,即使下一次沒有hook_openat,依然不會再彈那個檢測介面,也不會退出。

連執行流也改變了,要重裝遊戲才會回復「正常」。感覺是該保護的一種BUG?不太確定。

改AOSP / 修改AndroidManifest.xml,這兩種賦予APP Debuggable權限的方法,都會被檢測到。

上次分析LIAPP時也有類似的檢測,那次沒分析明白,這次再來看看。

注:在分析過程中發現0xB11C類似檢測處理函數,記為mb_detect_handler

hook mb_detect_handler,在參數包含AndroidManifest.xml時打印調用棧。

看到相關邏輯在0xb5bc

0xb5bcdetected_APKMODE,繼續向上跟,看到是由g_APKMODE_flag1g_APKMODE_flag2決定是否創建detected_APKMODE線程的。

x沒有看到g_APKMODE_flag1g_APKMODE_flag2賦值的地方,嘗試使用frida的內存斷點,但沒什麼效果。

改用這篇文章自己實現的frida內存斷點,成功命中:

libdxbase.so!0x18f0c看看( 這裡位於reg_func_d )。

似乎import_data + 9984就是g_APKMODE_flag1 ( 動調後發現的確如此 ),值來源是a19

hook reg_func_d,在enter和leave時分別打印,的確是在leave時才有值,即g_APKMODE_flag都是在reg_func_d中賦值。

a19其實就是reg_func_dargs[18] ( 倒數第3個參數 )。

看Java層是怎樣傳值的,原來是ApplicationInfoflags屬性。

hook Java層的reg_func_d,去掉FLAG_DEBUGGABLE標誌。

結果是遊戲終於不再顯示APKMOD檢測介面,順利bypass它的Debuggable檢測。

總的來說這個保護與之前分析的LIAPP差不多,都不難,只是比較麻煩。

( 各位有好玩的遊戲樣本也可以分享給我,有空會看看的^^ )

[RegisterNatives] java_class: com.xshield.da name: d sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIII)Ljava/lang/String; fnPtr: 0x7137359258  fnOffset: 0x7137359258 libdxbase.so!0x18258  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: o sig: (II)I fnPtr: 0x7137348228  fnOffset: 0x7137348228 libdxbase.so!0x7228  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: p sig: (II)Ljava/lang/String; fnPtr: 0x7137347e78  fnOffset: 0x7137347e78 libdxbase.so!0x6e78  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: q sig: (Landroid/content/Context;ILjava/lang/String;)Ljava/lang/String; fnPtr: 0x7137360d60  fnOffset: 0x7137360d60 libdxbase.so!0x1fd60  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
[RegisterNatives] java_class: com.xshield.da name: d sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIII)Ljava/lang/String; fnPtr: 0x7137359258  fnOffset: 0x7137359258 libdxbase.so!0x18258  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: o sig: (II)I fnPtr: 0x7137348228  fnOffset: 0x7137348228 libdxbase.so!0x7228  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: p sig: (II)Ljava/lang/String; fnPtr: 0x7137347e78  fnOffset: 0x7137347e78 libdxbase.so!0x6e78  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
 
[RegisterNatives] java_class: com.xshield.da name: q sig: (Landroid/content/Context;ILjava/lang/String;)Ljava/lang/String; fnPtr: 0x7137360d60  fnOffset: 0x7137360d60 libdxbase.so!0x1fd60  callee: 0x713736543c libdxbase.so!JNI_OnLoad+0x15e0
[exit_func] call in:
7bb25dab70 is in libdxbase.so offset: 0x1ab70
7c1f940354 is in libart.so offset: 0x140354 
7c1f936470 is in libart.so offset: 0x136470
[exit_func] call in:
7bb25dab70 is in libdxbase.so offset: 0x1ab70
7c1f940354 is in libart.so offset: 0x140354 
7c1f936470 is in libart.so offset: 0x136470
function hook_lstat() {
    let fake_time = Date.now();
    Interceptor.attach(Module.findExportByName(null, "lstat"), {
        onEnter: function(args) {
            this.name = args[0].readCString();
            this.statbuf = args[1];
        },
        onLeave: function(retval) {
            if (this.name == "/system/lib") {
                this.statbuf.add(0x68).writeU64(fake_time++);
                console.log("bypass lstat");
            }
            if (this.name == "/sbin") {
                this.statbuf.add(0x68).writeU64(fake_time++);
                console.log("bypass lstat");
            }
        }
    })
}
function hook_lstat() {
    let fake_time = Date.now();
    Interceptor.attach(Module.findExportByName(null, "lstat"), {
        onEnter: function(args) {
            this.name = args[0].readCString();
            this.statbuf = args[1];
        },
        onLeave: function(retval) {
            if (this.name == "/system/lib") {
                this.statbuf.add(0x68).writeU64(fake_time++);
                console.log("bypass lstat");
            }
            if (this.name == "/sbin") {
                this.statbuf.add(0x68).writeU64(fake_time++);
                console.log("bypass lstat");
            }
        }
    })
}
[decrypt1]  0x3a304 /system/bin/su
[decrypt1]  0x3a2f4 /system/xbin/su
[decrypt1]  0x3a313 /system/bin/.ext/.su
[decrypt1]  0x3a328 /system/xbin/.tmpsu
[decrypt1]  0x3a33c /vendor/bin/su
[decrypt1]  0x3a34b /sbin/su
[decrypt1]  0x3a354 /system/xbin/nosu
[decrypt1]  0x3a366 /system/bin/nosu
[decrypt1]  0x3a377 /system/xbin/su_bk
[decrypt1]  0x3a38a /system/bin/su_bk
[decrypt1]  0x3a39c /system/xbin/xsu
[decrypt1]  0x3a3ad /system/xbin/suu
[decrypt1]  0x3a3be /system/xbin/bstk/su
[decrypt1]  0x3a3d3 /system/RootTools/su
[decrypt1]  0x3a3e8 /data/data/bin/su
[decrypt1]  0x3a3fa /data/data/in/su
[decrypt1]  0x3a40b /data/data/n/bstk/su
[decrypt1]  0x3a420 /data/data/xbin/su
[decrypt1]  0x3a433 /res/su
[decrypt1]  0x3a43b /data/local/bin/su
[decrypt1]  0x3a44e /data/local/su
[decrypt1]  0x3a45d /data/local/xbin/su
[decrypt1]  0x3a471 /system/su
[decrypt1]  0x3a47c /data/su
[decrypt1]  0x3a485 /su/bin/su
[decrypt1]  0x3a490 /su/bin/sush
[decrypt1]  0x3a49d /system/bin/failsafe/su
[decrypt1]  0x3a4b5 /system/sbin/su
[decrypt1]  0x3a4c5 /system/sd/xbin/su
[decrypt1]  0x3a4d8 /system/xbin/noxsu
[decrypt1]  0x3a4eb /magisk/.core/bin/su
[decrypt1]  0x3a500 /sbin/.magisk
[decrypt1]  0x3a50e /sbin/.core
[decrypt1]  0x3b0c3 /system/usr/we-need-root/su
[decrypt1]  0x3b0df /cache/su
[decrypt1]  0x3b0e9 /dev/su
[decrypt1]  0x3a304 /system/bin/su
[decrypt1]  0x3a2f4 /system/xbin/su
[decrypt1]  0x3a313 /system/bin/.ext/.su
[decrypt1]  0x3a328 /system/xbin/.tmpsu
[decrypt1]  0x3a33c /vendor/bin/su
[decrypt1]  0x3a34b /sbin/su
[decrypt1]  0x3a354 /system/xbin/nosu
[decrypt1]  0x3a366 /system/bin/nosu
[decrypt1]  0x3a377 /system/xbin/su_bk
[decrypt1]  0x3a38a /system/bin/su_bk
[decrypt1]  0x3a39c /system/xbin/xsu
[decrypt1]  0x3a3ad /system/xbin/suu
[decrypt1]  0x3a3be /system/xbin/bstk/su
[decrypt1]  0x3a3d3 /system/RootTools/su
[decrypt1]  0x3a3e8 /data/data/bin/su
[decrypt1]  0x3a3fa /data/data/in/su
[decrypt1]  0x3a40b /data/data/n/bstk/su
[decrypt1]  0x3a420 /data/data/xbin/su
[decrypt1]  0x3a433 /res/su
[decrypt1]  0x3a43b /data/local/bin/su
[decrypt1]  0x3a44e /data/local/su
[decrypt1]  0x3a45d /data/local/xbin/su
[decrypt1]  0x3a471 /system/su
[decrypt1]  0x3a47c /data/su
[decrypt1]  0x3a485 /su/bin/su
[decrypt1]  0x3a490 /su/bin/sush
[decrypt1]  0x3a49d /system/bin/failsafe/su
[decrypt1]  0x3a4b5 /system/sbin/su
[decrypt1]  0x3a4c5 /system/sd/xbin/su
[decrypt1]  0x3a4d8 /system/xbin/noxsu
[decrypt1]  0x3a4eb /magisk/.core/bin/su
[decrypt1]  0x3a500 /sbin/.magisk
[decrypt1]  0x3a50e /sbin/.core
[decrypt1]  0x3b0c3 /system/usr/we-need-root/su
[decrypt1]  0x3b0df /cache/su
[decrypt1]  0x3b0e9 /dev/su
function hook_popen() {
    Interceptor.attach(Module.findExportByName(null, "popen"), {
        onEnter: function(args) {
            if (args[0].readCString().indexOf(" su") != -1) {
                console.log("[popen] which su -> which xx");
                Memory.writeUtf8String(args[0], "which xx");
            }
        }
    })
}
 
// hook after dlopen libdxbase.so
function hook_pthread_func2() {
    Interceptor.attach(base.add(0x983C), {
        onEnter: function(args) {
            let check_path = args[0].readPointer().readCString();
            if (check_path.indexOf("/su") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("/su", "/XX"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            if (check_path.indexOf("magisk") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("magisk", "3Ag1sk"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            if (check_path.indexOf("/sbin") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("/sbin", "/ABCD"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            // console.log("[pthread_func2] check: ", check_path);
            this.a0 = args[0];
        }
    })
}
function hook_popen() {
    Interceptor.attach(Module.findExportByName(null, "popen"), {
        onEnter: function(args) {
            if (args[0].readCString().indexOf(" su") != -1) {
                console.log("[popen] which su -> which xx");
                Memory.writeUtf8String(args[0], "which xx");
            }
        }
    })
}
 
// hook after dlopen libdxbase.so
function hook_pthread_func2() {
    Interceptor.attach(base.add(0x983C), {
        onEnter: function(args) {
            let check_path = args[0].readPointer().readCString();
            if (check_path.indexOf("/su") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("/su", "/XX"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            if (check_path.indexOf("magisk") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("magisk", "3Ag1sk"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            if (check_path.indexOf("/sbin") != -1) {
                Memory.writeUtf8String(args[0].readPointer(), check_path.replace("/sbin", "/ABCD"));
 
                // console.log(`[pthread_func2]: ${check_path} -> ${args[0].readPointer().readCString()}`);
            }
            // console.log("[pthread_func2] check: ", check_path);
            this.a0 = args[0];
        }
    })
}
function hook_decrypt1() {
    Interceptor.attach(base.add(0x5E84),{
        onEnter(args){
            this.a3 = args[3];
            this.len = args[4].toInt32();
            this.offset = this.a3.sub(base);
        },
        onLeave(retval){
            let dec_str = this.a3.readCString(this.len);
            console.log("[decrypt1] ", ptr(this.offset), dec_str);
        }
    })
}
function hook_decrypt1() {
    Interceptor.attach(base.add(0x5E84),{
        onEnter(args){
            this.a3 = args[3];
            this.len = args[4].toInt32();
            this.offset = this.a3.sub(base);
        },
        onLeave(retval){
            let dec_str = this.a3.readCString(this.len);
            console.log("[decrypt1] ", ptr(this.offset), dec_str);
        }
    })
}
function printStack(){
    console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()))
}
function hook_leave_java() {
    Java.perform(() => {
        let System = Java.use("java.lang.System");
 
        System.exit.implementation = function() {
            console.log("exit....")
            printStack()
        }
     
        let Process = Java.use("android.os.Process");
     
        Process.killProcess.implementation = function() {
            console.log("killProcess....")
            printStack()
        }
     
    })
  
}
function printStack(){
    console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()))
}
function hook_leave_java() {
    Java.perform(() => {

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 3天前 被ngiokweng编辑 ,原因: 圖
收藏
免费 14
支持
分享
赞赏记录
参与人
雪币
留言
时间
鱼木
+1
谢谢你的细致分析,受益匪浅!
13小时前
墨穹呢
为你点赞!
1天前
Shangwendada
+10
这个讨论对我很有帮助,谢谢!
1天前
mb_vkwwpotw
感谢你的贡献,论坛因你而更加精彩!
1天前
劫__
这个讨论对我很有帮助,谢谢!
2天前
Our_OT
感谢你分享这么好的资源!
2天前
陈可牛
这个讨论对我很有帮助,谢谢!
2天前
SnowFox
感谢你的贡献,论坛因你而更加精彩!
2天前
七星舞月
感谢你的贡献,论坛因你而更加精彩!
2天前
.KK
+5
期待更多优质内容的分享,论坛有你更精彩!
2天前
逆天而行
感谢你的贡献,论坛因你而更加精彩!
2天前
New对象处
+10
为你点赞!
2天前
无事不觉
期待更多优质内容的分享,论坛有你更精彩!
2天前
AL10000
这个讨论对我很有帮助,谢谢!
3天前
最新回复 (24)
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
3天前
0
雪    币: 62
活跃值: (155)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
现在工作不好找哥们,有的做就不错了。
3天前
0
雪    币: 490
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
fairguard加固的游戏可以试一下,反注入也挺强的
3天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
安卓逆向test fairguard加固的游戏可以试一下,反注入也挺强的
有樣本嗎
3天前
0
雪    币: 0
活跃值: (245)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
真厉害啊,都看不懂
2天前
0
雪    币: 126
活跃值: (5016)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
ngiokweng 有樣本嗎[em_065]
游戏逆向这块工作不好找,前阵子遇到一个游戏,jp.gungho.bm,会释放子so来做检测, 有点类似小红书的操作
2天前
0
雪    币: 126
活跃值: (5016)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
好贴
2天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
9
New对象处 游戏逆向这块工作不好找,前阵子遇到一个游戏,jp.gungho.bm,会释放子so来做检测, 有点类似小红书的操作
是的, 感覺逆向都不太好找, 感謝分享樣本
2天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
10
New对象处 游戏逆向这块工作不好找,前阵子遇到一个游戏,jp.gungho.bm,会释放子so来做检测, 有点类似小红书的操作
woc, 才發現之前研究過這家公司的另一款遊戲jp.gungho.padHT, 記得它有一個自定義的section, 還mmap了無數層, 分析了挺久的, 但沒看明白它的檢測邏輯, 大佬帶帶
2天前
0
雪    币: 1841
活跃值: (6916)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
.KK
11
nb 一如既往的强~
2天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
12
.KK nb 一如既往的强~
不強
2天前
0
雪    币: 490
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
ngiokweng 有樣本嗎[em_065]
https://yy.shiyue.com/m
2天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
14
安卓逆向test https://yy.shiyue.com/m
OK
2天前
0
雪    币: 2984
活跃值: (3697)
能力值: ( LV5,RANK:61 )
在线值:
发帖
回帖
粉丝
15
太强了
2天前
0
雪    币: 6428
活跃值: (5567)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
ngiokweng woc, 才發現之前研究過這家公司的另一款遊戲jp.gungho.padHT, 記得它有一個自定義的section, 還mmap了無數層, 分析了挺久的, 但沒看明白它的檢測邏輯, 大佬帶帶[em_0 ...
你看一下WiFi万能钥匙,它从20年开始,核心so的文件结构就不正常,疑似采用了你说的保护
2天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
17
mb_rjdrqvpa 你看一下WiFi万能钥匙,它从20年开始,核心so的文件结构就不正常,疑似采用了你说的保护
好, 有空看看
2天前
0
雪    币: 9666
活跃值: (6900)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
膜拜大佬
2天前
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
19
膜拜,非常厉害
1天前
0
雪    币: 2775
活跃值: (3176)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
20
唉,大佬啊
1天前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
21
Shangwendada 唉,大佬啊
佬, 為何唉聲嘆氣
1天前
0
雪    币: 2723
活跃值: (3822)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
22
感谢分享
1天前
0
雪    币: 2775
活跃值: (3176)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
23
ngiokweng 佬, 為何唉聲嘆氣[em_065]
叹气我太弱鸡哈哈
13小时前
0
雪    币: 2657
活跃值: (2210)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
24
Shangwendada 叹气我太弱鸡哈哈
唉, 太謙虛了佬
11小时前
0
雪    币: 90
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25
666
9小时前
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册