逆向对抗技术之ring3解除文件句柄,删除文件
- 2019 年 10 月 8 日
- 筆記
目录
一丶简介
这些问题主要是工作中会遇到.包括后面的逆向对抗技术.有的可能只会提供思路.并且做相应的解决与对抗.
二丶实战 + 环境模拟
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