2023Anti-Frida加固樣本分析_第1頁
2023Anti-Frida加固樣本分析_第2頁
2023Anti-Frida加固樣本分析_第3頁
2023Anti-Frida加固樣本分析_第4頁
2023Anti-Frida加固樣本分析_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

分析某加固的Anti-Frida保護(hù)分析過程 找到檢測所在的so我們可以通過frida-trace快速進(jìn)行系統(tǒng)函數(shù)的hook,首先我們需要知道loadso的函數(shù)一般為dlopen和android_dlopen_ext,所以先執(zhí)行fridafrida-trace-U-fcom.wujie.chengxin-idlopen可以觀察到以下輸出:可以看到這里只顯示了調(diào)用dlopen,但是參數(shù)沒有輸出,dlopen的第一個(gè)參數(shù)即為所需load的so字(args[0].readCString())我們可以去提示的路徑下修改dlopen.js腳本修改前:修改后:再次輸出一下:現(xiàn)在dlopen的參數(shù)就顯示出來了,但是這里load的三個(gè)so顯然是系統(tǒng)的so而非app的so,所以我們?cè)賖ookandroid_dlopen_ext看看:可以看到當(dāng)load到libDexHelper.so的時(shí)候,frida被殺掉了,所以我們初步可以判定做檢測的位置在libDexHelper.so中檢測點(diǎn)一首先我們可以通過hook字符串比較函數(shù)(比如strstr和strcmp等函數(shù))來觀察是否傳入了frida符串進(jìn)行比較通過這些字符串的特征,可以知道它們來自maps,而Frida的一大特征就是在注入到app中后,app的maps中會(huì)有frida-agent.so的內(nèi)存分布。所以這里我們可以通過偽造maps來繞過這里的檢測(在/data/data/pkgname/路徑下創(chuàng)建一個(gè)新的maps,并讀取按行讀取原始的maps,如果某一行中存在tmp字符串時(shí),就跳過這一行,否則寫入新的maps)在腳本里加入以下代碼:constconstopenPtr=Module.getExportByName('libc.so','open');constopen=newNativeFunction(openPtr,'int',['pointer','int']);varreadPtr=Module.findExportByName("libc.so","read");varread=newNativeFunction(readPtr,'int',['int','pointer',"int"]);varfakePath="/data/data/com.pkgname/maps";varfile=newFile(fakePath,"w");varbuffer=Memory.alloc(512);Interceptor.replace(openPtr,newNativeCallback(function(pathnameptr,flag){varvarpathname=Memory.readUtf8String(pathnameptr);varrealFd=open(pathnameptr,flag);console.log("open:",pathname)if(pathname.indexOf("maps")>=0){//console.log("openmaps:",pathname);while(parseInt(read(realFd,buffer,512))!==0){varoneLine=Memory.readCString(buffer);if(oneLine.indexOf("tmp")===-1){file.write(oneLine);}else{console.log(oneLine);}}varfilename=Memory.allocUtf8String(fakePath);returnopen(filename,flag);}varfd=open(pathnameptr,flag);//Thread.sleep(1)returnfd;},'int',['pointer','int']));執(zhí)行后的輸出如下:通過觀察log可以發(fā)現(xiàn),之前maps中frida相關(guān)的字符串沒有出現(xiàn)在strstr的參數(shù)中,說明我們已經(jīng)過掉了這個(gè)檢測點(diǎn),但是frida仍然被殺掉了,并且被殺掉之前app打開了/proc/self/task/pid/status件,所以我們需要再去觀察一下這些status文件。檢測點(diǎn)二通過觀察發(fā)現(xiàn),當(dāng)app中注入了frida,那么frida的特征會(huì)在status文件中的Name字段有所體現(xiàn),這里我們可以通過其它沒有檢測frida的app做一個(gè)驗(yàn)證,如下圖所示:所以我們可以通過上面?zhèn)卧靘aps的方法去偽造task,修改腳本如下:constconstopenPtr=Module.getExportByName('libc.so','open');constopen=newNativeFunction(openPtr,'int',['pointer','int']);varreadPtr=Module.findExportByName("libc.so","read");varread=newNativeFunction(readPtr,'int',['int','pointer',"int"]);varfakePath="/data/data/com.pkgname/maps";varfile=newFile(fakePath,"w");varbuffer=Memory.alloc(512);varfakePath2="/data/data/com.pkgname/task";varfile2=newFile(fakePath2,"w");varbuffer2=Memory.alloc(512);Interceptor.replace(openPtr,newNativeCallback(function(pathnameptr,flag){varpathname=Memory.readUtf8String(pathnameptr);varrealFd=open(pathnameptr,console.log("open:",pathname)if(pathname.indexOf("maps")>=0||pathname.indexOf("task")>=0){vartemp=pathname.indexOf("maps")>=0?1:2;switch(temp){case1://console.log("openmaps:",pathname);while(parseInt(read(realFd,buffer,512))!==0){varoneLine=Memory.readCString(buffer);if(oneLine.indexOf("tmp")===-1){file.write(oneLine);}else{//console.log(oneLine);}}}varfilename=Memory.allocUtf8String(fakePath);returnopen(filename,flag);break;case2://console.log("opentask:",pathname);while(parseInt(read(realFd,buffer2,512))!==0){varoneLine=Memory.readCString(buffer2);varreplaceStr="123"if(oneLine.indexOf("gum-js-loop")!=-1){oneLine=oneLine.replace("gum-js-loop",replaceStr)}if(oneLine.indexOf("gmain")!=-1){oneLine=oneLine.replace("gmain",replaceStr)}file2.write(oneLine);//console.log(oneLine)}varfilename=Memory.allocUtf8String(fakePath2);returnopen(filename,flag);break;}}varfd=open(pathnameptr,flag);//Thread.sleep(1)returnfd;},'int',['pointer','int']));上面的腳本執(zhí)行完成后,其實(shí)frida還是會(huì)被斷下來,但是查看輸出的log我們可以看到替換是成功的:但細(xì)心一點(diǎn)我們會(huì)發(fā)現(xiàn),還有一個(gè)frida相關(guān)的字符串出現(xiàn)在了log里(pool-frida)下腳本:然后,執(zhí)行!然后frida又雙叒叕被終止了,所以還是繼續(xù)看輸出。檢測點(diǎn)三通過輸出可以看到上面還有個(gè)關(guān)于strstr函數(shù)且參數(shù)為frida相關(guān)字符串的調(diào)用:我們打印一下這個(gè)strstr的調(diào)用??纯此晕覀?cè)偃タ纯磮D中這個(gè)JNI_OnLoad+0x14a8位置的代碼邏輯(此處省略從內(nèi)存中dumpxxx.so以及修復(fù)so過程)通過在ida里搜索可以看到JNI_OnLoad函數(shù)被抹掉了,所以我們得去打印libDexHelper.so的基址,然后計(jì)算偏移來獲取strstr的調(diào)用點(diǎn),修改hookstrstr部分的腳本為:InterceptorInterceptor.attach(Module.findExportByName(null,"strstr"),{onEnter:function(args){if(args[0].readCString().indexOf("frida")!==-1||args[1].readCString().indexOf("frida")!==-1 args[0].readCString().indexOf("gum-js-loop")!==-1||args[1].readCString().indexOf("gum-js-loop")!==-1||args[0].readCString().indexOf("gmain")!==-1||args[1].readCString().indexOf("gmain")!==-1 ||argsargs[0].readCString().indexOf("linjector")!==-1||args[1].readCString().indexOf("linjector")!==-1){console.log("\nlibDexHelper.sobaseaddress:"+Module.findBaseAddress("libDexHelper.so"))console.log('\nstrstr('+'s1="'+args[0].readCString()+'"'+',s2="'+args[1].readCString()+'"'')');console.log(Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')+'\n');}},onLeave:function(retval){}});執(zhí)行:所以偏移為:0xc2eae91d-0xc2e8a000,在ida里跳轉(zhuǎn)后,往上找一找能發(fā)現(xiàn)一個(gè)strstr函數(shù)調(diào)用(計(jì)算出來的偏移在ida中跳轉(zhuǎn)后并不是strstr的調(diào)用點(diǎn),但肯定是在這個(gè)函數(shù)里的,所以需要上下找一找):這里strstr函數(shù)上面就是一個(gè)readlink函數(shù),并且參數(shù)v518也和readlink似乎有點(diǎn)關(guān)聯(lián),所以我們?nèi)ミ@個(gè)readlink看看,在我們的腳本里補(bǔ)充:varvariii,jjj;Interceptor.attach(Module.findExportByName(null,"readlink"),{onEnter:function(args){console.log("calliii=args[0]jjj=args[1]//console.log(Thread.backtrace(this.context,Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n')+},onLeave:function(retval){console.log("leavereadlink:"+iii.readCString()+""+jjj.readCString())}});果然,我們可以看到frida出現(xiàn)了:readlink函數(shù)的定義如下:所以,我們需要在readlink函數(shù)返回的時(shí)候替換掉buf中關(guān)于frida的內(nèi)容,這樣就能繞過這個(gè)檢測了,腳本如下:varvaraaa,bbb,ccc;varss=falseInterceptor.attach(Module.findExportByName(null,"readlink"),{onEnteronEnter:function(args){aaa=args[0];bbb=ccc=},onLeave:function(retval){if(bbb.readCString().indexOf("frida")!==-1||bbb.readCString().indexOf("gum-js-loop")!==-1||bbb.readCString().indexOf("gmain")!==-1||bbb.readCString().indexOf("linjector")!==-1){console.log('\nreadlink('+'s1="'+aaa.readCString()+'"'+',s2="'+bbb.readCString()+'"'',s3="'+ccc+'"'+')');bbb.writeUtf8String("/system/framework/boot

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論