[原创]发段Hive格式解析的VB代码

信息来源:邪恶八进制信息安全团队(www.eviloctal.com
文章作者:炉子
Code Language : Visual Basic
  1. Attribute VB_Name = \"mHiveControl\"
  2.  
  3. 'By 炉子[0GiNr]
  4. 'http://hi.baidu.com/breakinglove_
  5. 'http://0ginr.com
  6.  
  7. Option Explicit
  8.  
  9. Public Declare Function RegRestoreKey Lib \"advapi32.dll\" Alias \"RegRestoreKeyA\" ( _
  10.      ByVal hKey As Long, _
  11.      ByVal lpFile As String, _
  12.      ByVal dwFlags As RegRestoreFlags) As Long
  13. Public Declare Function RegSaveKeyEx Lib \"advapi32.dll\" Alias \"RegSaveKeyExA\" ( _
  14.      ByVal hKey As Long, _
  15.      ByVal lpFile As String, _
  16.      ByVal lpSecurityAttributes As Long, _
  17.      ByVal dwFlags As RegSaveExFlags) As Long
  18. Public Enum RegKeys
  19.     HKEY_CLASSES_ROOT = &H80000000
  20.     HKEY_CURRENT_USER = &H80000001
  21.     HKEY_LOCAL_MACHINE = &H80000002
  22.     HKEY_USERS = &H80000003
  23.     HKEY_CURRENT_CONFIG = &H80000005
  24. End Enum
  25. Public Enum RegRestoreFlags
  26.     REG_FORCE_RESTORE = &H8
  27.     REG_WHOLE_HIVE_VOLATILE = &H1
  28. End Enum
  29. Public Enum RegSaveExFlags
  30.     REG_STANDARD_FORMAT = &H1
  31.     REG_LATEST_FORMAT = &H2
  32.     REG_NO_COMPRESSION = &H4
  33. End Enum
  34. Public Type LARGE_INTEGER
  35.     LowPart As Long
  36.     HighPart As Long
  37. End Type
  38. Public Type RegfBlock
  39.     dwSignature As Long '字符串 - \"regf\" = 0x66676572
  40.     dwUnknown1 As Long '未知
  41.     dwUnknown2 As Long '总是为 0x00000004
  42.     liLastEdit As LARGE_INTEGER 'NT 时间格式
  43.     dwNumber1 As Long '恒为1
  44.     dwNumber2 As Long '恒为3
  45.     dwNumber3 As Long '恒为0
  46.     dwNumber4 As Long '恒为1 - 或许这个1301是版本1.3.0.1?
  47.     dwOffsetOfFirstKeyRecord As Long '第一个键纪录的偏移
  48.     dwBlockSize As Long '数据块大小(文件大小-4kb)
  49.     dwNumber5 As Long '恒为1
  50.     bytUnknownData(1 To &H1CC) As Byte '无需分析
  51.     dwSum As Long '从 0x00000000 至 0x000001FB 的所有DWORD的数据总和
  52. End Type
  53.  
  54. Public Type UnkownDataAfterRegfBlock '紧随 RegfBlock 之后
  55.     bytReserved(1 To &HE00) As Byte '未知
  56. End Type
  57.  
  58. Public Type HBinHeader
  59.     dwSignature As Long '字符串 - \"hbin\" = 0x6E696268
  60.     dwOffsetFromFirstHBinRecord As Long '第一个 Hbin 记录的偏移
  61.     dwOffsetFromNextHBinRecord As Long '下一个 Hbin 记录的偏移
  62.     dwUnknownData(1 To &H10) As Byte
  63.     dwBlockSize As Long 'Hbin 记录长度
  64. End Type
  65.  
  66. Public Type HBinData '如果这个段是一个负值(第 31 位被置1),则这个块是空的,并且长度被置为负的块大小
  67.     dwDataBlockSize As Long
  68.     szData() As Byte '长度取决于 dwDataBlockSize
  69. End Type
  70.  
  71. Public Type NkRecord 'NameKey
  72.     wSignature As Integer '字符串 - \"nk\" = 0x6B6E
  73.     wKeyType As Integer '根键为 0x2C,否则为0x20
  74.     liLastEdit As LARGE_INTEGER 'NT 时间格式
  75.     bytUnknowData(1 To &H4) As Byte
  76.     dwOffsetOfParentKey As Long '父键的偏移
  77.     dwSubKeyNumber As Long '子键数目
  78.     bytUnknowData2(1 To &H4) As Byte
  79.     dwOffsetOfSubKeyLfRecords As Long '子键的 Lf 记录的偏移
  80.     bytUnknowData3(1 To &H4) As Byte
  81.     dwValuesNumber As Long '项的数目
  82.     dwOffsetOfValueList As Long 'NkRecordValueList 的偏移
  83.     dwOffsetOfSkRecord As Long 'Sk 记录的偏移
  84.     dwOffsetOfClassName As Long '类名的偏移(???)
  85.     bytUnused(1 To &H10) As Byte
  86.     dwUnused As Long '无用数据
  87.     wNameLength As Integer '项名长度
  88.     wClassNameLength As Integer '类名的长度(???)
  89.     szKeyName(1 To 1) As Byte '长度取决于 dwNameLength
  90. End Type
  91.  
  92. Public Type NkRecordValueList
  93.     dwValueOffset(1) As Long '数组数量取决于 dwValuesNumber
  94. End Type
  95.  
  96. Public Type VkRecord 'ValueKey
  97.     wSignature As Integer '字符串 - \"vk\" = 0x6B76
  98.     wNameLength As Integer '项名长度
  99.     dwDataLength As Long '数据长度 - 如果 dwDataLength <=4 那么这个值的数据就是该项的数据 (DWORD);如果为 0 那么这个项无数据
  100.     dwDataOffset As Long '数据偏移
  101.     dwValueType As Long '数据类别 - 数据类别见 DataTypes
  102.     wFlags As Integer '如果第 0 位被置1,那么这条数据是有名称的,否则意味着这条数据是无名称的(“默认”)
  103.     wUnused As Integer '无用数据
  104.     szName(1 To 1) As Byte
  105. End Type
  106.  
  107. Public Enum DataTypes
  108.     REG_SZ = &H1 '字符串 UNICODE
  109.     REG_EXPEND_SZ = &H2 '可展开的字符串(使用环境变量,例如 \"%SystemRoot%\system32\") UNICODE
  110.     REG_BINARY = &H3 '二进制数据
  111.     REG_DWORD = &H4 'DWORD
  112.     REG_MULTI_SZ = &H7 '多个字符串,使用 vbNullChar 分隔 UNICODE
  113.     REG_UNKNOWN = &HFFFFFFFF
  114. End Enum
  115.  
  116. Public Type HashRecord 'Lf 记录的哈希记录
  117.     dwRecordOffset As Long '所属的 Lf 记录的偏移
  118.     szKeyName(1 To 4) As Byte '键名的前4字节 如果修改了键名,这个也需要修改
  119. End Type
  120.  
  121. Public Type LfRecord
  122.     wSignature As Integer '字符串 - \"lf\" = 0x666C
  123.     wKeyNumber As Integer '键的数目
  124.     dwHashRecord(1 To 1) As HashRecord
  125. End Type
  126.  
  127. Public Type SkRecord 'SecurityKey
  128.     wSignature As Integer '字符串 - \"sk\" = 0x6B73
  129.     wUnused As Integer
  130.     dwPreviousSkRecordOffset As Long '前一个Sk记录的偏移
  131.     dwNextSkRecordOffset As Long '后一个Sk记录的偏移
  132.     dwUsageCounter As Long '使用计数 (???)
  133.     dwRecordSize As Long 'Sk记录的字节数
  134.     '剩余部分为权限设置数据
  135. End Type
  136.  
  137. Public Declare Function SafeCopyMemory _
  138.         Lib \"NTDLL.DLL\" Alias \"ZwWriteVirtualMemory\" _
  139.                 (ByVal ProcessHandle As Long, _
  140.                 ByVal pDest As Long, _
  141.                 ByVal pSrc As Long, _
  142.                 ByVal NumberOfBytesToCopy As Long, _
  143.                 ByRef NumberOfBytesCopied As Long) As Long
  144. Public Const ZwGetCurrentProcess As Long = -1 '//0xFFFFFFFF
  145. Dim m_pHive As Long
  146. Dim m_RegfBlock As RegfBlock, m_HBinHeader As HBinHeader, m_RootNkRecord As NkRecord
  147. Dim m_RaisedErr As Boolean
  148. Dim m_pRootNk As Long
  149. Private Const GlobalOffset As Long = &H1004
  150. Private Const RegDefault As String = \"(Default)\"
  151.  
  152. Public Sub dbg()
  153.     Dim a As NkRecord
  154.     Debug.Print Hex(LenB(a))
  155. End Sub
  156.  
  157. 'hHive should be the base of the hive file in memory
  158. Public Function PreProcessHive(ByVal hHive As Long) As Boolean
  159.     Dim st As Long
  160.     Dim hBase As Long
  161.     Dim unKnownData As UnkownDataAfterRegfBlock
  162.    
  163.     'save hive pointer
  164.     m_pHive = hHive
  165.    
  166.     hBase = hHive
  167.    
  168.     'read regf block
  169.     st = CopyMemory(VarPtr(m_RegfBlock), hBase, LenB(m_RegfBlock))
  170.     If (Not st) Then GoTo InitFaild_
  171.    
  172.     'read hbin header
  173.     hBase = hBase + LenB(m_RegfBlock) + LenB(unKnownData)
  174.     st = CopyMemory(VarPtr(m_HBinHeader), hBase, LenB(m_HBinHeader))
  175.     If (Not st) Then GoTo InitFaild_
  176.    
  177.     'read root nk header
  178.     Dim HbData As HBinData
  179.     st = CopyMemory(VarPtr(HbData), hBase + LenB(m_HBinHeader), LenB(HbData))
  180.     If (Not st) Then GoTo InitFaild_
  181.     hBase = hBase + GetHBinSize(HbData)
  182.     st = CopyMemory(VarPtr(m_RootNkRecord), hBase, LenB(m_RootNkRecord))
  183.     m_pRootNk = hBase
  184.     If (Not st) Then GoTo InitFaild_
  185.    
  186.     'return
  187.     PreProcessHive = True
  188.     Exit Function
  189. InitFaild_:
  190.     PreProcessHive = False
  191. End Function
  192.  
  193. '这两段是测试用的。
  194. Public Sub NOP()
  195.     NOP1 (m_pRootNk)
  196.    
  197.     DoEvents
  198. End Sub
  199.  
  200. Public Sub NOP1(ByVal lpNk As Long)
  201.     'MsgBox GetKeyNameByPointer(m_pRootNk)
  202.     Dim szReturn As String
  203.     Dim I As Long, J As Long
  204.     Dim nks() As Long
  205.     Dim lfs() As Long
  206.     lfs = GetSubKeyListNkPointers(lpNk)
  207.     For I = LBound(lfs) To UBound(lfs)
  208.         Dim vks() As Long
  209.         vks = GetValueListVkPointers(lfs(I))
  210.         szReturn = szReturn & \"KeyName:\" & GetKeyNameByPointer(lfs(I)) & vbCrLf
  211.         If (Not m_RaisedErr) Then
  212.             For J = LBound(vks) To UBound(vks)
  213.                 If (vks(J)) = 0 Then Exit For
  214.                 Dim dt As DataTypes
  215.                 dt = GetValueTypeByPointer(vks(J))
  216.                 Dim ret() As Byte
  217.                 ret = GetValueDataByPointer(vks(J), dt)
  218.                 If dt = REG_DWORD Then
  219.                     Dim K As Long
  220.                     Call CopyMemory(VarPtr(K), VarPtr(ret(1)), 4)
  221.                     szReturn = szReturn & vbTab & GetValueNameByPointer(vks(J)) & vbTab & K & vbCrLf
  222.                 ElseIf dt = REG_SZ Then
  223.                     Dim szValue As String: szValue = ret
  224.                     szReturn = szReturn & vbTab & GetValueNameByPointer(vks(J)) & vbTab & szValue & vbCrLf
  225.                 Else
  226.                     szReturn = szReturn & vbTab & GetValueNameByPointer(vks(J)) & vbTab & \"(Unsupportted value type = \" & dt & \")\" & vbCrLf
  227.                 End If
  228.                 DoEvents
  229.             Next
  230.  
  231.         Else
  232.             ClearError
  233.         End If
  234.     Next
  235.     DoEvents
  236.     WriteFile App.Path & \"\Output.txt\", StrConv(szReturn, vbFromUnicode)
  237. End Sub
  238.  
  239. 'get the size of the HBIN block
  240. Private Function GetHBinSize(ByRef pHBinInfo As HBinData) As Long
  241.     Dim HBHdrInfo As HBinHeader
  242.     If (pHBinInfo.dwDataBlockSize And &H80000000) Then
  243.         'the 31bit of 0x80000000 is 1, others are 0
  244.         GetHBinSize = LenB(HBHdrInfo) + LenB(pHBinInfo.dwDataBlockSize)
  245.         Exit Function
  246.     Else
  247.         GetHBinSize = LenB(HBHdrInfo) + LenB(pHBinInfo.dwDataBlockSize) + pHBinInfo.dwDataBlockSize
  248.     End If
  249. End Function
  250.  
  251. 'get key name from NK record
  252. Public Function GetKeyNameByPointer(ByVal pNkRecord As Long) As String
  253.     Dim retByt() As Byte
  254.     Dim szRetKeyName As String
  255.     Dim Offset As Long
  256.     Dim NkRec As NkRecord
  257.     Dim st As Boolean
  258.     ReDim pVkRec(1 To 1)
  259.     st = CopyMemory(VarPtr(NkRec), pNkRecord, LenB(NkRec))
  260.     If (Not st) Then GoTo ExitFunc_
  261.     With NkRec
  262.         If (.wNameLength = 0) Then GoTo ExitFunc_
  263.         ReDim retByt(.wNameLength)
  264.         Offset = VarPtr(.szKeyName(1)) - VarPtr(NkRec) + pNkRecord ' - m_pHive
  265.         st = CopyMemory(VarPtr(retByt(LBound(retByt))), Offset, .wNameLength)
  266.         If (Not st) Then GoTo ExitFunc_
  267.         szRetKeyName = StrConv(retByt, vbUnicode)
  268.         If (InStr(szRetKeyName, vbNullChar)) Then szRetKeyName = Left(szRetKeyName, InStr(szRetKeyName, vbNullChar) - 1)
  269.     End With
  270. FinishFunc_:
  271.     Erase retByt
  272.     GetKeyNameByPointer = szRetKeyName
  273.     Exit Function
  274. ExitFunc_:
  275.     m_RaisedErr = True
  276.     'Resume FinishFunc_
  277. End Function
  278.  
  279. 'get key name from NK record
  280. Public Function GetValueNameByPointer(ByVal pVkRecord As Long) As String
  281.     Dim retByt() As Byte
  282.     Dim szRetName As String
  283.     Dim Offset As Long
  284.     Dim VkRec As VkRecord
  285.     Dim st As Boolean
  286.     ReDim pVkRec(1 To 1)
  287.     st = CopyMemory(VarPtr(VkRec), pVkRecord, LenB(VkRec))
  288.     If (Not st) Then GoTo ExitFunc_
  289.     With VkRec
  290.         If (.wNameLength = 0) Then szRetName = RegDefault: GoTo FinishFunc_
  291.         ReDim retByt(.wNameLength)
  292.         Offset = VarPtr(.szName(1)) - VarPtr