cve-2017-11882 poc分析

CVE-2017-11882 poc分析

思路:由樣本poc出發,尋找漏洞觸發點安全

0x00 工具&實驗環境

0x01 分析行爲

第一步:觀察poc行爲

​ 打開11882.rtf (樣本文件)後,彈出一個計算器,以下圖所示:服務器

​ ok,既然彈出了計算器,那麼我就用windbg附加到Word程序用bp命令下那幾個函數的斷點嘛(CreateProcess系列、WinExec、ShellExecute系列),而後再把11882.rtf脫進被附加調試器的Word程序。編輯器

​ 可是結果出乎我意料,計算器都彈出來了,windbg卻仍是BUSY狀態(沒有觸發斷點)。個人第一反應就是,難道windbg出bug了?因而我再三檢查,查閱能夠彈出計算器的函數,試了幾回,都沒有斷下來。因而,我請教了一位搞逆向很厲害的樹老哥。老哥直接給了我方法,解開了個人疑惑。函數

第二步:找出計算器被彈出的地方

樹老哥 是這樣作的:工具

首先他打開pchunter查看計算器進程的進程信息,結果以下圖:線程

​ 發現有什麼不對勁的地方了嗎?calc的父進程竟然不是WINWORD.EXE!(calc.exe的父進程id不等於WINWORD.EXE的進程ID),那就說明計算器不是由WINWORD.EXE進程打開的。那麼根據calc的父進程ID查找,得出calc是由進程ID爲2440的cmd.exe建立的。而cmd.exe的父進程ID是2476,可是當前進程列表中並無進程ID是2476的進程信息。說明那個進程ID爲2476的進程是個一秒男,放出了cmd.exe就沒了。調試

​ 那麼怎麼去找到是哪一個進程建立了cmd.exe呢?這個時候就能夠上進程監控神器:Process Monitor了。Process Monitor 是windows下高級實時監聽工具,用於監視文件系統、註冊表、進程和線程的活動。code

下面是具體操做步驟:orm

  • 首先打開process monitor開始監控,雙擊打開11882.rtf樣本文件,待彈出計算器程序後,中止process monitor的監控(不關監控的話,會記錄不少其餘信息,不利於分析)。

  • 打開pchuntor查看cmd.exe的父進程id,獲得cmd.exe的父進程id爲428

  • 再在Process Monitor中的記錄大量記錄信息進行PID過濾,獲得是EQNEDT32.EXE這個程序建立的cmd.exe。它的路徑也能夠在下圖中獲得:

  • 點中任意一個條目,ctrl+p能夠獲得EQNEDT32.EXE的父進程ID

  • ok,同理使用Process Monitor的過濾功能,獲得原來是svchsot.exe建立的EQNEDIT32.EXE。

  • 在看看winword.exe中的進程相關信息,發現WINWORD.EXE是經過調用系統服務啓動的公式編輯器EQNEDT32.EXE(能夠選中下圖中選中那項,再Ctrl+P查看這一條記錄的棧信息)

    根據大佬解釋,這是一種叫作decom的調用方法(後臺調用com組件)。

    好了,既然已經找到了彈出計算器的進程是EQNEDT32.EXE,那麼咱們就打開這個程序,而後用windbg附加它,bp 那幾個函數,再打開11882.rtf樣本文件,看看能不能斷下來。嘿嘿斷下來了,能夠看到執行的命令參數爲:cmd.exe /c calc.exe &一堆亂碼

    好,下面進行棧回溯,看看是哪兒出了問題。

0x02 調試定位漏洞觸發點

  • 查看棧回溯信息以下:

    0:000> kb 4
    ChildEBP RetAddr  Args to Child              
    0018f1d0 00430c18 0018f354 00000000 0018f1f0 kernel32!WinExec
    WARNING: Stack unwind information not available. Following frames may be wrong.
    0018f214 004218e4 0018f354 0018f5e4 0018f7e4 eqnedt32!MFEnumFunc+0x241b
    0018f304 004214e2 0018f354 72ed005a 00000001 eqnedt32!FMDFontListEnum+0x650
    0018f330 0043b466 0018f354 72ed005a 0018f5e4 eqnedt32!FMDFontListEnum+0x24e

    能夠定位到返回位置爲0x00430c18,IDA 查看該位置處的代碼以下:

    .text:00430C0C                 push    1               ; uCmdShow
    .text:00430C0E                 mov     eax, [ebp+lpCmdLine]
    .text:00430C11                 push    eax             ; lpCmdLine
    .text:00430C12                 call    ds:WinExec      ; 調用的它
    .text:00430C18                 cmp     eax, 20h
    .text:00430C1B                 jnb     loc_430C43
  • 那麼是從哪兒執行到call ds:WinExec的呢?只有看棧的信息(或者使用ctrl+f8或ctrl+f7的方法,不建議使用)。很明顯棧被破壞了,只看獲得最近的一個返回地址是0x004218e4,IDA查看該位置處的代碼以下:

    .text:004218DE                 push    eax             ; lpString1
    .text:004218DF                 call    sub_4115A7 ;調用的它
    .text:004218E4                 add     esp, 4
    .text:004218E7                 test    eax, eax
    .text:004218E9                 jz      loc_421919
  • 好,使用OD來附加(由於windbg很差保存斷點記錄,也很差及時的看堆棧的信息,因此如今換OD上)。先打開EQNEDT32.EXE,用OD附加後在0x4218DF處下斷。打開11882.rtf樣本poc文件,發現斷到了0x4218DF處。

    而後單步步入,看看執行到call ds:WinExec的調用順序是啥子樣子的。有耐心的分析出來是這樣的:

    sub_4115A7--->sub_41160F--->ret--->call ds:WinExec

    Tip:我在進入了sub_41160F後(已經使用了bp WinExec函數下斷),使用Ctrl+F8,讓其自動單步步過找下一個call的時候,發現其實就沒有下一個call了。

    意思是:當自動單步步過中止的時候,按esc鍵先是回到call ds:WinExec處,再按一下esc鍵,就回到了sub_41160F函數的最後0x00411874 處了,而該處是一條ret指令。

    因此我在這條ret指令處下了斷點,從新調試,發現斷到這個ret指令的時候,棧頂的值爲0x00430c12,也就是call ds:WinExec指令的地址。

    因此判斷應該是棧溢出,覆蓋了函數的返回地址。

  • 那麼是哪兒把sub_41160F的返回地址給覆蓋成了0x430c12了呢?先無論,先看看進入sub_41160F函數的時候棧的狀況:能夠發現剛進入的時候,返回地址是沒有出問題的

  • 繼續單步調,發現到了這兒,返回地址就立刻從正確的0x004115d8變爲了,0x00430c12。

0x03 分析漏洞成因

​ 下面來分析一下這個sub_41160F函數:

int __cdecl sub_41160F(char *a1, char *a2, int a3)
{
  int result; // eax
  char v4; // [esp+Ch] [ebp-88h]
  char v5; // [esp+30h] [ebp-64h]
  __int16 v6; // [esp+51h] [ebp-43h]
  char *v7; // [esp+58h] [ebp-3Ch]
  int v8; // [esp+5Ch] [ebp-38h]
  __int16 v9; // [esp+60h] [ebp-34h]
  int v10; // [esp+64h] [ebp-30h]
  __int16 v11; // [esp+68h] [ebp-2Ch]
  char v12; // [esp+6Ch] [ebp-28h]
  int v13; // [esp+90h] [ebp-4h]

  LOWORD(v13) = -1;
  LOWORD(v8) = -1;
  v9 = strlen(a1);
  strcpy(&v12, a1); //這兒形成的 :覆蓋返回地址
  _strupr(&v12);
 /*
 .....省略一部分
 */
  return result;
}

堆棧圖:

strcpy(&v12,a1) 太明顯不過的棧溢出了,對棧上進行字符串拷貝未作長度檢測,若是a1所指向的字符串的長度大於或等於48個字節,就能夠徹底覆蓋掉返回地址。調試的時候發現a1所指向的內存爲下圖所示:

的確如此,((DWORD*)a1)[11] = 0x00430c12 就是call ds:WinExec的地址。

固然,讀取a1的過程我也分析了下:分析思路是 根據棧回溯,結合OD,IDA調試查找。是在sub_43b418中調用sub_4164fa讀取的a1,讀取終止條件是一直讀到\0結束。

_BYTE *__cdecl sub_4164FA(_BYTE *a1)
{
  char *v1; // ST0C_4
  _BYTE *result; // eax

  do
  {
    v1 = a1++;
    *v1 = sub_416352();//從一塊固定內存塊中讀取
  }
  while ( *v1 );//讀到\0結束
  result = a1;
  *a1 = 0;
  return result;
}

因此關鍵就是 看怎麼才能構造個樣本,讓咱們執行到這個地方,公式編輯器是將樣本的哪一個地方加載到了那個固定內存塊中,若是能夠找到,那麼就能夠構造樣本了。

通過回溯棧,找關鍵call 的方式,我發現 好像並非公式編輯器解析的文本文檔。

全是ole32的rpc*調用。等於說,我分析不動了。那就先暫時分析到這兒,等我功力上去了,再來搞。

0x04 總結

​ 微軟和Intel處理器的成功很大一部分緣由是由於他們的產品始終都盡最大努力向下兼容。可是這樣也形成了極大的安全隱患。好比這個公式編輯器,超級超級老了,不支持ASLR,DEP等漏洞緩解措施。可是爲了保持向下兼容,儘管都office 2016了,微軟仍是將它保留了下來。

​ 因此,不少人都會選擇去挖那些微軟爲了兼容性而保留下來的軟件的漏洞。我估計不止office軟件,像服務器上的軟件好比:SQL Server系列的軟件 確定也有不少。

​ 怎麼去挖呢???來個高人指點指點我吧。

相關文章
相關標籤/搜索