熱點推薦:
您现在的位置: 電腦知識網 >> 操作系統 >> Windows系統管理 >> 正文

NT平台撥號連接密碼恢復原理

2013-11-11 21:52:21  來源: Windows系統管理 

  前段時間ADSL密碼忘記了但幸好還保存在撥號連接裡面於是到網上找了些星號密碼顯示工具可惜不起作用後來找到一種名為dialupass的工具這家伙還真的把密碼給我還原出來了(用的dialupass v我的系統是windows xp)
  
  看起來dialupass非普通的星號密碼顯示工具那它的原理是什麼呢?上GOOGLE查了一翻沒找到相關資料(可能是我用的關鍵字有問題) 一生氣便操起家伙(windbg)准備把它大卸八塊郁悶的是用windbg加載後密碼就還原不出來了顯示是星號換替補ollydbg上場情況依舊莫非這小工具有AntiDebug功能?當時只是一絲懷疑因為實在不相信這樣的小工具作者會花心思來保護
  
  後來在用sice跟蹤的過程中發現有這麼一個調用
  
  GetProcAddress(xx IsDebugPresent)
  
  暈倒原來真的有AntiDebug功能好在比較簡單統計了一下總共有處進行了AntiDebug檢查情況查明了便換回windbg來調試在windbg裡面下這麼一個斷點便可繞過AntiDebug檢測
  
  bp KERNEL!IsDebuggerPresent g poi(esp);r eax=;g
  
  花了些時間跟蹤了一下把dialupass恢復密碼的流程都搞清楚了這小程序貓膩還挺多的總結如下
  
   關鍵函數不直接調用而是用LoadLibraryA和GetProcAddress來獲取函數地址後再CALL
   函數名是經過編碼的反匯編後看字符串是看不到的
   關鍵地方一概用花指令來迷惑你和反匯編軟件
  
  其實原理很簡單就是用rasapidll裡面的一些函數來獲取撥號連接的一些信息再用 ADVAPI!LsaRetrievePrivateData 函數來獲取密碼根據dialupasss的原理寫了個類似的工具源代碼參見後面的x_dialupassc後來用LsaRetrievePrivateDataRasDialParams做關鍵字重新在GOOGLE搜索了一遍找到一些類似的代碼
  
  參考資源[]和[]的是俄羅斯人公布的演示代碼沒有對LsaRetrievePrivateData返回的數據進行拆分用戶名和密碼參考資源[]是日本人公布的完整的應用程序的代碼可惜在對LsaRetrievePrivateData返回的數據進行拆分處理時存在BUG導致有些情況下用戶名和密碼取的不正確後來發現lsadump DUMP出來的數據裡面包含了LsaRetrievePrivateData返回的數據lsadump的原理大致如下
  
  )插入一線程到lsassexe進程
  )打開LSA Policy database
  )從注冊表"HKLM\SECURITY\Policy\Secrets"中枚舉子鍵
  )LsarOpenSecret
  )LsarQuerySecret
  
  進一步跟蹤後發現其實ADVAPI!LsaRetrievePrivateData是通過NdrClientCall 發送RPC調用到lsassexe進程lsassexe裡面再調用LsarOpenSecretLsarQuerySecret來完成獲取撥號連接信息過程的(注LsarOpenSecret裡面有權限判斷非ADMIN組用戶是沒有權限來調用ADVAPI!LsaRetrievePrivateData的)跟蹤了一下LsarQuerySecret發現它返回的數據其實是從注冊表中讀取保存撥號連接信息的注冊表鍵值為
  
  HKLM\SECURITY\Policy\Secrets\RasDialParams!SID#\CurrVal
  
  SID對應的是用戶的string SID(HKLM\SECURITY這個鍵只有SYSTEM有權限讀寫連admin都沒有權限)
  
  LsarQuerySecret從注冊表中讀取出來數據後接著調用LsapCrDecryptValue函數來解密對於同一台機器來說解密時用的KEY始終都是固定的這個KEY在lsasrvdll裡面變量名為_LsapDbSecretCipherKey在windows 裡面變量名不一樣對應的有兩個分別為LsapDbSecretCipherKeyWriteLsapDbSecretCipherKeyRead但這兩個變量裡面的數據是一樣的LsapCrDecryptValue用的似乎是標准DES算法解密時主要流程如下
  
  lsasrv!LsapCrDecryptValue
  |_ advapi!SystemFunction
  |_ advapi!DecryptDataLength
  |_ advapi!SystemFunction
  |_ advapi!DES_ECB_LM
  |_ advapi!des
  
  解密後<<"標示處還有一個判斷:
  
  .text:785462F0 call_LsapCrDecryptValue@12
  .text:785462F5 testeax, eax
  .text:785462F7 mov [ebp+var_8], eax
  .text:785462FA jl
  loc_785838E1
  .text:78546300
  .text:78546300 loc_78546300:
  .text:78546300 cmp byte ptr [esi+45h], 0
  
  .text:78546304 jz  short loc_7854632E
  ......
  .text:7854632E loc_7854632E:
  .text:7854632E lea eax, [ebp+var_10]
  .text:78546331 pusheax
  .text:78546332 push[ebp+arg_8]
  .text:78546335 push[ebp+var_C]
  .text:78546338 call_LsapCrEncryptValue@12
  
  假如[esi+45h]為0的話(esi是LsarOpenSecret函數返回的HANDLE),它會把解密後的數據再進行一次加密,不管是2000還是2003,這時用的KEY始終都是固定為“SystemLibraryDTC”。TW.WiNgwit.Comlsadump2裡面調用LsarOpenSecret得到的HANDLE,偏移0x45處值為1,所以LsarQuerySecret函數返回的就是解密後的數據了。而在調用ADVAPI32!LsaRetrievePrivateData時,LsarOpenSecret返回的HANDLE偏移。0x45處值為0x0,所以LsarQuerySecret返回的是解密後又加密的數據,所以在ADVAPI32!LsaRetrievePrivateData裡面還有一個對應的解密過程。相應的,LsapCrEncryptValue加密的主要流程如下:
  
  lsasrv!LsapCrEncryptValue
  |_ advapi32!SystemFunction004
  |_ advapi32!EncryptDataLength
  |_ advapi32!SystemFunction001
  |_ advapi32!DES_ECB_LM
  |_ advapi32!des
  
  開始我以為在同一版本的windows裡面,_LsapDbSecretCipherKey是固定的,後來發現我錯了。那麼這個_LsapDbSecretCipherKey是如何產生的?流程如下:
  
  (1)調用ntdll!NtConnectPort打開 L"\Security\WxApiPort"
  (2)調用ntdll!NtRequestWaitReplyPort得到一些數據 。ebp-40處為NtRequestWaitReplyPort返回的LPCMESSAGE。
  
  kd>; dd ebp-40
  0006fcb8 00400028 00000002 000000dc 000000d8
  0006fcc8 00000024 00000000 00000000 00000000
  0006fcd8 00000001 00000010 00000010 fd317e3e
  0006fce8 7e24e86d d12503d3 5f7d01a8 7665f528
  kd>; db ebp
  fce e e fd d e ed d a d f
  
  ()將上述ebp處的x字節數據COPY到lsasrvdll裡面的_LsapDbSysKey變量 _LsapDbSysKey在不同的機器上面(即使版本相同)都是不一樣的它是怎麼產生的?有幸拜讀了flashsky的大作後(參考資源[])才明白這就是傳說中的SYSKEY用flashsk的代碼驗證一下
  
  c:\>;getsyskey
  e e fd d e e d d a d f
  
  跟蹤系統啟動過程可知道\Security\WxApiPort是由winlogonexe進程創建的然後lsass進程通過這個LPC PORT從winlogon進程獲取SYSKEY隨後winlogon進程會關閉這個LPC PORT所以在系統啟動完成之後Process Explorer等工具是看不到這個LPC PORT存在的而且在winlogon和LSASS進程空間都搜索不到上述SYSKEY
  
  ()從注冊表HKLM\SECURITY\Policy\PolSecretEncryptionKey中讀取出來一段數據調用函數_LsapDbDecryptKeyWithSyskey把它用_LsapDbSysKey來解密 _LsapDbSecretCipherKey就在解密完後的數據裡面LsapDbDecryptKeyWithSyskey函數做的其實就是MD和RC運算)了解原理後我們就可以直接從注冊表裡面來獲取撥號連接中的密碼等數據了但有幾個問題需要解決
  
  ()原料
  
  Q:HKLM\SECURITY鍵只有SYSTEM有權限讀寫?
  A:我們可以把代碼插入到SYSTEM進程裡面去運行或者把這個鍵修改為ADMIN有權限讀或者提升本進程權限
  
  ()催化劑:)
  
  Q: 如何獲取_LsapDbSysKey?解密用的函數_LsapDbDecryptKeyWithSyskey為非導出函數怎麼辦?
  A: 用flashsky的代碼來獲取SYSKEY利用公開的MD和RC庫函數來解密
  A: 直接從lsassexe進程裡面搜索_LsapDbSecretCipherKey它的結構如下:
  
  typedef struct _LSA_BLOB {
  DWORD cbData;
  DWORD cbMaxData;
  BYTE* pbData;
  } LSA_BLOB;
  
  pbData指向存儲KEY的地址KEY長度固定為x字節即cbData和cbMaxData都是固定為x所以從lsass進程的空間裡面搜索\x\x\x\x\x\x\x\x即可找到正確的KEY結果可能會有多個可以把所有搜索到的KEY都試一下總有一個正確的
  
  ()工具
  
  Q: 解密函數LsapCrDecryptValue為非導出函數怎麼辦?
  A: 或許可以根據特征碼來搜索但總覺得不太可靠
  
  幸好LsapCrDecryptValue 調用的advapi!SystemFunction是導出函數:)或者直接利用公開的DES庫函數自己來運算x_dialupasscpp 中的代碼演示了直接從注冊表中讀取數據並解密之的過程沒有太多實際意義
From:http://tw.wingwit.com/Article/os/xtgl/201311/9385.html
  • 上一篇文章:

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