`
ijavagos
  • 浏览: 1229294 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

用远线程实现文件自删除

阅读更多

http://www.titilima.cn/readblog.php?id=138

点这里下载示例代码

实现文件自删除不是一个特别新的话题了,不过貌似一直没有特别完美的解决方式。从早先Gary Nebbett的堆栈溢出版本到后来的批处理、临时文件等方式,无不存在着各样瑕疵:如堆栈溢出不支持XP,临时文件(批处理)不够优雅等等。

当然,还有用驱动发IRP的方式,不过这只是一个自删除,杀鸡焉用牛刀?于是这个方案在我这儿亦不讨论。

李马讨论的,只是一个2005年的老调重提:远线程注入。2005年李马提到的DLL远程注入技术只是远线程的最简单应用,局限很多,能做的事情很少;下面的自删除示例,则是如何让远线程能够做更多的事,也可以说是一个补充材料,不必记入原创文档了吧就。

言归正传。首先,我们假定这个线程函数是这样的:

DWORDWINAPIDelProc(LPVOIDlpParam)
{
Sleep(50);
DeleteFileA((LPCSTR)lpParam);
return0;
}

解释一下,先用Sleep等待要删除的程序结束,之后调用DeleteFile删除目标文件。

现在,你可以在VC的Project Settings->C/C++->Category: Listing Files->Listing file type中,设置输出文件的类型为“Assembly, Machine Code, and Source”或“Assembly with Machine Code”,这样就会在编译完成后生成带有汇编代码和指令机器码的附属文件供你下一步对照。——当然,如果你极熟悉汇编,这一步可以跳过。

在查看附属文件后,我们可以提取出对我们有用的汇编代码:

push 50
call Sleep

mov eax, [esp + 4]
push eax
call DeleteFileA
ret 4

之后,对照着对应的机器码,构造下面的结构:

#pragmapack(push,1)
typedefstruct_tagDeleteStruct{
BYTEbyPush;
DWORDdwTime;
BYTEwCall1;
DWORDdwSleep;
DWORDdwMov;
BYTEbyPushEax;
BYTEwCall2;
DWORDdwDeleteFileA;
BYTEbyRet;
WORDw4;
CHARszFile[1];
}DELETESTRUCT,*PDELETESTRUCT;
#pragmapack(pop)

最后的szFile域,就是用来放置文件名的。其余的就不解释了,因为下面就要填充它了。远线程函数还是很模式化的代码,改造自两年前我的RemoteLoadLibrary:

BOOLRemoteDel(DWORDdwProcessID,LPCSTRlpszFileName,DWORDdwTime)
{
//打开目标进程
HANDLEhProcess=OpenProcess(
PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,
dwProcessID);
if(NULL==hProcess)
returnFALSE;

//向目标进程地址空间写入删除信息
DWORDdwSize=sizeof(DELETESTRUCT)+lstrlenA(lpszFileName);
PDELETESTRUCTpDel=(PDELETESTRUCT)GlobalAlloc(GPTR,dwSize);

HMODULEhKernel32=GetModuleHandle(_T("kernel32.dll"));
//pushdwTime
pDel->byPush=0x68;
pDel->dwTime=dwTime;
//callSleep
pDel->wCall1=0xe8;
pDel->dwSleep=(DWORD)GetProcAddress(hKernel32,"Sleep");
//moveax,[esp+4]
pDel->dwMov=0x0424448b;
//pusheax
pDel->byPushEax=0x50;
//callDeleteFileA
pDel->wCall2=0xe8;
pDel->dwDeleteFileA=(DWORD)GetProcAddress(hKernel32,"DeleteFileA");
//ret4
pDel->byRet=0xc2;
pDel->w4=0x0004;
lstrcpyA(pDel->szFile,lpszFileName);

LPVOIDlpBuf=VirtualAllocEx(hProcess,NULL,dwSize,MEM_COMMIT,
PAGE_READWRITE);
if(NULL==lpBuf)
{
GlobalFree((HGLOBAL)pDel);
CloseHandle(hProcess);
returnFALSE;
}

//修正近调用
pDel->dwSleep-=(DWORD)lpBuf+offsetof(DELETESTRUCT,dwMov);
pDel->dwDeleteFileA-=(DWORD)lpBuf+offsetof(DELETESTRUCT,byRet);
DWORDdwWritten;
WriteProcessMemory(hProcess,lpBuf,(LPVOID)pDel,dwSize,&dwWritten);

//创建线程,远程删除!
DWORDdwID;
HANDLEhThread=CreateRemoteThread(hProcess,NULL,0,
(LPTHREAD_START_ROUTINE)lpBuf,
(LPVOID)((DWORD)lpBuf+offsetof(DELETESTRUCT,szFile)),0,&dwID);

GlobalFree((HGLOBAL)pDel);
CloseHandle(hThread);
CloseHandle(hProcess);
returnTRUE;
}

至于为什么最后不用VirtualFreeEx释放资源,那是因为注入的远程代码在执行的时候目标exe就已经消失了,所以这里的寄主程序肯定存在着内存泄露,真是造孽啊。

最后说三点。第一,RemoteDel是要挑选一个寄主程序的,这个程序应该始终运行并存在于当前的系统中,我在示例中挑选的是explorer.exe;并且,打开这个进程是需要调试权限的,提权的代码也一并加入在示例代码中,算是弥补了2005年的缺失。第二,为了方便定位,我修改了远程代码中的调用,也就是call ds:xxx(FF 15 xxx)改为了call near xxx(E8 xxx)。第三,自己手写机器码的做法的确不如纯汇编代码重定位来的优雅,但是我认为这里填充并定位Sleep和DeleteFile的片断也是纯汇编的办法无法比拟的。

分享到:
评论

相关推荐

    [Delphi]使用远程线程方式删除自身

    3. **删除自身**:在TDeleteMeThread的Execute方法中,使用WinAPI函数`DeleteFile`来删除可执行文件。但需要注意的是,由于权限问题,当前进程无法直接删除自身,所以我们需要先结束进程然后再删除文件。 ```delphi...

    Java 利用多线程实现文件的分片下载

    Main方法是运行开始的方法,里面StopWatch是测速工具类,如果要想使用请导入相关maven坐标,不想使用直接删除即可。 内容概要: 这是随手写的一个利用线程池下载文件的小玩具,如果刚学完线程池不知道怎么使用的,...

    远程文件管理 线程插入

    用户可以在本地客户端通过这些协议与远程服务器进行交互,实现文件的浏览、下载、上传和删除。例如,FTP允许用户在不直接登录到远程服务器的情况下,传输和管理文件。 2. **反向连接方式**:反向连接是指客户端主动...

    Delphi中用多线程实现日志文件的读写与管理

    我们可以在多线程环境中设计一个定时任务,比如使用TTimer组件(尽管它不是线程,但可以在适当的时间触发事件),在特定时间点检查日志文件大小,当达到阈值时,创建新的日志文件或删除旧的日志。同时,为了保持日志...

    操作系统多线程与文件系统实现

    加上TCB管理的结构体,实现线程调度。 物理文件的存储结构 引导块区 FAT区 i节点区 数据区 实现的命令集 命令名称 使用举例 说明 format format 1024 格式化硬盘 open open filesystem 打开上次保存的文件系统 cd...

    多线程实现ftp客户端程序

    总的来说,多线程实现的FTP客户端程序通过并行处理多个任务,提高了文件操作的效率,提供了更高效的文件传输体验。在实际开发过程中,需要兼顾性能优化、线程安全和用户体验,确保程序的稳定性和可靠性。

    UDP 多线程 压缩文件

    6. **删除文件**: 文件删除功能可能用于清理不再需要的临时文件或旧的压缩文件,以释放磁盘空间。 在实现这个项目时,开发者首先需要理解和配置Winsock接口,创建UDP套接字,并设置多线程环境。每个线程可能需要...

    QT4.8 创建线程及日志定期删除

    以上就是使用QT4.8创建线程和实现日志定期删除的基本方法。在实际应用中,你可能需要考虑更多的细节,比如线程同步、异常处理、日志的滚动策略等,以确保程序的稳定性和可靠性。同时,对于QT4.8的项目,由于其已较为...

    Java Socket 多线程实现文件传输

    Java Socket 多线程实现文件传输是一个常见的网络编程任务,主要涉及到Java的Socket编程、多线程技术以及文件I/O操作。在这个过程中,服务器端创建一个Socket监听特定端口,等待客户端连接请求。一旦连接建立,双方...

    winform 多线程 异步 文件操作(查询、删除) 实例 代码 textbox ComboBox label C#

    6. **异步文件删除** 用户在ComboBox中选中要删除的文件,点击删除按钮,同样在新线程或任务中调用`File.Delete()`方法。删除操作完成后,可以通过Label显示成功或失败的信息,并更新ComboBox的文件列表。 7. **...

    多线程垃圾文件清除器

    总的来说,“多线程垃圾文件清除器”结合了多线程技术、文件遍历算法以及异常处理策略,实现了高效、稳定的垃圾文件清理。其设计思路和实现方式对于学习系统优化和文件管理具有很高的参考价值。通过深入理解并应用...

    使用线程动态遍历查找文件变化

    "使用线程动态遍历查找文件变化"这一主题,旨在教你如何通过编程技术实时监测文件或目录的变动,如新建、修改、删除等事件。这个过程通常涉及到多线程技术,以便在不影响主程序运行的情况下,实时获取文件系统的最新...

    自己用JAVA做的一个多线程文件服务器

    3. **网络编程**:Java的Socket编程是实现文件传输的关键,它允许服务器与客户端建立TCP连接进行数据交换。ServerSocket用于监听客户端连接,Socket用于处理客户端请求。 4. **输入/输出流**:Java的IO流库用于读取...

    C#实现远程文件传送

    在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows应用程序、Web...在C#的广阔世界里,还有很多其他高级特性和技术,如多线程、异步编程、任务并行库(TPL),都可以进一步优化远程文件传输的性能和体验。

    一个简单的文件操作多线程程序类(自己用的)

    - 使用`lock`语句或`Monitor`类可以确保同一时间只有一个线程访问文件,实现互斥访问。 - 为了提高效率,可以考虑使用异步I/O操作,如`async/await`关键字,允许线程在等待I/O操作完成时释放出来执行其他任务。 5...

    易语言多线程读取大文本文件源码

    6. **资源释放**:销毁不再需要的线程,使用“删除线程”命令释放线程资源。 在实际应用中,可能还需要考虑错误处理和性能优化。例如,设置适当的线程数量以平衡CPU资源的利用和线程管理开销,或者在读取大文件时...

    Android实例:多线程文件下载+在线音乐播放+清除下载文件

    在Android开发中,实现多线程文件下载、在线音乐播放以及清除下载文件是常见的功能需求。下面我们将逐一探讨这些知识点。 1. **Android多线程下载** 在Android中,由于主线程(UI线程)不能执行耗时操作,因此在...

    Android文件多线程下载

    本文将详细解析如何在Android环境中实现文件的多线程下载,包括自定义线程数、断点续传以及下载任务的管理。 一、多线程下载原理 1. 分块下载:多线程下载的基本思路是将大文件分割成若干小块,每个线程负责下载...

    Delphi多线程批量文件下载及解压程序源代码

    通过使用Indy、VclZip和可能的Siow_OBRAR_v0.04库,开发者能够克服单线程下载的局限性,提供更快速、更灵活的文件处理解决方案。对于学习和理解Delphi编程,以及多线程和文件处理技术的开发者来说,这是一个宝贵的...

    linux线程实现定时器源码

    在Linux系统中,线程实现定时器是一种常见的技术,它涉及到多线程编程、时间管理以及C语言编程。本文将深入探讨如何使用C语言在Linux环境下编写线程定时器的源码,同时会涵盖相关标签所涉及的关键概念。 首先,我们...

Global site tag (gtag.js) - Google Analytics