首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

[chenhui530]VB 拷贝SAM文件,该怎么解决

2012-01-23 
[chenhui530]VB 拷贝SAM文件最近出差在外,写了几篇文章也没时间发布出来.前些天看到有朋友提到这方面,我也

[chenhui530]VB 拷贝SAM文件
最近出差在外,写了几篇文章也没时间发布出来.
前些天看到有朋友提到这方面,我也就留意了下
抽了点时间写了这个程序,其实这个程序也是转换
C的代码,希望对大家有帮助.下面是完整源码


VERSION   5.00
Begin   VB.Form   frmMain  
      BorderStyle           =       1     'Fixed   Single
      Caption                   =       "SAM文件复制 "
      ClientHeight         =       3090
      ClientLeft             =       45
      ClientTop               =       435
      ClientWidth           =       4680
      LinkTopic               =       "Form1 "
      MaxButton               =       0       'False
      MinButton               =       0       'False
      ScaleHeight           =       3090
      ScaleWidth             =       4680
      StartUpPosition   =       3     '窗口缺省
      Begin   VB.TextBox   txtPath  
            Height                     =       345
            Left                         =       1200
            TabIndex                 =       1
            Text                         =       "c:\sam "
            Top                           =       630
            Width                       =       2265
      End
      Begin   VB.CommandButton   cmdCopy  
            Caption                   =       "复制 "
            Height                     =       465
            Left                         =       1470
            TabIndex                 =       0
            Top                           =       1260
            Width                       =       1275


      End
End
Attribute   VB_Name   =   "frmMain "
Attribute   VB_GlobalNameSpace   =   False
Attribute   VB_Creatable   =   False
Attribute   VB_PredeclaredId   =   True
Attribute   VB_Exposed   =   False
Private   Declare   Function   DeviceIoControl   Lib   "kernel32 "   (ByVal   hDevice   As   Long,   ByVal   dwIoControlCode   As   Long,   lpInBuffer   As   Any,   ByVal   nInBufferSize   As   Long,   lpOutBuffer   As   Any,   ByVal   nOutBufferSize   As   Long,   lpBytesReturned   As   Long,   lpOverlapped   As   Any)   As   Long
Private   Declare   Function   CreateFile   Lib   "kernel32 "   Alias   "CreateFileA "   (ByVal   lpFileName   As   String,   ByVal   dwDesiredAccess   As   Long,   ByVal   dwShareMode   As   Long,   lpSecurityAttributes   As   Any,   ByVal   dwCreationDisposition   As   Long,   ByVal   dwFlagsAndAttributes   As   Long,   ByVal   hTemplateFile   As   Long)   As   Long
Private   Declare   Function   WriteFile   Lib   "kernel32 "   (ByVal   hFile   As   Long,   lpBuffer   As   Any,   ByVal   nNumberOfBytesToWrite   As   Long,   lpNumberOfBytesWritten   As   Long,   lpOverlapped   As   Any)   As   Long
Private   Declare   Function   SetFilePointer   Lib   "kernel32 "   (ByVal   hFile   As   Long,   ByVal   lDistanceToMove   As   Long,   lpDistanceToMoveHigh   As   Long,   ByVal   dwMoveMethod   As   Long)   As   Long
Private   Declare   Function   ReadFile   Lib   "kernel32 "   (ByVal   hFile   As   Long,   lpBuffer   As   Any,   ByVal   nNumberOfBytesToRead   As   Long,   lpNumberOfBytesRead   As   Long,   lpOverlapped   As   Any)   As   Long
Private   Declare   Function   GetSystemDirectory   Lib   "kernel32 "   Alias   "GetSystemDirectoryA "   (ByVal   lpBuffer   As   String,   ByVal   nSize   As   Long)   As   Long
Private   Declare   Function   GetDiskFreeSpace   Lib   "kernel32 "   Alias   "GetDiskFreeSpaceA "   (ByVal   lpRootPathName   As   String,   lpSectorsPerCluster   As   Long,   lpBytesPerSector   As   Long,   lpNumberOfFreeClusters   As   Long,   lpTotalNumberOfClusters   As   Long)   As   Long
Private   Declare   Function   GetFileSize   Lib   "kernel32 "   (ByVal   hFile   As   Long,   lpFileSizeHigh   As   Long)   As   Long
Private   Declare   Sub   CopyMemory   Lib   "kernel32 "   Alias   "RtlMoveMemory "   (Destination   As   Any,   Source   As   Any,   ByVal   Length   As   Long)
Private   Declare   Function   CloseHandle   Lib   "kernel32 "   (ByVal   hObject   As   Long)   As   Long
Private   Const   GENERIC_READ   =   &H80000000
Private   Const   FILE_SHARE_READ   =   &H1


Private   Const   FILE_SHARE_WRITE   =   &H2
Private   Const   OPEN_EXISTING   =   3
Private   Const   INVALID_HANDLE_VALUE   =   -1
Private   Const   GENERIC_WRITE   =   &H40000000
Private   Const   OPEN_ALWAYS   =   4
Private   Const   FILE_READ_ATTRIBUTES   =   (&H80)
Private   Const   FSCTL_GET_RETRIEVAL_POINTERS   =   589939

Private   Type   RETRIEVAL_POINTERS_BUFFER
        dwExtentCount   As   Long
        bytStartingVcn(7)   As   Byte   '这些都可以使用LARGE_INTEGER类型代替
        bytNextVcn(7)   As   Byte   '这些都可以使用LARGE_INTEGER类型代替
        bytLcn(7)   As   Byte   '这些都可以使用LARGE_INTEGER类型代替
        lngTmp   As   Long
End   Type

Private   Type   LARGE_INTEGER
        LowPart   As   Long
        HighPart   As   Long
End   Type

Private   Sub   cmdCopy_Click()
        Dim   strSamPath   As   String
        strSamPath   =   GetSystemPath   &   "\Config\Sam "
        If   CopySamFile(strSamPath,   txtPath.Text)   Then
                MsgBox   "复制完毕!! ",   vbInformation,   "提示 "
        Else
                MsgBox   "复制错误!! ",   vbCritical,   "提示 "
        End   If
End   Sub

'获取系统目录路径
Private   Function   GetSystemPath()   As   String
        Dim   strTmp   As   String
        strTmp   =   String(260,   Chr(0))
        GetSystemDirectory   strTmp,   260
        strTmp   =   Left(strTmp,   InStr(strTmp,   Chr(0))   -   1)
        GetSystemPath   =   strTmp
End   Function

Private   Function   GetFileClusters(ByVal   strFileName   As   String,   ByVal   lngClusterSize   As   Long,   lngClCount   As   Long,   lngFileSize   As   Long)   As   Long()
        Dim   hFile   As   Long
        Dim   lngOutSize   As   Long
        Dim   lngBytes   As   Long,   lngCls   As   Long,   lngCnCount   As   Long,   r   As   Long,   lngCount   As   Long,   i   As   Long,   j   As   Long
        Dim   lngClusters()   As   Long
        Dim   bytInBuf(7)   As   Byte
        Dim   objOutBuf   As   RETRIEVAL_POINTERS_BUFFER
        hFile   =   CreateFile(strFileName,   FILE_READ_ATTRIBUTES,   _
                                              FILE_SHARE_READ   Or   FILE_SHARE_WRITE   Or   FILE_SHARE_DELETE,   _


                                              ByVal   0&,   OPEN_EXISTING,   0,   0)
        If   hFile   <>   INVALID_HANDLE_VALUE   Then
                lngFileSize   =   GetFileSize(hFile,   0)
                lngOutSize   =   32   +   (lngFileSize   /   lngClusterSize)   *   16
                If   DeviceIoControl(hFile,   FSCTL_GET_RETRIEVAL_POINTERS,   bytInBuf(0),   8,   objOutBuf,   lngOutSize,   lngBytes,   ByVal   0&)   Then
                        lngClCount   =   (lngFileSize   +   lngClusterSize   -   1)   \   lngClusterSize
                        CopyMemory   lngCount,   objOutBuf.bytNextVcn(4),   4
                        For   r   =   0   To   objOutBuf.dwExtentCount   -   1
                                CopyMemory   j,   objOutBuf.bytLcn(4),   4
                                For   i   =   lngCount   To   0   Step   -1
                                        ReDim   Preserve   lngClusters(0   To   lngCls)
                                        lngClusters(lngCls)   =   j
                                        j   =   j   +   1
                                        lngCls   =   lngCls   +   1
                                Next
                        Next
                        CloseHandle   hFile
                        GetFileClusters   =   lngClusters
                End   If
        End   If
End   Function

Private   Function   CopySamFile(ByVal   strSamPath   As   String,   ByVal   strDestPath   As   String)   As   Boolean
        Dim   lngClusterSize   As   Long
        Dim   lngClusters()   As   Long
        Dim   lngClCount   As   Long,   lngFileSize   As   Long,   lngBytes   As   Long
        Dim   hDrive   As   Long,   hFile   As   Long


        Dim   lngSecPerCl   As   Long,   lngBtPerSec   As   Long,   r   As   Long
        Dim   curTmp   As   Currency
        Dim   ligNo   As   LARGE_INTEGER
        Dim   bytBuff()   As   Byte
        GetDiskFreeSpace   Left(strSamPath,   2),   lngSecPerCl,   lngBtPerSec,   ByVal   0&,   ByVal   0&
        lngClusterSize   =   lngSecPerCl   *   lngBtPerSec
        On   Error   GoTo   ErrHandle
        lngClusters   =   GetFileClusters(strSamPath,   lngClusterSize,   lngClCount,   lngFileSize)
        hDrive   =   CreateFile( "\\.\ "   &   Left(strSamPath,   2),   GENERIC_READ,   FILE_SHARE_READ   Or   FILE_SHARE_WRITE,   ByVal   0&,   OPEN_EXISTING,   0,   0)
        If   hDrive   <>   INVALID_HANDLE_VALUE   Then
                hFile   =   CreateFile(strDestPath,   GENERIC_WRITE,   0,   ByVal   0,   OPEN_ALWAYS,   0,   0)
                If   hFile   <>   INVALID_HANDLE_VALUE   Then
                        For   r   =   0   To   lngClCount   -   1
                                curTmp   =   Ccur(lngClusterSize)   *   Ccur(lngClusters(r))   /10000     'lngClusterSize   *   lngClusters(r)
                                CopyMemory   ligNo,   curTmp,   Len(ligNo)
                                Call   SetFilePointer(hDrive,   ligNo.LowPart,   ligNo.HighPart,   0)
                                If   lngFileSize   <   lngClusterSize   Then
                                        ReDim   bytBuff(lngFileSize   -   1)
                                Else
                                        ReDim   bytBuff(lngClusterSize   -   1)
                                End   If
                                Call   ReadFile(hDrive,   bytBuff(0),   lngClusterSize,   lngBytes,   ByVal   0&)
                                lngFileSize   =   lngFileSize   -   lngBytes
                                Call   WriteFile(hFile,   bytBuff(0),   lngClusterSize,   lngBytes,   ByVal   0&)


                                Debug.Print   ligNo.LowPart;   ligNo.HighPart
                        Next
                End   If
                CloseHandle   hFile
        End   If
        CloseHandle   hDrive
        CopySamFile   =   True
        Exit   Function
ErrHandle:
        If   hDrive   <>   -1   Then   CloseHandle   hDrive
        If   hFile   <>   -1   Then   CloseHandle   hFile
End   Function


[解决办法]
我来解释一下什么是SAM文件:

SAM最初是跟随第一代NT来到世界的,它在微软总部的特工代号叫做“安全账户管理器”(Security Accounts Manager),可以所sam文件是windows的门卫,在win2k时代这个门卫不太强大,到了NT内核时代,这个家伙的作用就变得强大了。SAM记录的数据很多,包括所有组、账户信息、密码HASH、账户SID等,应该说是一个考虑得比较周全的门卫。


SAM不仅仅是一个文件那么简单,它不但有文件数据,在注册表里面还有一个数据库,位于HKEY_LOCAL_MACHINE\\SAM下,这是一个比较复杂的结构。SAM在系统启动后就处于锁定状态,我们没法擅自更改这个文件内容。

在注册表里我们可以看到一下内容:
1.在HKEY_LOCAL_MACHINE\\SAM\\SAM\\
Domains下就是SAM的内容,其下有两个分支“Account”和“Builtin”。

2.Domains\\Account\\Users下存放的就是各个账号的信息,当然,这里是加密过的二进制数据,每个账号下面有两个子项,F和V。项目V中保存的是账户的基本资料,用户名、所属组、描述、密码、注释、是否可以更改密码、账户启用、密码设置时间等。项目F中保存的是一些登录记录,比如上次登录时间、错误登录次数等。SAM靠这些齐全的备忘录来保存与用户账号相关的各种信息。

3.Domains\\Builtin存放着不同用户分组信息,SAM就是根据这个来划分NT中固有的6个不同的工作组的,它们分别是:管理员(Administrators)、备份操作员(Backup Operators)、客人(Guests)、高权限用户(Power Users)、修复员(Replicator)和普通用户(Users)。

幕后指挥官

在Windows系统中,虽然SAM如此尽力,但是他不听从你的指挥。它只听本地安全认证(Local Security Authority)程序——LSASS.EXE的差遣,就连进门时的审查也是LSASS的指示。如果你把LSASS杀了,你就等着被赶出门吧——当然,对于普通用户来说,如果你试图用普通的进程管理工具或者Windows系统的进程管理杀掉“LSASS.EXE”进程的话,只会得到“该进程为关键系统进程,任务管理器无法结束进程。”的提示,本地安全认证(Local Security Authority)在Windows系统中主要负责以下任务:1.重新找回本地组的SID和用户权限;2.创建用户的访问令牌;3.管理本地安装的服务所使用的服务账号;4. 存储和映射用户权限;5.管理审核的策略和设置;6.管理信任关系。

俗话说,“人无完人”。尽管SAM(萨姆)是这么尽心尽责,可是在这里,我们还是必须用那句话——“萨姆也是人”来形容它。由于一些设计上的失误,在WinNT/2000里,如果你忘记了密码,那么你要做的不是呼天喊地,只需要在非NT环境里把SAM驱逐出硬盘就可以了。但是在XP以后的Windows操作系统里,这个情况得以改善,如果你把萨姆大叔踢了,NT也躲着死活不肯出来了。

特别提醒:不要以为sam文件记录了密码信息你就可以删除该文件使得系统用户密码为空,虽然在早期的win2k时代你可以在dos环境下这样做以求达到置空密码的目的,在xp时代,这样可没有用哦。
[解决办法]
陈辉大哥的代码还有点小问题,就是不能复制C:\windows\system32\config\system文件,我修改了下面几个地方就可以了
1.RETRIEVAL_POINTERS_BUFFER 类型声明的
lngTmp As Long 改成 lngTmp(255) As byte

2.lngOutSize = 32 + (lngFileSize / lngClusterSize) * 16
If DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, bytInBuf(0), 8, _
objOutBuf, lngOutSize, lngBytes, ByVal 0&) Then
lngClCount = (lngFileSize + lngClusterSize - 1) \ lngClusterSize
改成
lngOutSize = 32 + (lngFileSize \ lngClusterSize) * 16
Dim bytOutBuf() As Byte: ReDim bytOutBuf(lngOutSize - 1)
If DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, bytInBuf(0), 8, _
bytOutBuf(0), lngOutSize, lngBytes, ByVal 0&) Then
CopyMemory objOutBuf, bytOutBuf(0), lngBytes
lngClCount = (lngFileSize + lngClusterSize - 1) \ lngClusterSize

不过还是很多谢陈辉大哥!以后还有很多地方要想你学习!

热点排行