首页 | IT新闻 | 硬件 | 操作系统 | 开发 | 网络编程 | 数据库 | 热门框架 | 网络安全 | 组网 | 建站指南 | 网页制作 | 特效 | 实用技巧 | 服务器 | 办公 | QQ | 探索 | 社区

  • 技术部落
  • 部落首页 > 程序开发 > VB > 正文
  • VB编写的Viking(维金)病毒专杀工具
      2008-5-9  来源:魏滔序原创  编辑:Jsbulo  热度:

      Viking的肆虐让很多受害者忍无可忍,更可气的是专业软件公司提供的专杀工具竟然无法彻底清除。

      无奈之余自己动手写了一个,请需要的朋友到这里下载:http://www.chenoe.com

      该工具可以有效解除被感染的exe中的病毒并还原exe文件,网上的大部分工具是直接删除exe文件。另外,本工具还具有Viking免疫功能。

      下载后直接运行即可查杀,如果查杀几次都有无法关闭的进程的,重新启动一下计算机继续查杀应该可以杀掉。直到病毒数为0时为止。

      另外提供该工具中结束进程部分的代码,结束进程一般采用TerminateProcess函数,但是对于比较顽固的进程就要用非常规的手段来Kill了。

      我的方法是,先提高本程序为Debug级别的权限。再用TerminateProcess关闭,如果失败就枚举该进程中的线程并用TerminateThread关闭。然后再用TerminateProcess结束进程。这样就基本上可以关闭99%的非系统进程了。

      还有,对于被注入了病毒dll的进程,要先枚举进程中的模块并判断。然后决定是否Kill,Kill方法同上。

      以下为进程、线程、模块相关的代码:

    Private Declare Function CreateToolhelp32Snapshot Lib "kernel32" (ByVal lFlags As Long, ByVal lProcessID As Long) As Long
    Private Declare Function Process32First Lib "kernel32" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
    Private Declare Function Process32Next Lib "kernel32" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
    Private Declare Function Thread32First Lib "KERNEL32.dll" (ByVal hSnapshot As Long, ByRef lpte As THREADENTRY32) As Long
    Private Declare Function Thread32Next Lib "KERNEL32.dll" (ByVal hSnapshot As Long, ByRef lpte As THREADENTRY32) As Long
    Private Declare Function Module32First Lib "KERNEL32.dll" (ByVal hSnapshot As Long, ByRef lppe As MODULEENTRY32) As Long
    Private Declare Function Module32Next Lib "KERNEL32.dll" (ByVal hSnapshot As Long, ByRef lpme As MODULEENTRY32) As Long
    Private Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
    Private Declare Function TerminateThread Lib "kernel32" (ByVal hThread As Long, ByVal dwExitCode As Long) As Long
    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Function OpenThread Lib "KERNEL32.dll" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwThreadId As Long) As Long
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

    Private Const TH32CS_SNAPPROCESS = &H2
    Private Const TH32CS_SNAPTHREAD = &H4
    Private Const TH32CS_SNAPMODULE As Long = &H8

    Private Const PROCESS_TERMINATE As Long = (&H1)
    Private Const MAX_PATH As Integer = 260

    Private Type PROCESSENTRY32
        dwsize As Long
        cntusage As Long
        th32ProcessID As Long
        th32DefaultHeapID As Long
        th32ModuleID As Long
        cntThreads As Long
        th32ParentProcessID As Long
        pcPriClassBase As Long
        dwFlags As Long
        szExeFile As String * MAX_PATH
    End Type

    Private Type MODULEENTRY32                                          ’模块
        dwsize   As Long
        th32ModuleID   As Long
        th32ProcessID   As Long
        GlblcntUsage   As Long
        ProccntUsage   As Long
        modBaseAddr   As Byte
        modBaseSize   As Long
        hModule   As Long
        szModule   As String * 256
        szExePath   As String * 1024
    End Type

    Private Type THREADENTRY32                                          ’线程
        dwsize   As Long
        cntusage   As Long
        th32threadID   As Long
        th32OwnerProcessID   As Long
        tpBasePri   As Long
        tpDeltaPri   As Long
        dwFlags   As Long
    End Type

    Public Function KillThread(ByVal ProcessID As Long) As Boolean
        Dim hThread As Long, r As Long, i As Long
        Dim TList() As THREADENTRY32

        TList = GetThreadList(ProcessID)

        For i = 0 To UBound(TList)
            With TList(i)
                hThread = OpenThread(PROCESS_TERMINATE, False, .th32threadID)    ’获取进程句柄
                If hThread <> 0 Then
                    r = TerminateThread(hThread, 0)            ’关闭进程
                End If
            End With
        Next
        KillThread = r <> 0
    End Function


    Public Function KillProcess(ByVal ProcessName As String, Optional ByVal bKillThread As Boolean) As Boolean
        Dim hProcess As Long, r As Long
        Dim PList() As PROCESSENTRY32
        Dim Name As String, i As Long

        PList = GetProcessList

        For i = 0 To UBound(PList)
            With PList(i)
                Name = Left(.szExeFile, InStr(1, .szExeFile, vbNullChar) - 1)
                DoEvents
                Form1.lbState.Caption = "正在内存查毒: " & Name
                r = InModule(.th32ProcessID, ProcessName)

                If LCase(Trim(Name)) = LCase(Trim(ProcessName)) Or r Then
                    hProcess = OpenProcess(PROCESS_TERMINATE, False, .th32ProcessID)    ’获取进程句柄
                    If hProcess <> 0 Then
                        r = TerminateProcess(hProcess, 0)      ’关闭进程
                        If r Then
                            AddLog Name, "已结束进程"
                        Else
                            If bKillThread Then
                                If KillThread(.th32ProcessID) Then
                                    AddLog Name, "已结束线程"
                                Else
                                    AddLog Name, "线程结束失败"
                                End If
                            End If
                            r = TerminateProcess(hProcess, 0)  ’关闭进程
                            If r Then
                                AddLog Name, "已结束进程"
                            Else
                                AddLog Name, "进程结束失败"
                            End If
                        End If
                    Else
                        AddLog Name, "无法获得进程句柄"
                    End If
                End If

            End With
        Next
    End Function

    Private Function GetThreadList(ByVal ProcessID As Long) As THREADENTRY32()
        Dim i As Long
        Dim TList() As THREADENTRY32
        Dim TE32 As THREADENTRY32
        Dim hThreadSnap As Long
        Dim TheLoop As Long

        hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, ProcessID)
        TE32.dwsize = Len(TE32)

        TheLoop = Thread32First(hThreadSnap, TE32)
        While TheLoop <> 0

            If TE32.th32OwnerProcessID = ProcessID Then
                ReDim Preserve TList(i)
                TerminateThread TE32.th32threadID, 0
                TList(i) = TE32
                i = i + 1
            End If

            TheLoop = Thread32Next(hThreadSnap, TE32)
        Wend

        CloseHandle hThreadSnap
        GetThreadList = TList
    End Function

    Private Function GetProcessList() As PROCESSENTRY32()
        Dim i As Long
        Dim PList() As PROCESSENTRY32
        Dim PE32 As PROCESSENTRY32
        Dim hProcessSnap As Long
        Dim TheLoop As Long

        hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
        PE32.dwsize = Len(PE32)

        TheLoop = Process32First(hProcessSnap, PE32)
        While TheLoop <> 0
            ReDim Preserve PList(i)
            PList(i) = PE32
            i = i + 1
            TheLoop = Process32Next(hProcessSnap, PE32)
        Wend

        CloseHandle hProcessSnap
        GetProcessList = PList
    End Function

    Private Function GetModuleList(ByVal ProcessID As Long) As MODULEENTRY32()
        Dim i As Long
        Dim MList() As MODULEENTRY32
        Dim ME32 As MODULEENTRY32
        Dim hModuleSnap As Long
        Dim TheLoop As Long

        hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessID)
        ME32.dwsize = Len(ME32)

        TheLoop = Module32First(hModuleSnap, ME32)
        While TheLoop <> 0
            ReDim Preserve MList(i)
            MList(i) = ME32
            i = i + 1
            TheLoop = Module32Next(hModuleSnap, ME32)
        Wend

        CloseHandle hModuleSnap
        GetModuleList = MList
    End Function

    Private Function InModule(ByVal ProcessID As Long, ByVal ModuleName As String) As Boolean
        Dim i As Long
        Dim MList() As MODULEENTRY32
        Dim Name As String
       
        On Error GoTo Err:

        MList = GetModuleList(ProcessID)

        For i = 0 To UBound(MList)
            With MList(i)
                Name = Left(.szModule, InStr(1, .szModule, vbNullChar) - 1)
                If LCase(Name) = LCase(ModuleName) Then
                    InModule = True
                    Exit For
                End If
            End With
        Next
    Err:
    End Function

      ’这个是显示的杀毒记录

    Sub AddLog(txt1 As String, txt2 As String)
        Dim Item As ListItem
        Set Item = Form1.lv.ListItems.Add(, , txt1)
        Item.SubItems(1) = txt2
    End Sub

      以下为设置本程序权限级别的代码,在程序加载前调用EnableDebugPrivilege即可:

    Private Type LARGE_INTEGER
        lowpart As Long
        highpart As Long
    End Type

    Private Const ANYSIZE_ARRAY As Long = 1
    Private Const SE_PRIVILEGE_ENABLED As Long = &H2
    Private Const TOKEN_ADJUST_PRIVILEGES As Long = &H20
    Private Const TOKEN_QUERY As Long = &H8

    Private Type LUID_AND_ATTRIBUTES
        LUID As LARGE_INTEGER
        Attributes As Long
    End Type

    Private Type TOKEN_PRIVILEGES
        PrivilegeCount As Long
        Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
    End Type

    Private Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LARGE_INTEGER) As Long
    Private Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As Long, ByVal DisableAllPrivileges As Long, ByRef NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long, ByRef PreviousState As Long, ByRef ReturnLength As Long) As Long
    Private Declare Function GetCurrentProcess Lib "KERNEL32.dll" () As Long
    Private Declare Function GetCurrentProcessId Lib "KERNEL32.dll" () As Long

    Private Declare Function CloseHandle Lib "KERNEL32.dll" (ByVal hObject As Long) As Long
    Private Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
    Private Declare Function GetLastError Lib "KERNEL32.dll" () As Long


    Function EnableDebugPrivilege() As Boolean
        Dim TP As TOKEN_PRIVILEGES
        Dim hToken As Long, r As Long, e As Long

        r = OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken)
        e = GetLastError
    ’    Err.Raise 6
        If r And Not e Then
            r = LookupPrivilegeValue(vbNullString, "SeDebugPrivilege", TP.Privileges(0).LUID)
            e = GetLastError

            If r And Not e Then
                TP.PrivilegeCount = 1
                TP.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED

                r = AdjustTokenPrivileges(hToken, False, TP, LenB(TP), 0, 0)
                EnableDebugPrivilege = GetLastError = 0
            End If
        End If
        Call CloseHandle(hToken)
    End Function

      下面贴出本工具中用到的关闭本地计算机共享目录的代码(与其相对应的创建共享的代码也整理出来一同贴上),实际上用这个代码还可以关闭网络中其他计算机的共享目录,但要保证有足够的权限(至少可以通过网上邻居正常访问到对方计算机)。创建或删除本机的共享目录,用127.0.0.1就可以了。

      代码如下:

    Option Explicit
    ’共享类型
    Private Const STYPE_ALL       As Long = -1
    Private Const STYPE_DISKTREE  As Long = 0
    Private Const STYPE_PRINTQ    As Long = 1
    Private Const STYPE_DEVICE    As Long = 2
    Private Const STYPE_IPC       As Long = 3
    Private Const STYPE_SPECIAL   As Long = &H80000000
    ’共享权限
    Private Const ACCESS_READ     As Long = &H1
    Private Const ACCESS_WRITE    As Long = &H2
    Private Const ACCESS_CREATE   As Long = &H4
    Private Const ACCESS_EXEC     As Long = &H8
    Private Const ACCESS_DELETE   As Long = &H10
    Private Const ACCESS_ATRIB    As Long = &H20
    Private Const ACCESS_PERM     As Long = &H40
    Private Const ACCESS_ALL      As Long = ACCESS_READ Or ACCESS_WRITE Or ACCESS_CREATE Or ACCESS_EXEC Or ACCESS_DELETE Or ACCESS_ATRIB Or ACCESS_PERM
    ’共享信息
    Private Type SHARE_INFO_2
        shi2_netname       As Long                             ’共享名
        shi2_type          As Long                             ’类型
        shi2_remark        As Long                             ’备注
        shi2_permissions   As Long                             ’权限
        shi2_max_uses      As Long                             ’最大用户
        shi2_current_uses  As Long                             ’
        shi2_path          As Long                             ’路径
        shi2_passwd        As Long                             ’密码
    End Type

    Private Declare Function NetShareAdd Lib "netapi32.dll" (ByVal ServerName As Long, ByVal level As Long, buf As Any, Parmerr As Long) As Long
    Private Declare Function NetShareDel Lib "netapi32.dll" (ByVal ServerName As Long, ByVal ShareName As Long, ByVal dword As Long) As Long

    ’设置共享(返回0 为成功)
    Public Function CreateShare(ByVal ServerName As String, ByVal SharePath As String, ByVal ShareName As String, Optional ByVal Password As String, Optional ByVal Remark As String) As Long
        Dim pRemark As Long
        Dim pPassword As Long
        Dim SHI2 As SHARE_INFO_2
      
        If Len(Remark) > 0 Then pRemark = StrPtr(Remark) ’备注
        If Len(Password) > 0 Then pPassword = StrPtr(Password) ’密码

        ’初始化共享信息
        With SHI2
            .shi2_netname = StrPtr(ShareName)
            .shi2_path = StrPtr(SharePath)
            .shi2_remark = pRemark
            .shi2_type = STYPE_DISKTREE
            .shi2_permissions = ACCESS_ALL
            .shi2_max_uses = -1
            .shi2_passwd = pPassword
        End With

        ’设置共享(用户名,共享类型,共享信息,)
        CreateShare = NetShareAdd(StrPtr(ServerName), 2, SHI2, 0)
    End Function

    ’删除共享(返回0 表示成功)
    Public Function DeleteShare(ByVal ServerName As String, ByVal ShareName As String) As Long
        DeleteShare = NetShareDel(StrPtr(ServerName), StrPtr(ShareName), 0)
    End Function

      最后声明一下:不得请将本代码用到任何能够给别人造成任何损失的场合。