首页
社区
课程
招聘
[N1CTF2024] ezapk
发表于: 2024-11-10 20:07 4220

[N1CTF2024] ezapk

2024-11-10 20:07
4220

久違的看看安卓題,順便水一篇文章,有任何問題歡迎指出!

拉入jadx,很容易可以定位到關鍵邏輯,經典的加密對比。

加密函數enc在native層,而且加載了2個so。

嘗試分別將2個so都拉入ida,但都未發現enc,顯然是動態注冊的。

網上抄的一個frida腳本,用來hook動態注冊的native函數

發現是在libnative1.so!0x1b148

0x1b148函數如下,重命名成enc,做了一些奇奇怪怪的操作,等等再分析

在此之前,由於比較好奇另一個so libnative2.so有什麼用,於是順手查看了.init_array段,看看有沒有偷偷在做壞事。( 因為在java層沒有發現任何對libnative2.so函數的調用,只有調用libnative1.so的,因此合理懷疑對libnative2.so的操作是在libnative1.so中進行的,而.init_array就是一個很好的時機。 )

sub_1B540.init_array段最後一個函數,果然發現了libnative2.so的字樣。

sub_1B540一開始先從/proc/self/maps裡獲取libnative.so的基址

然後調用sub_1B000將libnative2.so的一些信息初始化,保存在libnative2_base

sub_1B000的實現挺像linker加載so的流程中的prelink_image

sub_1B540最後部份如下,大概是將libnative2.so裡的rand函數返回值固定為0xE9

看完.init_array後,可以回到enc函數了( 其實上面的那些東西看不看都沒有所謂,單純是我好奇想看看,純動調其實就能解決這題 )。

動調後會發現,第1個紅框大概是在取libnative2.so某個函數的offset,然後第2個紅框調用該函數對輸入進行加密( 通過base + offset得到函數的具體地址 )。

一步一步調試完後會發現,總共從libnative2.so裡取了3個加密函數。

第1個的offset是0x106C,只是簡單的異或,異或的值是上述分析的0xE9

第2個的offset是0x12C0,一眼RC4。

第3個的offset是0x1AB0,一眼base64。

最終結果:MysT3r10us_C0d3_2024N1CTF!

這題目挺好的,感覺我以往遇到的題更偏向於算法的部份,而這題對算法分析的要求不高,反而多了一些android逆向實際可能會遇到的東西,挺有意思的。

// com.n1ctf2024.ezapk
function find_RegisterNatives(params) {
    let symbols = Module.enumerateSymbolsSync("libart.so");
    let addrRegisterNatives = null;
    for (let i = 0; i < symbols.length; i++) {
        let symbol = symbols[i];
         
        //_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
        if (symbol.name.indexOf("art") >= 0 &&
                symbol.name.indexOf("JNI") >= 0 &&
                symbol.name.indexOf("RegisterNatives") >= 0 &&
                symbol.name.indexOf("CheckJNI") < 0) {
            addrRegisterNatives = symbol.address;
            console.log("RegisterNatives is at ", symbol.address, symbol.name);
            hook_RegisterNatives(addrRegisterNatives)
        }
    }
 
}
 
function hook_RegisterNatives(addrRegisterNatives) {
 
    if (addrRegisterNatives != null) {
        Interceptor.attach(addrRegisterNatives, {
            onEnter: function (args) {
                console.log("[RegisterNatives] method_count:", args[3]);
                let java_class = args[1];
                let class_name = Java.vm.tryGetEnv().getClassName(java_class);
                //console.log(class_name);
 
                let methods_ptr = ptr(args[2]);
 
                let method_count = parseInt(args[3]);
                for (let i = 0; i < method_count; i++) {
                    let name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
                    let sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
                    let fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
 
                    let name = Memory.readCString(name_ptr);
                    let sig = Memory.readCString(sig_ptr);
                    let symbol = DebugSymbol.fromAddress(fnPtr_ptr)
                    console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr,  " fnOffset:", symbol, " callee:", DebugSymbol.fromAddress(this.returnAddress));
                }
            }
        });
    }
}
 
setImmediate(find_RegisterNatives);
// com.n1ctf2024.ezapk
function find_RegisterNatives(params) {
    let symbols = Module.enumerateSymbolsSync("libart.so");
    let addrRegisterNatives = null;
    for (let i = 0; i < symbols.length; i++) {
        let symbol = symbols[i];

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2024-11-10 20:08 被ngiokweng编辑 ,原因: .
收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//