計(jì)算機(jī)編程基本功:使用IDA的通用解壓插件_第1頁(yè)
計(jì)算機(jī)編程基本功:使用IDA的通用解壓插件_第2頁(yè)
計(jì)算機(jī)編程基本功:使用IDA的通用解壓插件_第3頁(yè)
計(jì)算機(jī)編程基本功:使用IDA的通用解壓插件_第4頁(yè)
計(jì)算機(jī)編程基本功:使用IDA的通用解壓插件_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

使用IDA的通用解壓插件從4.9版開(kāi)始,IDA就集成了UniversalPEUnpacker通用解壓插件,其源代碼可以在IDAProSDK中找到。這個(gè)小教程將會(huì)演示如何使用這個(gè)插件,并簡(jiǎn)單介紹其內(nèi)部工作原理。一個(gè)壓縮的應(yīng)用程序下面是當(dāng)我們執(zhí)行這個(gè)可執(zhí)行程序的運(yùn)行結(jié)果:非常簡(jiǎn)單的程序,但是,如果我們使用IDA來(lái)打開(kāi)它,會(huì)出現(xiàn)下面的警告提示:IDA檢測(cè)到異常的輸入段,并提示我們文件可能被壓縮了…如果我們看一下它的輸入表窗口,我們就會(huì)發(fā)現(xiàn):我們的程序只導(dǎo)入了kernel32.dll中的3個(gè)函數(shù)。我們可以看到在加壓縮殼的程序種常用到的2個(gè)動(dòng)態(tài)鏈接庫(kù)函數(shù)LoadLibraryA和GetProcAddress,它們通常用于恢復(fù)程序的輸入表。使用通用PEUniversalUnpacker在插件的子菜單種選擇UniversalPEunpacker,開(kāi)始解壓:你會(huì)看到插件的選項(xiàng)對(duì)話(huà)框:在這個(gè)對(duì)話(huà)框中,我們可以配置一個(gè)的地址范圍,當(dāng)程序運(yùn)行到這個(gè)區(qū)域(原始的程序入口點(diǎn)區(qū)域),它會(huì)掛起程序的執(zhí)行。你也可以指定一個(gè)文件用于保存解壓的資源。按過(guò)確定按鈕后,插件開(kāi)始運(yùn)行,它啟動(dòng)了我們的程序,并自己解壓,直到它運(yùn)行到我們?cè)O(shè)定的地址范圍內(nèi)。這時(shí)解壓已經(jīng)結(jié)束,依照對(duì)話(huà)框中的提示,我們保存了當(dāng)前的內(nèi)存快照。你會(huì)注意到,我們遇到了兩個(gè)斷點(diǎn),這個(gè)我們最后再去討論它。為了重新構(gòu)造原始的程序輸入表,插件創(chuàng)建了一個(gè)新段:解壓完成后,我們?cè)趕tart()函數(shù)處可以看到更多我們熟悉的代碼結(jié)構(gòu)。我們還可以進(jìn)一步改進(jìn),讓這個(gè)反匯編結(jié)果盡可能的更完美一些!使用簽名如果我們查看解壓后的程序的字符串窗口,我們可以看出我們的程序是使用VirsualC++編譯的,我們可以應(yīng)用相應(yīng)的FLIRT(快速庫(kù)識(shí)別恢復(fù)技術(shù))的庫(kù)簽名。應(yīng)用簽名庫(kù)后,最終的反匯編結(jié)果如下:是不是更好了!插件分析下面我們仔細(xì)研究一下這個(gè)插件,看它是如何使用SDK的調(diào)試API來(lái)完成這些工作的。主要的操作就是啟動(dòng)這個(gè)進(jìn)程,然后根據(jù)調(diào)試器捕捉到的一些事件,進(jìn)行相應(yīng)的處理,直到我們確認(rèn)程序已經(jīng)完全被解壓。我們先設(shè)定一個(gè)句柄用于接收調(diào)試器的事件,并啟動(dòng)這個(gè)程序直到它到達(dá)入口點(diǎn)。if(!hook_to_notification_point(HT_DBG,callback,NULL)){warning("Couldnothooktonotificationpoint\n");return;}//Let'sstartthedebuggerif(!run_to(inf.beginEA)){warning("Sorry,couldnotstarttheprocess");unhook_from_notification_point(HT_DBG,callback,NULL);}事件將會(huì)被送到我們聲明的句柄,定義如下:

staticintidaapicallback(void*/*user_data*/,intnotification_code,va_listva){switch(notification_code){casedbg_process_start:...casedbg_library_load:...casedbg_run_to:...casedbg_bpt:...casedbg_trace:...casedbg_process_exit:......}return0;}當(dāng)我們通過(guò)一個(gè)函數(shù)run_to()來(lái)開(kāi)始我們的進(jìn)程時(shí),我們將會(huì)收到一個(gè)相應(yīng)的事件dbg_run_to,它表示run_to()命令被正確的執(zhí)行?,F(xiàn)在我們來(lái)到壓縮文件的入口點(diǎn),在GetProcAddress()這個(gè)函數(shù)上設(shè)定一個(gè)斷點(diǎn),(假定這個(gè)解壓代碼在重構(gòu)原始輸入表之前結(jié)束):casedbg_run_to://Parameters:thread_id_ttiddbg->stopped_at_debug_event(true);gpa=get_name_ea(BADADDR,"kernel32_GetProcAddress");...elseif(!add_bpt(gpa)){bring_debugger_to_front();warning("Sorry,cannotsetbpttokernel32.GetProcAddress");gotoFORCE_STOP;}else{++stage;set_wait_box("WaitingforacalltoGetProcAddress()");}continue_process();break;當(dāng)程序運(yùn)行到GetProcAddress()斷點(diǎn),我們收到一個(gè)dbg_bpt事件,我們可以從堆棧中提取出這個(gè)地址,然后刪除這個(gè)斷點(diǎn),并在返回地址設(shè)定第二個(gè)斷點(diǎn),以便能在GetProcAddress()函數(shù)返回時(shí)立刻中止。casedbg_bpt://Auserdefinedbreakpointwasreached.//Parameters:thread_id_ttid//ea_tbreakpoint_ea{/*tid_ttid=*/va_arg(va,tid_t);ea_tea=va_arg(va,ea_t);...if(ea==gpa){regval_trv;if(get_reg_val("esp",&rv)){ea_tesp=rv.ival;invalidate_dbgmem_contents(esp,1024);ea_tret=get_long(esp);...if(!del_bpt(gpa)||!add_bpt(ret))error("Cannotmodifybreakpoint");還記得我們之前在運(yùn)行解壓插件時(shí)碰到的兩個(gè)斷點(diǎn)嗎?中斷在0x7C80AC28和0x00040C68D,第一個(gè)是我們的GetProcAddress()斷點(diǎn),而第而個(gè)是在返回地址上的斷點(diǎn)。在下面的反匯編窗口中,你可以看到進(jìn)入GetProcAddress()斷點(diǎn)的那個(gè)調(diào)用指令,現(xiàn)在我們要繼續(xù)運(yùn)行直到解壓程序恢復(fù)了程序寄存器的原始內(nèi)容,然后跳到解壓后的程序的真實(shí)入口點(diǎn):我們?cè)诘诙€(gè)斷點(diǎn)之后開(kāi)始單步跟蹤,直到指令執(zhí)行到我們之前設(shè)定的地址范圍。del_bpt(ea);if(!is_library_entry(ea)){deb(IDA_DEBUG_PLUGIN,"%a:reachedunpackercode,switchingtotracemode\n",ea);enable_step_trace(true);...set_wait_box("Waitingfortheunpackertofinish");}else{warning("%a:bptinlibrarycode",ea);//howcanitbe?add_bpt(gpa);}在每一步指令執(zhí)行時(shí),我們判斷其地址是否在我們之前設(shè)定的范圍之內(nèi)。如果我們運(yùn)行到了那個(gè)區(qū)域,重新分析這些解壓后的代碼,調(diào)整入口點(diǎn),重建輸入表,保存資源然后……最后來(lái)一張內(nèi)存快照!casedbg_trace://Astepoccured(oneinstructionwasexecuted).Thisevent//notificationisonlygeneratedifsteptracingisenabled.//Parameter:none…/*tid_ttid=*/va_arg(va,tid_t);ea_tip=va_arg(va,ea_t);if(oep_area.contains(ip)){//stopthetracemodeenable_step_trace(false);//reanalyzetheunpackedcodeset_wait_box("Reanalyzingtheunpackedcode");do_unknown_range(oep_area.startEA,oep_area.endEA,false);auto_make_code(ip);noUsed(oep_area.startEA,oep_area.endEA);auto_mark_range(oep_area.startEA,oep_area.endEA,AU_FINAL);//marktheprogram'sentrypointmove_entry(ip);set_wait_box();...set_wait_box("Recreatingtheimporttable");invalidate_dbgmem_config();...create_impdir();set_wait_box("Storingresourcesto'resource.res'");if(resfile[0]!='\0')extract_resource(resfile);set_wait_box();if(take_memory_snapshot(true))gotoFORCE_STOP;這樣,就在IDA數(shù)據(jù)庫(kù)中得到了進(jìn)程的內(nèi)存映像,我們可以象通常那樣來(lái)分析這些解壓后的代碼了?,F(xiàn)在就去看看那些在SDK中的源代碼吧!去了解一下這個(gè)插件的所有實(shí)現(xiàn)細(xì)節(jié)。附送編程必備之素質(zhì)在新手入門(mén)編程之前小編想給大家一些關(guān)于學(xué)習(xí)編程的建議。很多零基礎(chǔ)非計(jì)算機(jī)科班出身的初學(xué)者擔(dān)心自己學(xué)不好編程,其實(shí)這種擔(dān)心完全是多余的,學(xué)習(xí)編程就和學(xué)習(xí)一門(mén)外語(yǔ)是一樣的,即使現(xiàn)在你還是零,在經(jīng)過(guò)了一段時(shí)間的努力學(xué)習(xí)之后,也能成功掌握編程語(yǔ)言。那么有人可能要問(wèn)了,新手入門(mén)編程需要具備哪些素質(zhì)呢?或者換句話(huà)說(shuō),在學(xué)習(xí)編程的過(guò)程中哪些素質(zhì)會(huì)幫助我們更好更快的掌握一門(mén)編程語(yǔ)言呢?1.懂得打字。常常會(huì)有人擔(dān)心入門(mén)編程對(duì)學(xué)習(xí)者有一個(gè)很高的要求,其實(shí)不論你的性別還是學(xué)歷如何,入門(mén)編程的唯一門(mén)檻就是你會(huì)不會(huì)打字。如果你連打字都成問(wèn)題的話(huà),那你學(xué)習(xí)編程也會(huì)成問(wèn)題。尤其如果你連程序源代碼中的那些奇怪字符都打不出來(lái)的話(huà),就根本別提編程了。沒(méi)有這種基本素質(zhì)的話(huà),你將連最基本的軟件工作原理都難以學(xué)會(huì)。因此,新手入門(mén)編程的第一個(gè)必須具備的素質(zhì)就是懂得打字,只有輸入代碼樣例并讓他們運(yùn)行起來(lái),才能幫你記住各種符號(hào)的名字并對(duì)它們熟悉起來(lái),在這個(gè)過(guò)程也會(huì)讓你對(duì)編程語(yǔ)言更加熟悉。2、關(guān)注每個(gè)細(xì)節(jié)。尤其對(duì)剛剛學(xué)習(xí)編程的新手來(lái)講,對(duì)于細(xì)節(jié)的注重程度可以決定你的學(xué)習(xí)效果。事實(shí)上這也是任何行業(yè)區(qū)分好壞的標(biāo)準(zhǔn)。你必須關(guān)注你工作中任何一個(gè)微小的細(xì)節(jié),否則你的工作成果將缺乏重要的元素。從學(xué)習(xí)編程的角度來(lái)講,只有通過(guò)將仿照案例的代碼一字不差地打出來(lái),這樣的實(shí)踐訓(xùn)練才能讓自己集中精力到你作品的細(xì)節(jié)上面。這樣關(guān)注細(xì)節(jié)的素質(zhì),會(huì)讓你在學(xué)習(xí)的過(guò)程中成長(zhǎng)的更快!3.捕捉不同點(diǎn)。為什么這是一個(gè)編程必須具備的素質(zhì)?道理很簡(jiǎn)單,在程序員長(zhǎng)年累月的工作中的一項(xiàng)重要技能,就是對(duì)于不同點(diǎn)的區(qū)分能力。有經(jīng)驗(yàn)的程序員拿著兩份僅有細(xì)微不同的程序,可以立即指出里邊的不同點(diǎn)來(lái)。程序員甚至造出工具來(lái)讓這件事更加容易,不過(guò)我們不會(huì)用到這些工具。你要先用笨辦法訓(xùn)練自己的大腦,等你具備一些相關(guān)能力的時(shí)候才可以使用這些工具。在新手做每一個(gè)習(xí)題的時(shí)候,不免會(huì)寫(xiě)錯(cuò)點(diǎn)東西,甚至有經(jīng)驗(yàn)的程序員也會(huì)偶爾出點(diǎn)錯(cuò)。你的任務(wù)是對(duì)比你寫(xiě)過(guò)的東西和正確的答案,并將所有的不同點(diǎn)都改正。這個(gè)過(guò)程可以訓(xùn)練你關(guān)注自己的錯(cuò)誤,bugs以及其他的一些問(wèn)題。4.多親自動(dòng)手敲代碼。切忌復(fù)制粘貼代碼,制粘貼會(huì)讓你學(xué)習(xí)過(guò)程中的練習(xí)變得毫無(wú)意義。都說(shuō)學(xué)習(xí)講究眼到筆到心到,無(wú)論你對(duì)代碼的內(nèi)容多么清楚了,還是要自己手動(dòng)練習(xí)敲代碼。重復(fù)練習(xí)習(xí)題的目的是訓(xùn)練你的雙手和大腦思維,讓你有能力讀代碼、寫(xiě)代碼、觀(guān)察代碼。如果你復(fù)制粘貼的話(huà),那你就是在欺騙自己,而且所謂的練習(xí)也將失去效果。5.堅(jiān)持重復(fù)學(xué)習(xí)。無(wú)論是學(xué)什么東西,在我們開(kāi)始接觸一個(gè)全新的東西或者事物的時(shí)候,都是從零基礎(chǔ)開(kāi)始的,因此我們說(shuō)萬(wàn)事開(kāi)頭難。這個(gè)難其實(shí)就是堅(jiān)持,也是學(xué)習(xí)編程必須具備的重要素質(zhì)。學(xué)習(xí)編程難嗎?如果不能為什么這么多自學(xué)編程的人都從入門(mén)到放棄

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論