版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
分析某加固的Anti-Frida保護(hù)分析過(guò)程 找到檢測(cè)所在的so我們可以通過(guò)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ù)沒(méi)有輸出,dlopen的第一個(gè)參數(shù)即為所需load的so字(args[0].readCString())我們可以去提示的路徑下修改dlopen.js腳本修改前:修改后:再次輸出一下:現(xiàn)在dlopen的參數(shù)就顯示出來(lái)了,但是這里load的三個(gè)so顯然是系統(tǒng)的so而非app的so,所以我們?cè)賖ookandroid_dlopen_ext看看:可以看到當(dāng)load到libDexHelper.so的時(shí)候,frida被殺掉了,所以我們初步可以判定做檢測(cè)的位置在libDexHelper.so中檢測(cè)點(diǎn)一首先我們可以通過(guò)hook字符串比較函數(shù)(比如strstr和strcmp等函數(shù))來(lái)觀察是否傳入了frida符串進(jìn)行比較通過(guò)這些字符串的特征,可以知道它們來(lái)自maps,而Frida的一大特征就是在注入到app中后,app的maps中會(huì)有frida-agent.so的內(nèi)存分布。所以這里我們可以通過(guò)偽造maps來(lái)繞過(guò)這里的檢測(cè)(在/data/data/pkgname/路徑下創(chuàng)建一個(gè)新的maps,并讀取按行讀取原始的maps,如果某一行中存在tmp字符串時(shí),就跳過(guò)這一行,否則寫(xiě)入新的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í)行后的輸出如下:通過(guò)觀察log可以發(fā)現(xiàn),之前maps中frida相關(guān)的字符串沒(méi)有出現(xiàn)在strstr的參數(shù)中,說(shuō)明我們已經(jīng)過(guò)掉了這個(gè)檢測(cè)點(diǎn),但是frida仍然被殺掉了,并且被殺掉之前app打開(kāi)了/proc/self/task/pid/status件,所以我們需要再去觀察一下這些status文件。檢測(cè)點(diǎn)二通過(guò)觀察發(fā)現(xiàn),當(dāng)app中注入了frida,那么frida的特征會(huì)在status文件中的Name字段有所體現(xiàn),這里我們可以通過(guò)其它沒(méi)有檢測(cè)frida的app做一個(gè)驗(yàn)證,如下圖所示:所以我們可以通過(guò)上面?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ì)被斷下來(lái),但是查看輸出的log我們可以看到替換是成功的:但細(xì)心一點(diǎn)我們會(huì)發(fā)現(xiàn),還有一個(gè)frida相關(guān)的字符串出現(xiàn)在了log里(pool-frida)下腳本:然后,執(zhí)行!然后frida又雙叒叕被終止了,所以還是繼續(xù)看輸出。檢測(cè)點(diǎn)三通過(guò)輸出可以看到上面還有個(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過(guò)程)通過(guò)在ida里搜索可以看到JNI_OnLoad函數(shù)被抹掉了,所以我們得去打印libDexHelper.so的基址,然后計(jì)算偏移來(lái)獲取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ì)算出來(lái)的偏移在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)容,這樣就能繞過(guò)這個(gè)檢測(cè)了,腳本如下: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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度柑橘滯銷(xiāo)產(chǎn)品線上推廣與“搶購(gòu)”銷(xiāo)售合同3篇
- 2024瑜伽館瑜伽教練勞動(dòng)合同范本及教練休息時(shí)間規(guī)定3篇
- 2024版雞蛋簡(jiǎn)單購(gòu)銷(xiāo)合同
- 2025年度養(yǎng)老設(shè)施建設(shè)承包合同范本權(quán)威版4篇
- 2025年度智能交通信號(hào)控制系統(tǒng)研發(fā)與推廣合同4篇
- 2024知識(shí)產(chǎn)權(quán)許可使用合同許可人和被許可人
- 2025年度漁業(yè)生態(tài)循環(huán)承包經(jīng)營(yíng)合同4篇
- 2024版魚(yú)苗的購(gòu)銷(xiāo)合同范本
- 2025年度智慧能源管理系統(tǒng)承包合作協(xié)議范文4篇
- 2025年度醫(yī)院手術(shù)室設(shè)備供應(yīng)及承包運(yùn)營(yíng)協(xié)議4篇
- 車(chē)險(xiǎn)理賠全解析
- 微粒貸逾期還款協(xié)議書(shū)范本
- Unit10l'mten!(練)新概念英語(yǔ)青少版StarterA
- 產(chǎn)業(yè)園區(qū)開(kāi)發(fā)全流程實(shí)操解析
- NBT 47013.4-2015 承壓設(shè)備無(wú)損檢測(cè) 第4部分:磁粉檢測(cè)
- 羽毛球比賽對(duì)陣表模板
- 2024年上海市中考數(shù)學(xué)真題試卷及答案解析
- 2024年全國(guó)卷1高考理綜試題及答案
- 初中語(yǔ)文現(xiàn)代文閱讀訓(xùn)練及答案二十篇
- 農(nóng)村開(kāi)荒土地承包權(quán)轉(zhuǎn)讓協(xié)議書(shū)
- 牙科門(mén)診病歷
評(píng)論
0/150
提交評(píng)論