30 12
发新话题
打印

[原创]阻止删除文件(文件占坑)+nevergone逆向代码一份

本主题由 System 于 2008-8-1 05:00 解除限时高亮

[原创]阻止删除文件(文件占坑)+nevergone逆向代码一份

信息来源:邪恶八进制信息安全团队(www.eviloctal.com

逆向作者:nevergone

作者:Written by 风泽(EvilHsu)[E.S.T] 真正的技术作者是DebugMan上《ring3文件占坑大法》的作者。



介绍:
dhfile是参考《ring3文件占坑大法》一文制造出的一款利用DuplicateHandle函数防止文件被删除、改名等操作的软件,同时也提供卸载、查找、搜索打开的文件句柄。当程序运行后,再使用这款工具将程序句柄复制到其他进程中,达到防删除目的,不影响正在运行程序的正常运行。至于这款软件想怎么去利用,就要看你们的想象力了。

注:
感谢《ring3文件占坑大法》的作者。

用法:
dhfile.exe [ /p | /f | /c | /l ] [PID] [FileName]

例子:
1. dhfile.exe /l 868
   搜索PID为868的进程打开的所有文件
2. dhfile.exe /f text.exe
   搜索打开text.exe句柄的进程
3. dhfile.exe /c 868 text.exe
   卸载进程ID为868中text.exe文件句柄
4. dhfile.exe /p 868 c:\text.exe
   将text.exe句柄复制到PID为868的进程中,达到防止删除text.exe文件的目的。

关键代码
复制内容到剪贴板
代码:
BOOL DupFile( LPCTSTR lpFileName , int pid )
{
    BOOL    bRedup;
    HANDLE  hFile,hProcess;
    HANDLE  hTargetHandle;
   
    EnablePrivilege(SE_DEBUG_NAME,TRUE);

    if(ProcessList(pid)) printf("Process Name: %s\n",szProcessName);

    hProcess = OpenProcess( PROCESS_DUP_HANDLE, FALSE, pid);

    if ( hProcess == NULL )
       {
           printf("PROCESS_DUP_HANDLE Error\n");     
           return FALSE;
       }

    hFile = CreateFile( lpFileName,
                      GENERIC_READ,
                      0,
                      NULL,
                      OPEN_ALWAYS,
                      FILE_ATTRIBUTE_NORMAL,
                      NULL);

    if ( hFile == INVALID_HANDLE_VALUE )
    {
        printf("CreateFile Error\n");
        CloseHandle( hProcess );
        return FALSE;
    }

    bRedup = DuplicateHandle( GetCurrentProcess(),
                              hFile,
                              hProcess,
                              &hTargetHandle,
                              0,
                              FALSE,
                              DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE);

    CloseHandle( hProcess );

    return bRedup;
}
dhfile.rar (2.94 KB) 程序如有BUG请提示,如果有空偶会修改滴!


以下是nevergone逆向代码,其中软件存在的BUG已经提示并做了修改。(特别感谢nevergone能给予指正)
复制内容到剪贴板
代码:
/********************************************************************
        filename:         e:\C++\VS2008\dhfile_MY\dhfile_MY\dhfile.cpp
        file path:        e:\C++\VS2008\dhfile_MY\dhfile_MY
        file base:        dhfile
        file ext:        cpp
        completed:        7.7 0:15
        author:                nevergone
               
        purpose:        practice for reverseing
                                original author : 风泽
*********************************************************************/

#include <windows.h>
#include <TlHelp32.h>
#include <tchar.h>
#include <cstdio>
#include "ntdll/ntdll.h"
#pragma comment(lib, "ntdll.lib")

#pragma warning(disable : 4996)

using namespace std;

#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

char g_szProcessName[MAX_PATH];
HANDLE g_hProcessHeap;

struct HANDLE_NAME
{
        HANDLE hFile;
        FILE_NAME_INFORMATION file_info;
};

//
// this function come from KILL_KIS8
//
PVOID GetSystemInformation(SYSTEM_INFORMATION_CLASS iSystemInformationClass)
{
        ULONG                ulSize = 0x8000;
        ULONG                ulRequired;
        LPVOID                pvBuffer;
        NTSTATUS        Status;

        do {
                pvBuffer = HeapAlloc(GetProcessHeap(), 0, ulSize);

                if (!pvBuffer)
                        return NULL;

                Status = NtQuerySystemInformation(iSystemInformationClass,
                                                                                        pvBuffer,
                                                                                        ulSize,
                                                                                        &ulRequired);

                if (Status == STATUS_INFO_LENGTH_MISMATCH)
                {
                        HeapFree(GetProcessHeap(), 0, pvBuffer);
                        ulSize *= 2;
                }
        } while(Status == STATUS_INFO_LENGTH_MISMATCH);

        if (NT_SUCCESS(Status))
                return pvBuffer;

        HeapFree(GetProcessHeap(), 0, pvBuffer);
        return NULL;
}

DWORD WINAPI GetFileNameThreadProc(LPVOID pvParam)
{
        IO_STATUS_BLOCK io_status;

        HANDLE hFile = *(LPHANDLE)pvParam;
        PVOID pvBuffer = (PVOID)((DWORD)pvParam + sizeof(HANDLE));

        NtQueryInformationFile(hFile,
                                                        &io_status,
                                                        pvBuffer,
                                                        528,
                                                        FileNameInformation);
        return 0;
}


INT GetFileNameByHandle(HANDLE hFile, LPSTR lpMultiByteStr)
{
        PVOID pvBuffer = HeapAlloc(g_hProcessHeap, HEAP_ZERO_MEMORY, 532);

        *((LPDWORD)pvBuffer) = (DWORD)hFile;

        HANDLE hThread = CreateThread(NULL,
                                                                        0,
                                                                        GetFileNameThreadProc,
                                                                        pvBuffer,
                                                                        0,
                                                                        NULL);

        //
        // 100 may be too short for some slow machine~
        //
        DWORD dwRet = WaitForSingleObject(hThread, 100);

        if (dwRet == WAIT_TIMEOUT)
                TerminateThread(hThread, 0);

        CloseHandle(hThread);

        PFILE_NAME_INFORMATION pFileNameInfo = (PFILE_NAME_INFORMATION)((DWORD)pvBuffer + sizeof(HANDLE));
       
        WideCharToMultiByte(CP_ACP,
                                                0,
                                                pFileNameInfo->FileName,
                                                pFileNameInfo->FileNameLength / 2,
                                                lpMultiByteStr,
                                                MAX_PATH,
                                                NULL,
                                                NULL);

        HeapFree(g_hProcessHeap, 0, pvBuffer);
        return 0;
}


UCHAR GetFileObjectTypeNumber()
{
        UCHAR uchar_ObjectTypeNumber = 0;

        HANDLE hFile = CreateFileA("NUL",
                                                                GENERIC_READ,
                                                                0,
                                                                NULL,
                                                                OPEN_EXISTING,
                                                                0,
                                                                0);

        if (hFile == INVALID_HANDLE_VALUE)
                return 0;
       
        LPVOID pvBuffer = GetSystemInformation(SystemHandleInformation);
        if (pvBuffer == NULL)
        {
                CloseHandle(hFile);
                return 0;
        }

        DWORD dwCount = ((PSYSTEM_HANDLE_INFORMATION_EX)pvBuffer)->NumberOfHandles;

        if (!dwCount)
        {
                HeapFree(g_hProcessHeap, 0, pvBuffer);
                CloseHandle(hFile);
                return 0;
        }

        PSYSTEM_HANDLE_INFORMATION pHandleInfo = ((PSYSTEM_HANDLE_INFORMATION_EX)pvBuffer)->Information;

        for (DWORD i = 0; i < dwCount; ++i)
        {
                if (pHandleInfo[i].Handle == (USHORT)hFile &&
                        pHandleInfo[i].ProcessId == GetCurrentProcessId())
                {
                        uchar_ObjectTypeNumber = pHandleInfo[i].ObjectTypeNumber;
                        HeapFree(g_hProcessHeap, 0, pvBuffer);
                        CloseHandle(hFile);
                        return uchar_ObjectTypeNumber;
                }
        }

        return 0;
}

BOOL EnableDebugPrivilge(LPCSTR lpName, BOOL fEnable)
{
        HANDLE                                hObject;
        LUID                                Luid;
        TOKEN_PRIVILEGES        NewStatus;

        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hObject))
                return FALSE;

        if (LookupPrivilegeValue(NULL, lpName, &Luid))
        {
                NewStatus.Privileges[0].Luid = Luid;
                NewStatus.PrivilegeCount = 1;
                NewStatus.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;

                AdjustTokenPrivileges(hObject, FALSE, &NewStatus, 0, 0, 0);
               
                CloseHandle(hObject);
                return TRUE;
        }
       
        return FALSE;
}

BOOL GetProcessNameById(DWORD dwProcessId)
{
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,
                                                                                                0);
        //
        // add by nevergone
        //
        if (hSnapshot == INVALID_HANDLE_VALUE)
        {
           printf("CreateToolhelp32Snapshot error\n");
           return 0;
        }
       
        PROCESSENTRY32 pe;
        PCHAR pProcessName = NULL;

        //
        // add by nevergone. Process32First may be failed if without setting the size
        //
        pe.dwSize = sizeof(pe);
       
        if (!Process32First(hSnapshot, &pe))
        {
                CloseHandle(hSnapshot);
                return FALSE;
        }

        do {
                pProcessName = strrchr(pe.szExeFile, '\\');

                if (pProcessName)
                        pProcessName++;
                else
                        pProcessName = pe.szExeFile;

                if (pe.th32ProcessID == dwProcessId)
                {
                        ZeroMemory(g_szProcessName, sizeof(g_szProcessName));
                        strncpy(g_szProcessName, pProcessName, lstrlen(pProcessName));

                        //
                        //add by nevergone
                        //
                        CloseHandle(hSnapshot);
                        return TRUE;
                }
        } while(Process32Next(hSnapshot, &pe));

        CloseHandle(hSnapshot);
        return FALSE;
}

BOOL ProtectFile(LPCSTR lpFileName, DWORD dwProcessId)
{
        HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);

        if (!hProcess)
        {
                printf("PROCESS_DUP_HANDLE Error\n");
                return FALSE;
        }

        HANDLE hFile = CreateFile(lpFileName,
                                                                GENERIC_READ,
                                                                0,
                                                                NULL,
                                                                /*OPEN_ALWAYS*/OPEN_EXISTING,                // OPEN_EXISTING may be better [nevergone]
                                                                FILE_ATTRIBUTE_NORMAL,
                                                                NULL
                                                                );

        if (hFile == INVALID_HANDLE_VALUE)
        {
                printf("CreateFile Error\n");
                CloseHandle(hFile);
                return FALSE;
        }

        BOOL fOk = DuplicateHandle(GetCurrentProcess(),
                                                                hFile,
                                                                hProcess,
                                                                NULL,
                                                                0,
                                                                FALSE,
                                                                DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);

        CloseHandle(hProcess);

        return fOk;
}

int Process(int iUnknown, char *pString1, char *pString2)
{
        UCHAR uchar_FileTypeNumber;
        PVOID pvoid_HandleInfo;
        DWORD dwHandleCount;
        PSYSTEM_HANDLE_INFORMATION pHandleInfo;
        HANDLE hProcess;
        HANDLE hTarget;
        PCHAR pszPath;
        DWORD dwCount = 0;
        CHAR szFilePath[MAX_PATH] = { 0 };
       
        g_hProcessHeap = GetProcessHeap();
        uchar_FileTypeNumber = GetFileObjectTypeNumber();
        pvoid_HandleInfo = GetSystemInformation(SystemHandleInformation);
       
        if (pvoid_HandleInfo == NULL)
                return 0;
       

        dwHandleCount = *(LPDWORD)pvoid_HandleInfo;
        pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)((DWORD)pvoid_HandleInfo + sizeof(HANDLE));

        if (!dwHandleCount)
        {
                HeapFree(g_hProcessHeap, 0, pvoid_HandleInfo);
                printf("Not found File %s \n", pString1);
                return 0;
        }

        for (DWORD i = 0; i < dwHandleCount; ++i)
        {
                if (pHandleInfo[i].ObjectTypeNumber != uchar_FileTypeNumber)
                        continue;

                if (iUnknown == pHandleInfo[i].ProcessId ||
                        _strnicmp(pString2, "/f", 2) == 0)
                {
                        // ToDo:
                        hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pHandleInfo[i].ProcessId);

                        if (hProcess == NULL)
                                continue;

                        BOOL fOk = DuplicateHandle(hProcess,
                                                                                (HANDLE)pHandleInfo[i].Handle,
                                                                                GetCurrentProcess(),
                                                                                &hTarget,
                                                                                0,
                                                                                FALSE,
                                                                                DUPLICATE_SAME_ACCESS);
                        if (!fOk)
                        {
                                CloseHandle(hProcess);
                                continue;
                        }
                       
                        //
                        // add by nevergone, this is important. if GetFileNameThreadProc failed to
                        // get the file path, then WideCharToMultiByte do nothing with
                        // lpMultiByteStr parameter[see Test Project for detail],
                        // but lpMultiBytePtr is set by the previous GetFileNameByHandle. so must zero szFilePath.
                        //
                        ZeroMemory(szFilePath, sizeof(szFilePath));

                        GetFileNameByHandle(hTarget, szFilePath);

                        pszPath = szFilePath;

                        if (pszPath = strrchr(szFilePath, '\\'))
                                pszPath++;
                        else
                                pszPath = szFilePath;

                        if (_strnicmp(pString2, "/l", 2) == 0)
                        {
                                ++dwCount;
                                printf("Handle: %d .... FileName: %s\n", pHandleInfo[i].Handle, szFilePath);
                                CloseHandle(hTarget);
                                CloseHandle(hProcess);
                                continue;
                        }

                        if (_strnicmp(pString1, pszPath, lstrlen(pString1)) == 0)
                        {
                                ++dwCount;
                                printf("Process:%d Handle: %d .... FileName: %s\n",  pHandleInfo[i].ProcessId, pHandleInfo[i].Handle, szFilePath);

                                if (_strnicmp(pString2, "/c", 2) == 0)
                                {
                                        BOOL fOk = DuplicateHandle(hProcess,
                                                                                                (HANDLE)pHandleInfo[i].Handle,
                                                                                                GetCurrentProcess(),
                                                                                                NULL,
                                                                                                0,
                                                                                                FALSE,
                                                                                                DUPLICATE_CLOSE_SOURCE);

                                        if (fOk)
                                                printf("Close Files Handle....Success\n");
                                        else
                                                printf("Close Files Handle....Failure\n");
                                }
                        }

                        CloseHandle(hTarget);
                        CloseHandle(hProcess);
                }
        }
       
        HeapFree(g_hProcessHeap, 0, pvoid_HandleInfo);

        if (dwCount == 0)
        {
                printf("Not found File: %s \n", pString1);
        }

        return 0;
}

int main(int argc, char *argv[])
{
        if (argc < 2 ||
                lstrcmpi(argv[1], "/?") == 0 ||
                lstrcmpi(argv[1], "-?") == 0 ||
                lstrcmpi(argv[1], "-h") == 0 ||
                lstrcmpi(argv[1], "/help") == 0 ||
                lstrcmpi(argv[1], "-help") == 0)
        {
                //ShowHelp(argv[0]);
                exit(0);
        }

        EnableDebugPrivilge("SeDebugPrivilege", TRUE);

        if (argc < 3)
        {
                printf("参数不正确!\n");
                //ShowHelp(argv[0]);
                exit(0);
        }

        if (lstrcmpi(argv[1], "/f") == 0)
        {
                Process(-1, argv[2], argv[1]);
                return 0;
        }
       
        //
        // if argv[3] is absolute path, operation will failed.
        // but i don't want to solve this problem.
        // 风泽 take responsibility for this bug,
        // HA HA HA....
        //
        if (lstrcmpi(argv[1], "/c") == 0)
        {
                int dwProcessId = atoi(argv[2]);
                if (dwProcessId > 0xFFFF ||
                        dwProcessId < 4)
                {
                        printf("参数不正确!\n");
                        //ShowHelp(argv[0]);
                        exit(0);
                }

                if (!GetProcessNameById(dwProcessId))
                {
                        printf("Not found process : %d\n\n", dwProcessId);
                        exit(0);
                }

                printf("Process Name: %s \n\n", g_szProcessName);

                Process(dwProcessId, argv[3], argv[1]);
                return 0;
        }

        if (lstrcmpi(argv[1], "/l") == 0)
        {
                int dwProcessId = atoi(argv[2]);

                if (dwProcessId > 0xFFFF ||
                        argc > 3)
                {
                        printf("参数不正确!\n");
                        //ShowHelp(argv[0]);
                        exit(0);
                }

                if (!GetProcessNameById(dwProcessId))
                {
                        printf("Not found process : %d\n\n", dwProcessId);
                        exit(0);
                }

                printf("process name: %s \n\n", g_szProcessName);

                Process(dwProcessId, NULL, argv[1]);
                return 0;
        }

        if (lstrcmpi(argv[1], "/p") == 0)
        {
                int dwProcessId = atoi(argv[2]);
                if (dwProcessId > 0xFFFF ||
                        argc < 3)
                {
                        printf("参数不正确!\n");
                        //ShowHelp(argv[0]);
                        exit(0);
                }

                if (!GetProcessNameById(dwProcessId))
                {
                        printf("Not found process : %d\n\n", dwProcessId);
                        exit(0);
                }

                printf("Process Name: %s \n\n", g_szProcessName);

                if (ProtectFile(argv[3], dwProcessId))
                {
                        printf("\n...Success!\n");
                }

                return 0;
        }
}
[ 本帖最后由 风泽 于 2008-7-7 13:11 编辑 ]

附件

dhfile_MY.rar (122.91 KB)

2008-7-7 12:56, 下载次数: 1122

nevergone提供的完整逆向

本帖最近评分记录
  • 认真的雪 威望 +10 这代码短小精悍哟...... 2008-4-5 10:29
  • l4bm0s 威望 +10 膜拜一下风泽大牛~~~ 2008-4-4 10:19
  • sudami 威望 +10 膜拜一下风泽大牛~~~ 2008-4-3 22:45

TOP

汗一个. yiyikingking牛估计要说 风泽大牛你偷代码了

代码很X很XXX,不错不错~~~~~

[ 本帖最后由 sudami 于 2008-4-3 22:48 编辑 ]
[WINDOWS内核疯狂爱好者]

TOP

这个也不算偷吧?说明技术作者是他撒。。我只是一个书写者。。。把一系列的功能实现了。。。
修正了他DuplicateHandle中的一个参数。。。不改会造成文件损坏,也许是他故意的哈?呵呵~~好技术大家学习。。。
DuplicateHandle这个函数也被用烂了。。只是yiyikingking大牛的思路比较独特。
整个软件的代码yiyikingking的代码只占10%。。。。

再次感谢yiyikingking大牛~包括那个俄罗斯的。。。哈哈

[ 本帖最后由 风泽 于 2008-4-4 08:15 编辑 ]

TOP

yiyikingking大牛的代码的确淫荡~~哈哈~
不然偶也不会把这个工具给完善起来。
各位具体了解一下工具的使用方法,看这个工具到底能用在哪些地方,产生其他效果。
有思路及时跟帖,好东西大家分享撒~~

TOP

好象原作者说过:一个程序开机启动,删除xxxxx软件的某个重要文件,然后生成同名的占坑,短时间内无敌!
忘了在哪儿看到的这句话^&
本帖最近评分记录
  • 风泽 威望 +10 感谢您参加论坛讨论并做出认真回复 ... 2008-4-5 23:52

TOP

引用:
原帖由 doking 于 2008-4-5 20:18 发表
好象原作者说过:一个程序开机启动,删除xxxxx软件的某个重要文件,然后生成同名的占坑,短时间内无敌!
忘了在哪儿看到的这句话^&
这样做目的在于什么?阻止XXXXX软件自我恢复那个重要文件?那就是破坏XXXXX软件的完整性了?
不错的思路!

TOP

虽然可以做到自己不能被菜鸟删除,但是有个问题,就是如果做成U盘病毒的话,例如已经打开U盘中了病毒,现在程序已经启动了,如果再把U盘关闭的话,再打开U盘,程序不能再运行第二次,此时U盘就无法被打开,其他盘也是同样的原理
本帖最近评分记录
  • 风泽 威望 +5 感谢您参加论坛讨论并做出认真回复 ... 2008-4-6 20:55
love hack

TOP

说下,在U盘病毒中加了双击U盘,能打开U盘的代码,第一次打开U盘是病毒先启动,然后病毒把U盘打开的,第二次再打开U盘,病毒程序将无法再运行第二次,U盘也就打不开了
love hack

TOP

引用:
原帖由 dayang1718 于 2008-4-6 16:17 发表
说下,在U盘病毒中加了双击U盘,能打开U盘的代码,第一次打开U盘是病毒先启动,然后病毒把U盘打开的,第二次再打开U盘,病毒程序将无法再运行第二次,U盘也就打不开了 ...
首先感谢您对这个问题的阐述,但不知道你有没有写代码测试过,当U盘拔出来后,你复制到别的进程的句柄就自动关闭了,所以不存在再次插上U盘打不开文件的问题.如果程序被复制,再次打开U盘无法成功...这个我没有测试,但从病毒的角度考虑的话病毒首先应该自己把自己的主体释放到系统目录中才是最安全的做法.

为什么给你的回复加威望?因为你这个问题引出了思路.
可以在本机上利用该功能防止U盘病毒感染本地磁盘,就是开机把建立的空autorun.inf复制到系统进程,防止病毒改写autorun.inf要防止U盘上病毒的运行还需要利用其他技术,比如在打开U盘之前把他里面存在的autorun.inf复制到任意进程,这样打开U盘的时候就不会运行病毒了,因为autorun.inf无法运行了.

[ 本帖最后由 风泽 于 2008-4-6 21:15 编辑 ]

TOP

首先感谢风泽对我的关照,呵呵!
我是拿U盘举例而已,不一定只是用autorun.inf感染U盘的,应该是感染所有的本地磁盘,这样本地磁盘如何用本程序自己再打开又是个问题。
另外在其他的地方转了个代码
PVOID buf = malloc(200000);
WCHAR path [MAX_PATH] ;
ZeroMemory(buf , 200000);

GetSystemDirectoryW(path , MAX_PATH);
wcscpy((wchar_t *)buf , L"\\\\?\\C:\\test");
CreateDirectoryW((wchar_t *)buf , 0);
ULONG i ;

for ( i = 0 ; i < 1023 ; i ++)
{
wcscat((wchar_t *)buf , L\\test);
CreateDirectoryW((wchar_t *)buf , 0);

}
wcscat((wchar_t *)buf , L\\test.exe);
wcscat(path , L"\\calc.exe");
CopyFileW(path , (wchar_t *)buf , FALSE);

return ;
本人很菜,看不明白C的,希望能有delphi的,呵呵
love hack

TOP

DuplicateHandle
可以用这个过卡吧8主防
阿尔卑斯与八宝糖还有冷苹果

TOP

引用:
原帖由 dayang1718 于 2008-4-8 10:03 发表
首先感谢风泽对我的关照,呵呵!
我是拿U盘举例而已,不一定只是用autorun.inf感染U盘的,应该是感染所有的本地磁盘,这样本地磁盘如何用本程序自己再打开又是个问题。
对于这个问题我上面已经说过了,你感染到U盘或者是其他盘的病毒只是一个母体,释放文件再运行释放的文件并把文件句柄复制,不是一个很清晰的思路?再开个进程监视,如果发现程序不在运行了就到目标进程把句柄释放掉后再开启程序撒~~

[ 本帖最后由 风泽 于 2008-4-9 11:31 编辑 ]

TOP

引用:
原帖由 洋洋洒洒 于 2008-4-8 10:18 发表
DuplicateHandle
可以用这个过卡吧8主防
等有空自己动手搞搞~~用咔吧8的用户现在应该不多,至于KIS7 把SSDT恢复一下世界就安静了~

TOP

现在修复SSDT的代码,貌似只有C的,如果有个delphi的,就好了,呵呵
love hack

TOP

引用:
原帖由 dayang1718 于 2008-4-8 21:07 发表
现在修复SSDT的代码,貌似只有C的,如果有个delphi的,就好了,呵呵
这里有一个例
用DDDK编写驱动,修改SSDT表HOOK NTDebugActiveProcess函数
http://forum.eviloctal.com/thread-31008-1-1.html
Delphiscn Blog
http://blog.csdn.net/delphiscn

TOP

引用:
原帖由 dayang1718 于 2008-4-8 10:03 发表
PVOID buf = malloc(200000);
WCHAR path [MAX_PATH] ;
ZeroMemory(buf , 200000);

GetSystemDirectoryW(path , MAX_PATH);
wcscpy((wchar_t *)buf , L"\\\\?\\C:\\test");
CreateDirectoryW((wchar_t *)buf , 0);
ULONG i ;

for ( i = 0 ; i < 1023 ; i ++)
{
wcscat((wchar_t *)buf , L\\test);
CreateDirectoryW((wchar_t *)buf , 0);

}
wcscat((wchar_t *)buf , L\\test.exe);
wcscat(path , L"\\calc.exe");
CopyFileW(path , (wchar_t *)buf , FALSE);

return ;
才发现这个代码很淫荡的说~~没那么简单,MJ0011的确YD啊,哈哈~~有空测试一下。。。。。

[ 本帖最后由 风泽 于 2008-4-9 11:34 编辑 ]

TOP

MJ的代码just kidding...
DuplicateHandle其实只要XX了XX的handle table,NtDuplicateObject上过滤强悍点,也不是没可能喀嚓.至于其他的,只能说kblab的人都很懒很爱面子...


===========
我咋成未验证会员了呢?

[ 本帖最后由 evilsir 于 2008-4-10 13:03 编辑 ]

TOP

没有东西是绝对滴~~只要挂了NtDuplicateObject这个就完蛋了撒~
这个程序里面本来就提供喀嚓的功能,呵呵~~
咔吧LAB。。。不了解,没什么好评论的~

TOP

请教下,以dhfile.exe /p 868 c:\text.exe为例子,是如何实现取消的。要代码的,呵呵。。
love hack

TOP

实现卸载占坑文件的代码能否发下,呵呵
love hack

TOP

楼上的,你可以参考如下文章。
引用:
在Ring3上实现文件碎甲(解锁)功能

作者:cbns888
一.概述:
如果一个病毒文件被植入正在运行的进程中,我们想要清除它时系统总会提供无法删除;有时编辑文件的进程被意外中止而文件句柄没有正确释放,导致此文件无法进行改写操作。现在我们会使用Unlocker之类的小工具去解锁,但在编写程序的可能会需要把这些功能包含在自己的代码中,本文就是自己写代码实现”如何关闭已经被加载的DLL或是正在使用的文件”功能,使用文章中的方法能很方便的完成文件解锁功能。
按最初的想法准备在ring0中完成这些功能,但在查找资料的过程中发现既然我们能在ring3中做,为什么不让这些方法更通用一些呢。其实功能实现并不难,主要是前期从哪里入手比较麻烦。
我们知道无论是动态库或是文件在加载到进程中时,总会有一个指向它的指针,如果让进程释放这段指针,那么这些文件就不会被系统锁定。下面将是我们的需要实现文件解锁功能而分解出的步骤
1.    枚举当前系统所有进程;
2.    查找进程中打开的文件句柄和加载的动态库句柄;
3.    通知进程关闭这些句柄。
二.详细设计
2.1查找进程加模的动态库模块
Let’s go,我们来分步完成它吧。对于枚举当前系统所有进程,在这里就不给出代码了,相信实现的方法很多。下面的代码段完成查找指定进程加载动库信息的功能(在这里使用了Jeffrey在《Windows核心编程》一书中提供的CToolhelp类,用它可以完成进程加载信息的分析功能,感谢Jeffrey,我一直在使用它)

// 自定义结构,保存打开句柄的的信息
typedef struct _UNFILE_INFO    {
    int nFileType;
    DWORD dwHandle;
    char *strFileName;
} UNFILE_INFO, *PUNFILE_INFO;
//////////////////////////////////////////////////////////////////////////
// 通过PID号取得PID打开的文件句柄信息
//////////////////////////////////////////////////////////////////////////
void
GetModules(DWORD dwProcessID, CList<PUNFILE_INFO, PUNFILE_INFO> &plsUnFileInfo)
{
    CToolhelp::EnableDebugPrivilege(TRUE);
    CToolhelp th(TH32CS_SNAPALL, dwProcessID);
    // 显示进程的详细资料
    MODULEENTRY32 me = { sizeof(me) };
    BOOL fOk = th.ModuleFirst(&me);
    for (; fOk; fOk = th.ModuleNext(&me))
    {
        PVOID pvPreferredBaseAddr = NULL;
        pvPreferredBaseAddr =GetModulePreferredBaseAddr(dwProcessID, me.modBaseAddr);
        // 取得进程模块信息
        PUNFILE_INFO pUnFileInfo = new UNFILE_INFO;
        // 模块地址
        pUnFileInfo->dwHandle = (DWORD)me.modBaseAddr;
        // 模块类型
        pUnFileInfo->nFileType = UNTYPE_DLL;
        // 模块名称
        pUnFileInfo->strFileName = new char[strlen(me.szExePath)+1];
        memset( pUnFileInfo->strFileName, 0, strlen(me.szExePath)+1);
        strcpy( pUnFileInfo->strFileName, me.szExePath);
        // 保存打开的模块信息
        plsUnFileInfo.AddTail( pUnFileInfo);
    }
}

上面功能完成了枚举进程加载的模块功能,我们把得到的枚举信息加入了链表中,以备后面使用。
2.2枚举进程打开的文件信息
下面将分段说明如何枚举指定进程打开的文件句柄。在这里我们需要使用两个DDK中提供的函数:
NTSTATUS
ZwQuerySystemInformation(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
    OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength,
    OUT PULONG ReturnLength OPTIONAL
);
NTSTATUS
  ZwQueryInformationFile(
    IN HANDLE  FileHandle,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    OUT PVOID  FileInformation,
    IN ULONG  Length,
    IN FILE_INFORMATION_CLASS  FileInformationClass
);
ZwQuerySystemInformation是个未公开函数,通过它的SYSTEM_INFORMATION_CLASS结构,我们能完成许多进程和线程的操作,下面是它的部分内容,在这时我们使用它的SystemHandleInformation(0x10),来完成文件句柄的操作。
typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation,                 // 0
    SystemProcessorInformation,             // 1
    SystemPerformanceInformation,             // 2

    SystemHandleInformation,                 // 16

    SystemSessionProcessesInformation        // 53
} SYSTEM_INFORMATION_CLASS;
ZwQueryInformationFile可以根据参数FileInformationClass的不同值来返回不同的类型,在这里我们使用FileInformationClass=FileInformationClass来得到FILE_NAME_INFORMATION,从而得到文件句柄指向的文件名,下面是它的结构定义。
typedef struct _FILE_NAME_INFORMATION {
  ULONG  FileNameLength;
  WCHAR  FileName[1];
} FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION;

因为需要在Ring3上使用DDK提供的函数,我们需要导出这些两个函数,下面是导出函数的示例代码:
{
    g_hNtDLL = LoadLibrary( "ntdll.dll" );
    if ( !g_hNtDLL )
    {
        return FALSE;
    }

    ZwQuerySystemInformation =
    (ZWQUERYSYSTEMINFORMATION)GetProcAddress( g_hNtDLL, "ZwQuerySystemInformation");
    if( ZwQuerySystemInformation == NULL)
    {
        return FALSE;
    }

    ZwQueryInformationFile =
    (ZWQUERYINFORMATIONFILE)GetProcAddress( g_hNtDLL, "ZwQueryInformationFile");
    if( ZwQueryInformationFile == NULL)
    {
        return FALSE;
    }
}
我们先来使用ZwQuerySystemInformation函数枚举系统中打开的所有文件的句柄,枚举出的信息将包含如下结构:
typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG  ProcessId;
    UCHAR  ObjectTypeNumber;
    UCHAR  Flags;
    USHORT  Handle;
    PVOID  Object;
    ACCESS_MASK  GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
ObjectTypeNumber定义了句柄所属对像的类型,文件的ObjectType对不同的操作系统是不同的,所以需要先找到当前操作系统所定义的ObjectType值,这样才能在枚举出的众多句柄信息中找到哪些是文件句柄信息。通用的方法是我们CreateFile打开空设备NUL,记下它的句柄,用来比较。
UCHAR GetFileHandleType()
{
  HANDLE                     hFile;
  PSYSTEM_HANDLE_INFORMATION Info;
  ULONG                      r;
  UCHAR                      Result = 0;

  hFile = CreateFile("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);

  if (hFile != INVALID_HANDLE_VALUE)
  {
    Info = GetInfoTable(SystemHandleInformation);

    if (Info)
    {
      for (r = 0; r < Info->uCount; r++)
      {
        if (Info->aSH[r].Handle == (USHORT)hFile &&
                                    Info->aSH[r].uIdProcess == GetCurrentProcessId())
        {
          Result = Info->aSH[r].ObjectType;
          break;
        }
      }
      HeapFree(hHeap, 0, Info);
    }
    CloseHandle(hFile);
  }
  return Result;
}
现在知道了句柄的类型就可以枚举系统中打开的文件了。首先用句柄获取打开的文件名:
typedef struct _NM_INFO
{
  HANDLE  hFile;
  FILE_NAME_INFORMATION Info;
  WCHAR Name[MAX_PATH];
} NM_INFO, *PNM_INFO;

// 因为在在线程中取得文件名
DWORD WINAPI
  GetFileNameThread(PVOID lpParameter)

{
  PNM_INFO        NmInfo = lpParameter;
  IO_STATUS_BLOCK IoStatus;
  int r;

  NtQueryInformationFile(NmInfo->hFile, &IoStatus, &NmInfo->Info,
                       sizeof(NM_INFO) - sizeof(HANDLE), FileNameInformation);

  return 0;
}

void CFileProcess::GetFileName(HANDLE hFile, PCHAR TheName)
{

    HANDLE   hThread;
    PNM_INFO Info = new NM_INFO;
    char namebuf[2000] = {0};
    Info->Info = (PFILE_NAME_INFORMATION)namebuf;

    Info->hFile = hFile;
    Info->nRet = 0x00;
   
    // 在对打开的句柄调用ZwQueryInformationFile时,调用线程会等待PIPE中的消息
    // 如果PIPE中没有消息时,线程可能会永久挂起,所以使用一个等待超时来打开句柄
    hThread = CreateThread(NULL, 0, GetFileNameThread, Info, 0, NULL);
    if (WaitForSingleObject(hThread, 100) == WAIT_TIMEOUT)
        TerminateThread(hThread, 0);
    CloseHandle(hThread);
    // 调用句柄失败
    if( Info->nRet == 0x00)
    {
        delete Info;
        return ;
    }
   
    // 加上盘符
    wchar_t volume = GetVolumeName(hFile);
    if (volume != L'!')
    {
        wchar_t outstr[1000] = L"A:";
        outstr[0] = volume;
        memcpy(&outstr[2], Info->Info->FileName, Info->Info->FileNameLength);
        outstr[2+Info->Info->FileNameLength] = 0;
        WideCharToMultiByte(CP_ACP, 0, outstr, 2+Info->Info->FileNameLength, TheName, MAX_PATH, NULL, NULL);
    }
    delete Info;
    return ;
}

下面代码片段用来枚举打开的文件:
{
    // 取得操作系统文件句柄定义类型
    UCHAR ObFileType = GetFileHandleType();
    // 取得系统中打开的文件句柄列表
    PULONG buf = GetHandleList();
    if (buf == NULL)
        return ;
    Info = (PSYSTEM_HANDLE_INFORMATION)&buf[1];
    if (Info)
    {
        for (r = 0; r < buf[0]; r++, Info++)
        {
            if (Info->ObjectTypeNumber == ObFileType && Info->ProcessId == dwProcessID)
            {
                hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, Info->ProcessId);

                if (hProcess)
                {
                    // 复制句柄到当前进程中,这样方便对当前进程句柄取出文件名
                    // 因为共享一个FileObject,这两个文件句柄对像将由两个进程共享
                    if ( DuplicateHandle( hProcess, (HANDLE)Info->Handle,
                    GetCurrentProcess(), &hFile, 0, FALSE, DUPLICATE_SAME_ACCESS))
                    {
                        GetFileName(hFile, Name);
                        // 取得文件信息到链表中
                        if( strlen( Name)>0)
                        {
                            AfxTrace("PID=%d FileHandle %d FileName=%s", Info->ProcessId, Info->Handle, Name);
                            // 在这里加入你要保存的文件句柄信息
                        }

                        CloseHandle(hFile);
                    }
                    CloseHandle(hProcess);
                }
            }
        }
    }
}
2.3使用远线程方法关闭进程加载的模块和打开的文件
通过枚举进程加载的模块信息和打开的文件信息,我们已经得到系统中加载的DLL和文件名信息,以下是我们在链表中保存的信息:
{
DWORD    ProcessID    // 进程PID
BYTE    nHandleType    // 句柄类型是文件还是加载的DLL
Char strFileName[MAX_PATH]    // 文件名
}
如果我们需要关闭正在打开的文件,只需要在这个链表中以文件名进行查找,即得到打开文件的进程PID。怎么才能通知别的进程关闭相应的句柄呢,我们通过跨进程去关闭句柄是很困难的,不如直接注入代码到需要的进程中,然后直接关闭句柄就行了。
需要再遍写一个DLL用来注入到进程中通知进程关闭文件句柄。这个DLL不需要做别的处理,只需要在加载的地方根据不同的句柄类型使用不同的方法进行关闭即可。下面是注入到进程的DLL执行的关闭句柄函数:
Void CloseHandel( PVOID pHandle, BYTE nHandleType)
{
    If(HandleType = HANDLE_FILE)
FreeLibrary((HMODULE)pHandle);
    else
        CloseHandle((HANDLE)pHandle);
}
在DllMain中调用关闭句柄的函数:
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    // Remove this if you use lpReserved
    UNREFERENCED_PARAMETER(lpReserved);

    if (dwReason == DLL_PROCESS_ATTACH)
    {
        DWORD nHandle=0;
        BYTE nType=0;
        TRACE0("MOPER.DLL Initializing!\n");
        AfxMessageBox("MOPER.DLL Initializing!");
        // 从碎甲程序所生成的文件句柄映射文件中取出要关闭的句柄信息
        // 方法很多我在这里直接用共享文件实现的,就不写出代码了
        GetHandle( nHandle, nType)
        // 关闭句柄            
        CloseHandel((PVOID)nHandle, nType);
...
    }
...
}
下面示例取出通过文件句柄链表中的PID,使用远程注入的方法向进程注入关闭句柄的DLL
{
    HANDLE hRemoteProcess = OpenProcess(PROCESS_CREATE_THREAD | //允许远程创建线程
            PROCESS_VM_OPERATION | //允许远程VM操作
            PROCESS_VM_WRITE,//允许远程VM写
            FALSE, dwProcessId);
    if( hRemoteProcess == NULL)
        return FALSE;

    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
    int nLen = (strlen( pszLibFile)+1)*sizeof(char);
    char * pszLibFileRemote = (char *) VirtualAllocEx( hRemoteProcess, NULL, nLen, MEM_COMMIT, PAGE_READWRITE);
    if( pszLibFileRemote != NULL &&
        pfnStartAddr !=NULL)
    {
        if( WriteProcessMemory(hRemoteProcess, pszLibFileRemote, (PVOID) pszLibFile, nLen, NULL))
        {
            HANDLE hThread = CreateRemoteThread( hRemoteProcess, NULL, 0, pfnStartAddr, pszLibFileRemote, 0, NULL);
            if( !hThread)
            {
                WaitForSingleObject(hThread, INFINITE);
                bRet = TRUE;
                CloseHandle(hThread);
            }
        }
        VirtualFreeEx(hRemoteProcess, pszLibFileRemote, 0, MEM_RELEASE);
    }
    CloseHandle( hRemoteProcess);
}
三.备注
对查找文件句柄的方法,参考了鄙人拙译(http://greatdong.blog.edu.cn)的“如何操作被占用文件”在此表示感谢。
使用了Jeffrey在《Windows核心编程》一书中提供的CToolhelp类,用它可以完成进程加载信息的分析功能,感谢Jeffrey。

TOP

风老大,我刚开始接触DELPHI,对C的很是头疼,呵呵,能否提炼出实现卸载占坑文件的代码,呵呵,照顾下小菜!
love hack

TOP

回复 22楼 dayang1718 的帖子

不好意思,偶没学过DELPHI,看看还可以写的话就不会了。
如果你刚开始学的话我建议你学C

TOP

晕,你提取段能删除的C的代码就行,呵呵,没让老大你写delphi的呀,呵呵
love hack

TOP

回复 24楼 dayang1718 的帖子

看附件体积这么小...可想而知里面的东东跟直接看代码一样...
阿尔卑斯与八宝糖还有冷苹果

TOP

 30 12
发新话题