熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

raw

2013-11-13 16:10:31  來源: Oracle 

  socket( PF_INET SOCK_RAW IPPROTO_TCP );
  
  在RedHat 下這兩種socket都可以正常建立內核支持了的但是對於Solaris 如果以root身份truss跟蹤這兩個函數發現第二個socket建立的時候 內核不支持這種情況下指定IPPROTO_TCP庫函數本身做了處理
  
  so_socket( ) Err# EPROTOTYPE
  stat(/dev/rawip xEFFFFAC) =
  so_socket( /dev/rawip ) =
  setsockopt( xEFFFFBB ) =
  
  從執行效果看這樣的處理和Linux下的意義不同了
  
  如果考慮廣泛兼容性應該扔棄第二種socket全部以IPPROTO_RAW方式出現這樣的話理論上可以考慮不用TCP/UDP協議但是涉及client/server模式顯然應該繼
  續使用TCP/UDP從突破防火牆角度看還是以鬼子的ACK方式為好UDP通信被很多防火牆屏蔽TCP也好不到哪裡去而且按照目前的設想等於僅僅使用TCP的頭部概 念並沒有使用TCP協議的超時重傳等機制更沒有有限狀態機介入為什麼不使用UDP呢?還是應該從防火牆角度考慮這個設計選擇具體問題具體分析吧現在的難點是完全使用IPPROTO_RAW寫沒多大問題讀有了麻煩又需要重翻UNP此外 丟包是毫無疑問的因此必須盡量設計成無狀態方式(NFS Server就是一個例子)這 個也僅僅是說說技術問題尚未可知
  
  關於內核傳遞IP報文到一個raw_socket有幾點需要注意我們分別探討之
  
  ) TCP/UDP報文(IP報文負載為TCP/UDP)永遠不會傳遞給raw_socketStevens介紹
  的時候以BSD家族為例
  
  對於Linux顯然已經不適用這個結論socket( PF_INET SOCK_RAW IPPROTO_TCP )
  就可以接收到TCP報文Linux內核是給了這個機會的此時正常的TCP協議層也會收到TCP報文(後面我們會寫測試代碼驗證它)於是造成潛在的安全隱患在無需
  數據鏈路層和網卡混雜模式介入的情況下利用raw_socket監視發往本機的TCP報文盡管只有root才可以創建raw_socket但獲得創建raw_socket的機會和獲得完整root權限相比要大得多對於Solaris系統內核應該是沒有支持
  socket( PF_INET SOCK_RAW IPPROTO_TCP )方式盡管以root身份執行庫函數並沒有報錯(此時庫函數自己做了其他處理)
  
  對於Windows K從backend拖回來的程序執行效果以及袁哥分析代碼的結論看K可能支持socket( PF_INET SOCK_RAW IPPROTO_TCP )這種方式抓包分析
  backdoor的client/server通信發現除了預料中的ACK還夾帶有RST只能說明K內核傳遞IP報文到raw_socket的同時傳遞給了正常的TCP協議層RST是由正常
  TCP協議層發出的NT/x估計沒戲
  
  考慮我們要達到的目的如果內核不給這個機會(傳遞TCP報文到raw_socket)意味著ACK方式破產UDP自然也不用想了雖然Linux可以但我們希望得到一個更廣泛兼容的backdoor可以從數據鏈路層考慮這個問題牽扯的問題更多沒有太大必要
  
  ) 對於伯克利實現而言內核一般處理了幾種常見ICMP報文(回應請求時間戳請求地址掩碼請求)其余未處理ICMP報文交給raw_socket注意內核並沒有
  處理上面三種請求報文的應答報文想想pingc的實現如果內核處理icmp echo reply即使指定IPPROTO_ICMP處於應用層的ping也沒有機會得到應答報文這裡所說內核處理都是指處理入IP報文對於發送IP報文基本上任
  由應用程序處理的所以ping可以發送自己的icmp echo request
  
  Linux/Solaris的實現有差別提供給應用層更多機會內核處理了icmp echo request同時會交給socket( PF_INET SOCK_RAW IPPROTO_ICMP )不同於BSD
  實現內核未處理的icmp報文依舊交給raw_socket這給我們一個機會編寫自己的icmp daemon利用被內核傳遞到raw_socket的icmp報文進行交互式通信從突破防火牆角度考慮比較現實一般管理員會允許icmp echo request進入管理員要是在防火牆上過濾了icmp echo request估計我們也沒有機會在這種敵人內部安裝icmp daemon走先
  
  ) 所有的IGMP報文交給raw_socket
  
  同上可以利用現在的操作系統好象已經開始在內核裡處理igmp那樣的話機會不大而且防火牆對IGMP報文比較敏感
  
  socket( AF_INET SOCK_RAW IPPROTO_IGMP )Linux上可以接收到IGMP報文 Solaris上不行
  
  ) 如果內核無法理解IP報文頭中高層協議類型傳遞該報文給raw_socket
  
  內核無法理解的對於防火牆也是無法理解的除非不考慮突破防火牆的網絡拓撲否則暫時別想此外從前面的測試中看到Linux/Solaris下必須精確指定第
  三個參數可以接收匹配IP報文如果要利用內核無法理解之協議類型必須確保該類型可以指定在第三個參數中
  
  ) IP分片一定是在內核中重組完成了才會傳遞給raw_socket
  
  換句話說raw_socket無法分析IP分片數據鏈路層可以這裡隱含著一個意思IP分片重組永遠在內核完成一旦這部分的處理代碼出了問題就是內核的麻煩所以死得快
  
  ) 如果內核決定傳遞一個IP報文到raw_socket則系統中所有進程創建的所有raw_socket都會收到這個IP報文這是一個潛在的安全問題
  
  我們在測試程序中創建socket( PF_INET SOCK_RAW
  IPPROTO_ICMP )啟動了兩
  個實例然後從其他主機ping本機兩個實例都收到了icmp echo request
  
  ) 創建socket( PF_INET SOCK_RAW )並且不調用bindconnect這樣的
  raw_socket接收所有內核傳遞上來的IP報文第三個參數是指定匹配的如果非
  零不匹配的IP報文不會被傳遞給該raw_socket對於這種系統企圖監視本機
  所有入IP報文不需要數據鏈路層介入也不要求網卡混雜模式簡單創建一個
  raw_socket指定第三個參數為即可
  
  遺憾的是我們在Linux下測試根本就不支持第三個參數指定為指定成
  (IPPROTO_RAW)也無法達到Stevens描述的效果主要用於發送Stevens介
  紹的可能僅僅是BSD實現吧
  
  關於這個覺得看看Linux關於raw_socket的實現部分比較好瞎猜也不是辦法
  
  ) 有些代碼使用了raw_socket並未指定IP_HDRINCL選項年為了解決
  traceroute問題引入了一個patch創建SOCK_RAW時指定第三個參數為
  IPPROTO_RAW(值)效果和指定IP_HDRINCL選項一樣還更方便些
  
  
  /*
  * For Solaris
  * gcc O o raw rawc lsocket lnsl
  *
  * For Linux
  * gcc O o raw rawc
  */
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  
  #define SUCCESS
  #define FAILURE
  
  int recvSocket;
  u_char packet[ ];
  
  void Close ( int fd )
  {
  if ( close( fd ) == )
  {
  perror( close );
  exit( FAILURE );
  }
  return;
  } /* end of Close */
  
  void outputBinary ( const unsigned char * byteArray const size_t byteArrayLen )
  {
  u_long offset;
  int i j k;
  fprintf( stderr byteArray [ %lu bytes ] > \n byteArrayLen );
  if ( byteArrayLen <= )
  {
  return;
  }
  i = ;
  offset = ;
  for ( k = byteArrayLen / ; k > ; k offset += )
  {
  fprintf( stderr %X offset );
  for ( j = ; j < ; j++ i++ )
  {
  if ( j == )
  {
  fprintf( stderr %X byteArray[i] );
  }
  else
  {
  fprintf( stderr %X byteArray[i] );
  }
  }
  fprintf( stderr );
  i = ;
  for ( j = ; j < 16; j++, i++ )
  {
  /* if ( isprint( (int)byteArray[i] ) ) */
  if ( ( byteArray[i] >= ) && ( byteArray[i] <= 255 ) )
  {
  fprintf( stderr, "%c", byteArray[i] );
  }
  else
  {
  fprintf( stderr, "." );
  }
  }
  fprintf( stderr, "\n" );
  } /* end of for */
  k = byteArrayLen - i;
  if ( k <= 0 )
  {
  return;
  }
  fprintf( stderr, "%08X ", offset );
  for ( j = 0 ; j < k; j++, i++ )
  {
  if ( j == 8 )
  {
  fprintf( stderr, "-%02X", byteArray[i] );
  }
  else
  {
  fprintf( stderr, " %02X", byteArray[i] );
  }
  }
  i -= k;
  for ( j = 16 - k; j > 0; j-- )
  {
  fprintf( stderr, " " );
  }
  fprintf( stderr, " " );
  for ( j = 0; j < k; j++, i++ )
  {
  if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255
From:http://tw.wingwit.com/Article/program/Oracle/201311/17939.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.