• 逆向对抗技术之ring3解除文件句柄,删除文件


    一丶简介

    这些问题主要是工作中会遇到.包括后面的逆向对抗技术.有的可能只会提供思路.并且做相应的解决与对抗.

    二丶实战 + 环境模拟

    1.环境模拟.

    假设现在有一个进程.打开了你的文件.而你现在无法关系.

    其中一个原因就是句柄被占用了. 因为句柄占用的原因你无法删除.

    这里遇到了句柄占用.所以采用解除句柄的方法.

    无法删除例子如下.

    2.删除原理

    我自己闪现了一个解除文件句柄并删除文件的方法. 需要使用未公开的API

    原理很简单.主要是使用 ZwQueryObject的 2号功能获取句柄类型. 使用1号功能获取句柄对象文件名. 使用DuplicateHandle 传入DUPLICATE_CLOSE_SOURCE宏在拷贝的时候关闭其句柄占用.

    步骤:

    1.随便打开一个文件.获取其文件句柄在操作系统的中类型
    2.打开进程.使用查询句柄个数(这步可以略过,不查询)
    3.循环拷贝进程句柄,拷贝成功的使用 ZwQueryObject的2号功能遍历出文件名
    4.解析文件名是否跟你要解除的文件名一样.
    4.1 如果一样.则调用DuplicateHandle. 传入DUPLICATE_CLOSE_SOURCE

    3.代码实现

    1.查询文件句柄类型

    setp 1. 随便打开一个文件根据文件句柄查询文件类型号.

    
     DWORD dwSystemFileHandleType = 0;
        TCHAR szPath[MAX_PATH] = { 0 };
        GetModuleFileName(GetModuleHandle(NULL), szPath, MAX_PATH * sizeof(TCHAR));
        HANDLE hFile = CreateFile(szPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
        if (INVALID_HANDLE_VALUE == hFile)
            return 0;
        dwSystemFileHandleType = NatHndGetHandleTypeWithHandle(hFile);
    

    NatHndGetHandleTypeWithHandle 内部实现.
    因为自己封装在项目工程中.所以直接拿出来了.想要自己用自己需要改改.

    这个函数主要作用就是用 ZwQueryObject的2号功能.遍历出文件类型号.

    USHORT CNativeApiManger::NatHndGetHandleTypeWithHandle(HANDLE handle)
    {
    
        if (INVALID_HANDLE_VALUE == handle || 0 == handle)
            return 0;
        if (NULL == m_ZwQueryObject)
            return 0;
    
        PfnZwQueryObject CurZwQueryObject = NULL;
        CurZwQueryObject = reinterpret_cast<PfnZwQueryObject>(m_ZwQueryObject);
        if (CurZwQueryObject == NULL)
            return 0;
    
        char * pBuffer = new char[0x300];
        ULONG uRetSize = 0;
        OBJECT_INFORMATION_CLASS ob = ObjectTypeInformation;
        CurZwQueryObject(handle, ob, pBuffer, 0x300, &uRetSize);
        USHORT Type = 0;
        PPUBLIC_OBJECT_TYPE_INFORMATION PtypeInfo = reinterpret_cast<PPUBLIC_OBJECT_TYPE_INFORMATION>(pBuffer);  //查询类型信息
        Type = PtypeInfo->MaintainTypeList;
        delete[] pBuffer;
    
        return Type;
     
    }
    
    

    2.打开进程获得进程句柄

    
    HANDLE hProcess;
    hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid);
    

    3.遍历进程拷贝句柄.判断文件类型过滤.关闭句柄

    这个属于核心代码

    
    HANDLE hTarHandle;
        for (int i = 0; i < 0x40000; i++) //65535
        {
            if (NatHndDuplicateHandle(hProcess, (HANDLE)i, GetCurrentProcess(), &hTarHandle, 0, 0, 2))
            {
                //成功了.查询类型信息
    
                char * pBuffer = new char[0x300]();
                ULONG uRetSize = 0;
                OBJECT_INFORMATION_CLASS ob = ObjectTypeInformation;
                ZwQueryObject((HANDLE)hTarHandle, ob, pBuffer, 0x300, &uRetSize);
    
                PPUBLIC_OBJECT_TYPE_INFORMATION PtypeInfo = reinterpret_cast<PPUBLIC_OBJECT_TYPE_INFORMATION>(pBuffer);  //查询类型信息
                PtypeInfo->MaintainTypeList;
    
                if (PtypeInfo->MaintainTypeList == dwSystemFileHandleType)
                {
                    //是文件.尝试使用DumpLicateHandle 传入DUPLICATE_CLOSE_SOURCE 来关闭.
                    //psOpt.HndDuplicateHandle(hProcess, (HANDLE)i, GetCurrentProcess(), NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
    
                    //如果是是文件.查询其文件名.
                    OBJECT_INFORMATION_CLASS ob = ObjectFileInformation;
                    char * Buffer1 = new char[0x100];
                    memset(Buffer1, 0, 0x100);
                    ZwQueryObject(hTarHandle, ob, Buffer1, 0x100, &uRetLength);
                    POBJECT_NAME_INFORMATION pFileInfo = reinterpret_cast<POBJECT_NAME_INFORMATION>(Buffer1);
                    PWSTR pszBuffer = new wchar_t[0x255]();
    
                    char szBuffer[0x256] = { 0 };
                    if (pFileInfo->Name.Buffer == 0)
                        continue;
                    memcpy(pszBuffer, pFileInfo->Name.Buffer, pFileInfo->Name.Length);
    
                    WideCharToMultiByte(CP_ACP, 0, pszBuffer, 0X256 * sizeof(TCHAR), szBuffer, 0x256, 0, 0);
                    string str = szBuffer;
                    str.substr(str.find_last_of("\"));
                    if (str.find(OccFileName) != string::npos)
                    {
                        //关闭其句柄
                        NatHndDuplicateHandle(hProcess, (HANDLE)i, GetCurrentProcess(), NULL, 0, 0, DUPLICATE_CLOSE_SOURCE);
                        CloseHandle(hProcess);
                        return TRUE;
                    }
    
                }
    
            }
        }
        CloseHandle(hProcess);
    
        return FALSE;
    
    

    NatHndDuplicateHandle其实内部就是对 DuplicateHandle 函数的封装.

    关于结构网上也很多.我这里也直接进行拷贝了.
    .h跟.cpp都提供一下.看的容易.

    链接:https://pan.baidu.com/s/1ct-kNoe1Sr1j9LjM9sflCA
    提取码:nxo3

  • 相关阅读:
    Java +安卓 定时任务
    android动画解析(初级)
    语义化版本 2.0.0
    团队中的 Git 实践
    Spring和SpringBoot比较,解惑区别
    Spring boot 拦截器和过滤器
    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-install-plugin:2.4:install (default-cli) on project kircp-js-plan-resource: The packaging for this project did not assign a file to the bu
    Java函数优雅之道
    在springMVC的controller中获取request,response对象的一个方法
    Kotlin 数据类型(数值类型)
  • 原文地址:https://www.cnblogs.com/iBinary/p/11414236.html
Copyright © 2020-2023  润新知