cnhackteam7 发布于2022年11月8日 分享 发布于2022年11月8日 0x00 前言 在渗透测试中,文件的恢复和删除就像矛和盾。 文件恢复是指恢复目标系统的已删除文件,而文件删除是指删除目标系统上使用的工具,以避免被恢复。 0x01 简介 本文将介绍以下内容: 删除文件的原则 文件恢复原理 使用PowerForensics恢复文件 使用SDelete删除文件。 用SDelete删除文件后,可以用PowerForensics恢复吗? 防止通过文件覆盖来恢复文件。 枚举所有进程,搜索指定文件的句柄,释放句柄,移除文件占用,删除文件。 实现细节和开放源代码 0x02 文件删除与恢复的原理 参考资料: http://www.ntfs.com/ntfs_basics.htm 基本概念 Windows文件系统大多使用NTFS(新技术文件系统)技术。 NTFS中的每个文件都对应一个主文件表(MFT)。 MFT被用作文件索引来存储文件的属性。 文件删除的直观理解: 仅修改了MFT(文件属性),但未修改已删除文件的内容。 文件恢复的直观理解: 只需恢复文件的MFT。 简单测试 新建一个文件test.txt,写内容0123456789。 使用工具:WinHex 下载地址: http://www.x-ways.net/winhex/ 选择工具-打开磁盘,然后选择驱动器号。 找到文件test.txt,右键-导航-查找文件记录。 检查test.txt的MFT信息,如下图所示 MFT的结构如下 注: 照片取自http://www.blogfshare.com/detail-ntfs-filesys.html. 接下来,删除test.txt文件并清空回收站。 使用WinHex再次查看硬盘内容,关闭当前盘符,重新选择工具-打开磁盘,选择盘符。 该框提示您选择更新快照,如下图所示。 再次检查MFT结构,如下图所示 经过比较,区别如下: 偏移量0x08 偏移量0x10,值加1 偏移量0x16,从1到0 在WinHex界面选择恢复文件,成功恢复文件。 注: 成功恢复的前提是文件没有被覆盖。 综上所述,文件恢复的原理可以简单理解为: 文件删除操作仅修改了文件的MFT,如果文件内容尚未被覆盖,就能恢复文件 0x03 利用PowerForensics恢复文件 有很多种文件恢复软件。这里有一个通过powershell进行文件恢复的工具:PowerForensics。 工程地址: https://github.com/Invoke-IR/PowerForensics/ 下载地址: https://github.com/Invoke-IR/PowerForensics/releases 注: PowerForensicsv2.zip对应的是Powershell v2,这是Win7和Sever2008的默认版本。 如何使用工具可以直接参考xpn的博客: https://blog.xpnsec.com/offensive-forensics/ 获取所有可恢复文件的列表。powershell命令如下: powershell-执行策略旁路 导入模块。\PowerForensicsv2.psd1 get-forensicfilecord | Where { $ _。Deleted -eq $true} |选择全名 恢复的文件C:\test.txt保存为recovered.txt: $ file=Get-ForensicFileRecord | Where { $ _。FullName -eq 'C:\test.txt'} $file。CopyFile('recovered.txt ') 0x04 防止文件被恢复 1、使用工具SDelete 下载地址: https://docs . Microsoft . com/en-us/sysinternals/downloads/s delete 删除命令如下所示: sdelete64.exe accept EULA C:\ test . txt 2、通过c++实现 经过对0x01的原理分析,我们知道只有覆盖原文件才能防止文件被恢复。 最简单的实现思路: 修改原始文件的内容,填充随机字符串,然后删除文件。 我写了一个简单的测试代码,在删除文件之前,用0填充要删除的文件的内容。即使文件被恢复,内容也全是0。供参考的C代码如下: #包括 int main(int argc,char *argv[]) { 如果(argc!=2) { printf(' \ n覆盖文件,避免被还原\ n \ n '); printf('用法:\ n '); printf('%s \n ',argv[0]); 返回0; } printf('[*]尝试覆盖文件%s ',argv[1]); FILE * fp int err=fopen_s(fp,argv[1],' Rb '); 如果(呃!=0) { printf('\n[!]打开文件错误!'); 返回0; } fseek(fp,0,SEEK _ END); int len=ftell(FP); char * buf=new char[len]; memset(buf,0,len); fclose(FP); err=fopen_s(fp,argv[1],' WB '); 如果(呃!=0) { printf('\n[!]打开文件错误!'); 返回0; } fwrite(buf,len,1,FP); fclose(FP); printf(' done \ n '); printf('[*]尝试删除文件%s ',argv[1]); if(DeleteFile(argv[1])!=0) printf(' done \ n '); 其他 printf(' error \ n '); 返回0; } 0x05 解除文件占用 实际删除文件时,我们经常会遇到文件被占用而无法删除的情况。 这里需要找到占用文件的进程,获取文件句柄,在删除文件之前释放句柄。 实现思路如下: 该程序被提升为调试特权。 枚举所有进程 获取指定文件的句柄。 松开把手。 具体到方案实施,我们需要注意以下问题: 1、提升至debug权限 BOOL EnableDebugPrivilege { BOOL fOk=FALSE 处理hToken if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hToken)) { TOKEN _ PRIVILEGES tp tp。PrivilegeCount=1; LookupPrivilegeValue(NULL,SE_DEBUG_NAME,tp。权限[0]。luid); tp。权限[0]。Attributes=fEnable?SE _ private _ ENABLED:0; AdjustTokenPrivileges(hToken,FALSE,tp,sizeof(tp),NULL,NULL); fOk=(GetLastError()==ERROR _ SUCCESS); close handle(hto ken); } 退货(fOk); } 2、枚举所有进程,获得指定文件的句柄 使用内核API NtQuerySystemInformation查询SystemHandleInformation,获取所有进程的句柄。 筛选出类型文件的句柄:ObjectTypeNumber=0x1e。 如果句柄对应的进程打不开,就留一个标志位,不要重复打开进程。 过滤掉可能导致挂起的句柄,使用API WaitForSingleObject进行判断。 3、释放句柄 使用内核API NtQuerySystemInformation查询SystemHandleInformation得到的句柄是伪句柄,不能直接释放。 您需要使用API DuplicateHandle将伪句柄转换为真实句柄。 功能模型如下: BOOL WINAPI重复处理( _In_ HANDLE hSourceProcessHandle, _In_ HANDLE hSourceHandle, _In_ HANDLE hTargetProcessHandle, _Out_ LPHANDLE lpTargetHandle, _ In _ DWORD dwDesiredAccess, bInheritHandle, _In_ DWORD dwOptions ); 第七个参数设置为DUPLICATE_CLOSE_SOURCE,这意味着源进程中的句柄将被释放。 具体参数如下: DuplicateHandle(processHandle,(Handle)句柄。Handle,GetCurrentProcess(),dupHandle,0,0,DUPLICATE_CLOSE_SOURCE) 完整的代码已经开源,地址如下: https://github.com/3gstudent/Catch-specified-file-s-handle 该代码枚举当前系统的所有进程,找到指定文件的句柄并释放它。 它不仅可以用来缓解文件占用,还可以禁用日志的一些功能。 例如,如果system.evtx的句柄被释放,则日志服务无法将日志写入system.evtx,从而导致system.evtx下的日志失效。 0x06 小结 简要介绍文件删除和恢复的原理,测试工具,编写程序利用文件覆盖防止文件被恢复,解决文件占用问题。开源代码。 从渗透的角度来说,一是想办法恢复目标系统的文件,二是安全删除自己的工具,避免被恢复。 从防御的角度来说,可以使用工具SDelete安全删除重要文件。 留下回复 链接帖子 意见的链接 分享到其他网站 更多分享选项…
推荐的帖子