删除正在使用的文件

转载 2007年10月08日 20:10:00
#include <Windows.h>
#include 
<stdio.h>
BOOL ZapDelFile(
char *szFileToDel)
...{
    
char cTempFileName[0x80];
    
char cTempPathName[0x100];
    
char cFileName[0x100];

    
if(szFileToDel[1== ':')...{
        sprintf(cTempPathName, 
"%c:/", szFileToDel[0]);
    }

    
else...{
        GetModuleFileName(NULL, cFileName, 
0x100);
        sprintf(cTempPathName, 
"%c:/", cFileName[0]);
    }


    
if(GetTempFileName(cTempPathName, "_@"0, cTempFileName) == 0)...{
        
return FALSE;
    }


    
if(MoveFileEx(szFileToDel, cTempFileName, 1== 0)...{
        
return FALSE;
    }


    
if(MoveFileEx(cTempFileName, NULL, 4== 0)...{
        
return FALSE;
    }


    
return TRUE;
}


void usage(char *n) ...{
    printf(
"usage: %s fileNeedToDeln", n);
    exit(
0);
}


int main(int argc, char* argv[])
...{

    printf(
"Zap programed by bgate. :) *nn");

    
if (argc != 2)
        usage(argv[
0]);

    
if(ZapDelFile(argv[1]) == TRUE)...{
        printf(
"OK");
    }

    
else...{
        printf(
"error %d", GetLastError());
    }

    
return 0;
}
 

 

现在你已经可以用它去删除正在使用的系统文件了, 不过删除之后会弹出让你插入Windows CD对话框.
注意: 删系统文件前做好备份, 在重启前恢复, 另外删系统文件前还需要把dllcache中相应的备份删除. 否则系统会自动恢复.

接下来就想办法去掉这个对话框, 拿出我的法宝--google. 胡乱地搜了一气. 搜到两条有用信息.
1.Windows 2000下执行系统文件保护的代码在sfc.dll中, Xp系统下在sfc_os.dll中.
2.注册表中把一个叫SfcDisable的键设为FFFFFF9D能在下次启动时让文件保护功能失效.

下面的分析是在Win2K sp4+上进行的. 其中分析的sfc.dll版本是5.0.2195.6673

    用ida打开sfc.dll在string中找sfcdisable, 没找到! 让string显示Unicode. 这下看到了. 找到对SfcDisable引用的一个地方.代码如下
.text:769269F9                 call     _SfcQueryRegDwordWithAlternate@16 ; SfcQueryRegDwordWithAlternate(x,x,x,x)
.text:769269FE                 push     ebx
.text:769269FF                 push     offset ??_C@_1BG@HOGG@?$AAS?$AAf?$AAc?$AAD?; "SfcDisable"
.text:76926A04                 push     edi
.text:76926A05                 push     esi
.text:76926A06                 mov     _SFCDebug, eax
.text:76926A0B                 call     _SfcQueryRegDwordWithAlternate@16 ; SfcQueryRegDwordWithAlternate(x,x,x,x)
.text:76926A10                 push     ebx
.text:76926A11                 push     offset ??_C@_1BA@HLJH@?$AAS?$AAf?$AAc?$AAS?$AAc?$AAa?$AAn?$AA?$AA@ ; "SfcScan"
.text:76926A16                 push     edi
.text:76926A17                 push     esi
.text:76926A18                 mov     _SFCDisable, eax
.text:76926A1D                 call     _SfcQueryRegDwordWithAlternate@16 ; SfcQueryRegDwordWithAlternate(x,x,x,x)
.text:76926A22                 push     ebx
.text:76926A23                 push     offset ??_C@_1BC@KFAJ@?$AAS?$AAf?$AAc?$AAQ?$AAu?$AAo?$AAt?$AAa?$AA?$AA@ ; "SfcQuota"
.text:76926A28                 push     edi
.text:76926A29                 push     esi
.text:76926A2A                 mov     _SFCScan, eax

    其中_SfcQueryRegDwordWithAlternate@16是读注册表的函数. 很明显, 它把注册表中SfcDisable的值读到了_SFCDisable中. 好, 调出softice. 在_SFCDisable上设断点. 我们又用刚写的zap去删系统文件, softice弹出来了. 断到了下面这个地方, eip为7692A326, _SFCDisable为2.
.text:7692A319                 push     ecx
.text:7692A31A                 and     [esp+4+var_4], 0
.text:7692A31F                 cmp     _SFCDisable, 3
.text:7692A326                 push     ebx
.text:7692A327                 push     ebp
.text:7692A328                 push     esi
.text:7692A329                 push     edi
.text:7692A32A                 jnz     short loc_7692A333
.text:7692A32C                 xor     eax, eax
.text:7692A32E                 jmp     loc_7692A459
    F5退出, 一会儿对话框弹了出来, 就对这儿引用了一次. 很好, 看看上面这段代码"cmp _SFCDisable, 3". 此时_SFCDisable为2弹出了对话框, 那么我就把它改为3又用zap删系统文件试试. 哈, 运气很好, 这次没出现让插CD的对话框了. 也就是说只要我们把_SFCDisable改为3就能偷偷地替换系统文件了. 不过不同版本这个地址是不一样的, 用switch来做这个活总是不好. 得写个有通用性的代码.

    开始我想它的工作原理大概是Winlogon发现了有对系统文件进行操作. 便调用sfc.dll中的输出函数进行检查. 我们就只需得到这个输出函数入口然后把这个函数"注释"掉就可以了.跟着上面这段代码逆流而上, 找到最后由76924544输出, 又在76924544上加个断点, 继续去删文件. softice跳出来了, 不过不在函数的入口, 反倒在刚才设置的对_SFCDisable的读取上, 没运行函数的入口就运行了函数体中的代码, 看来遇到高人了. 非得逼我出必杀技, 打开2000源代码 : ). 找了半天没找到相应代码又只得退回来看汇编, 最后发现了这个函数NtWaitForMultipleObjects. 呵, 难怪没中断在函数的入口上, 原来早运行了函数的入口然后在函数体里一直没退出. 注释函数的方法不行了.

    这时我想它的工作原理大概是winlogon调用sfc.dll中的输出函数在系统启动时创建了一系列事件. 既然winlogon创建了, 那么它也应该得撤销. 用depends打开winlogon. 果然从sfc.dll中输入了两个函数. 一个是刚才分析的那个, 创建了一系列事件. 看看另一个, 输出地址是76926869, 不出所料, 关闭了一系列事件. 现在我们只要向winlogon中注入代码调用"另一个"函数就能取消文件保护功能了. 不过winlogon不能随便注入代码. 26A杂志第六期上有篇文章提到了注入方法:"adjust debugger access rightz to our process". 那也是一篇SFCDisable的文章, 他用的方法是在内存中搜索特征码, 然后修改. 通用性应该没这么好.

    下面的注入方法是从crazylord的代码中拷过来的, 不过方法不是. :), 写完后就懒得检查了, 加之水平有限, 写的不过优雅的地方就将就着看.

-----------------cut antisfc.c-----------

#include <stdlib.h> 
#include 
"Windows.h" 
#include 
"Tlhelp32.h" 
#pragma comment( lib, "Advapi32.lib" ) 

typedef 
void (_stdcall * CLOSEEVENTS)(void); 
typedef unsigned 
long DWORD; 
typedef DWORD ANTISFC_ACCESS; 

/**//* 
* ANTISFC structures 
*/
 

typedef 
struct _ANTISFC_PROCESS ...
    DWORD     Pid;                 
// process pid 
    HANDLE ProcessHandle;       // process handle 
    char   ImageName[MAX_PATH]; // image name (not full path) 
}
 ANTISFC_PROCESS, *PANTISFC_PROCESS; 

__inline 
void ErrorMessageBox(char *szAdditionInfo) 
...
    printf(
"error on %s, error code %d. n", szAdditionInfo, GetLastError()); 
}
 

void usage(char *n) ...
    printf(
"usage: %s [/d]n", n); 
    printf(
"t/d: disable sfc file protecte fuction.n"); 
    exit(
0); 
}
 

DWORD Init() 
...
    DWORD   Ret 
= 0
    HANDLE hToken; 
    LUID sedebugnameValue; 
    TOKEN_PRIVILEGES tkp; 

    
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) ...
        ErrorMessageBox(
"OpenProcessToken"); 
    }
 else ...

        
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)) ...
            ErrorMessageBox(
"LookupPrivilegeValue"); 
        }
 else ...

            tkp.PrivilegeCount 
= 1
            tkp.Privileges[
0].Luid = sedebugnameValue; 
            tkp.Privileges[
0].Attributes = SE_PRIVILEGE_ENABLED; 

            
if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL)) ...
                ErrorMessageBox(
"AdjustTokenPrivileges"); 
            }
 else ...
                Ret 
= 1
            }
 
        }
 
        CloseHandle(hToken); 
    }
 

    
return(Ret); 
}
 

DWORD GetPidEx(
char *proc_name, char *full_path) ...
    DWORD             dwPid
=0
    HANDLE             hSnapshot; 
    PROCESSENTRY32     pe; 
    BOOL               Ret; 
    
  
if (isdigit(proc_name[0])) 
      dwPid 
= strtoul(proc_name, NULL, 0); 
  
else 
      dwPid 
= -1
      
    hSnapshot 
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 
    
if (hSnapshot == (HANDLE) -1)...
        ErrorMessageBox(
"CreateToolhelp32Snapshot"); 
        
return(0); 
    }
 

    pe.dwSize 
= sizeof(PROCESSENTRY32); 
    Ret 
= Process32First(hSnapshot, &pe); 

    
while (Ret) ...
          
if((strncmp(strlwr(pe.szExeFile), strlwr(proc_name), strlen(proc_name)) == 0
            
(pe.th32ProcessID 
== dwPid)) ...
                dwPid 
= pe.th32ProcessID; 
                strcpy(full_path, pe.szExeFile); 
                
break
        }
 
        pe.dwSize 
= sizeof(PROCESSENTRY32); 
        Ret 
= Process32Next(hSnapshot, &pe); 
    }
 

    CloseHandle(hSnapshot); 
    
if (dwPid == -1
      dwPid 
= 0
    
return(dwPid); 
}
 

DWORD InitProcess(PANTISFC_PROCESS Process, 
char *proc_name, ANTISFC_ACCESS access) ...
    DWORD Ret
=0

    Process
->Pid = GetPidEx(proc_name, Process->ImageName); 
    
if (Process->Pid != 0 && Process->ImageName[0!= 0...
        Process
->ProcessHandle = OpenProcess(access, FALSE, Process->Pid); 
        
if (Process->ProcessHandle == NULL) 
            ErrorMessageBox(
"OpenProcess"); 
        
else 
            Ret 
= 1
    }
 

    
return(Ret); 
}
 

DWORD InjectThread(PANTISFC_PROCESS Process, 
                PVOID function) 
...
    HANDLE     hThread; 
    DWORD     dwThreadPid 
= 0, dwState; 

    hThread 
= CreateRemoteThread(Process->ProcessHandle, 
                                NULL, 
                                
0
                                (DWORD (__stdcall 
*) (void *)) function, 
                                NULL, 
                                
0
                                
&dwThreadPid); 
    
if (hThread == NULL) ...
        ErrorMessageBox(
"CreateRemoteThread"); 
        
goto cleanup; 
    }
 

    dwState 
= WaitForSingleObject(hThread, 4000); // attends 4 secondes 

    
switch (dwState) ...
    
case WAIT_TIMEOUT: 
    
case WAIT_FAILED: 
        ErrorMessageBox(
"WaitForSingleObject"); 
        
goto cleanup; 

    
case WAIT_OBJECT_0: 
        
break

    
default
        ErrorMessageBox(
"WaitForSingleObject"); 
        
goto cleanup; 
    }
 

    CloseHandle(hThread); 
    
return dwThreadPid; 
    
cleanup: 
    CloseHandle(hThread); 

    
return 0
}
 

int main(int argc, char* argv[]) 
...
    ANTISFC_PROCESS     Process; 
    HMODULE hSfc; 
    DWORD     dwThread; 
    CLOSEEVENTS pfnCloseEvents; 
    DWORD dwVersion; 

    printf(
"AntiSfc programed by bgate. :) *nn"); 

    
if (argc != 2
        usage(argv[
0]); 

    
if (strcmp(argv[1], "/d"!= 0...
        usage(argv[
0]); 
    }
 

    
if (Init()) ...
        printf(
"debug privilege setn"); 
    }
 else ...
        printf(
"error on get debug privilegen"); 
        
return(0); 
    }
 

    
if(InitProcess(&Process, "winlogon.exe", PROCESS_ALL_ACCESS) == 0...
        printf(
"error on get process info. n"); 
        
return(0); 
    }
 

    dwVersion 
= GetVersion(); 
    
if ((DWORD)(LOBYTE(LOWORD(dwVersion))) == 5)...{                 // Windows 2000/XP 
        if((DWORD)(HIBYTE(LOWORD(dwVersion))) == 0)...{             //Windows 2000 
            hSfc = LoadLibrary("sfc.dll"); 
            printf(
"Win2000n"); 
        }
 
        
else ...{//if((DWORD)(HIBYTE(LOWORD(dwVersion))) = 1)             //Windows XP 
            hSfc = LoadLibrary("sfc_os.dll"); 
            printf(
"Windows XPn"); 
        }
 
    }
     
    
//else if ()   //2003? 
    else ...
        printf(
"unsupported versionn"); 
    }
 

    pfnCloseEvents 
= (CLOSEEVENTS)GetProcAddress(hSfc, 
                                                MAKEINTRESOURCE(
2)); 
    
if(pfnCloseEvents == NULL)...
        printf(
"Load the sfc fuction failedn"); 
        FreeLibrary(hSfc); 
        
return(0); 
    }
 

    FreeLibrary(hSfc); 

    dwThread 
= InjectThread(&Process, 
                            pfnCloseEvents); 
    
    
if(dwThread == 0)...
        printf(
"failedn"); 
    }
 
    
else...
        printf(
"OKn"); 
    }
 

    CloseHandle(Process.ProcessHandle); 
    
return(0); 

}
 




------------------end cut---------
    在运行zap替换系统文件前运行一下antisfc就行了, 你也可以把它们写到一起. 理论上他能在2000, xp, 2003?的任何版本上使用. 不过我只在Win2K sp4+, WinXP sp1+上测试过.
    本文的缺点是替换的系统文件只能在重启后生效, 写完了.

 

如何删除正在使用中的dll文件

在论坛有时候老听网友说某某文件删不掉啊。。之类的。而且有很多都是dll文件。虽然解决这个问题的方法有很多种。而且也可以把他删除,但是网友们有没有想过是为什么删不掉呢??这是因为你运行的某个程序正在调用...
  • yluck
  • yluck
  • 2007-07-20 10:43:00
  • 5132

如何强制删除正在使用的文件

如何强制删除正在使用的文件好象以前有一个函数可以删除程序本身,找不到了,估计可以参考一下,请各位大侠指教------------------------------------------------...
  • killer000777
  • killer000777
  • 2006-08-11 10:22:00
  • 4235

Win7删除、移动文件时提示文件夹正在使用怎么办

如何解决Win7系统在删除或移动文件时提示,“操作无法完成,因为其中的文件夹或文件已在另一个程序中打开,请关闭该文件夹或文件,然后重试”。 右击任务栏,选择“启动任务管理器” 选择“性...
  • maoxiaojiemaoxiaojie
  • maoxiaojiemaoxiaojie
  • 2017-05-22 09:09:50
  • 441

学习强制删除正在运行的文件

看雪软件安全论坛 > 软件安全 > 『安全编程论坛』 > 【分享】学习强制删除正在运行的文件PDA查看完整版本 : 【分享】学习强制删除正在运行的文件yaolibing2009-04-28, 12:0...
  • jiftlixu
  • jiftlixu
  • 2009-12-03 18:32:00
  • 1743

java强行删除文件(针对进程正在使用的文件的删除)

boolean result = f.delete();   if(!result)    {     System.gc();     f.delete;    }...
  • paullinjie
  • paullinjie
  • 2017-01-07 08:51:39
  • 985

如何移动、替换和删除当前正在使用的文件

有时,Win32 应用程序需要删除、重命名或移动系统当前正在使用的文件。一个常见的例子就是安装程序在完成软件包的安装后,需要从用户硬盘中将它自身删除。有时,这些应用程序还需要移动系统当前正在使用的设备...
  • wangji163163
  • wangji163163
  • 2007-12-30 21:36:00
  • 1844

删除正在运行的程序(文件)

  • 2013年09月02日 18:38
  • 41KB
  • 下载

强制删除正在使用的文件unlocker1.8.8.exe

  • 2010年10月26日 09:16
  • 186KB
  • 下载

解决:删除文件时“文件正在使用”不能完成

删除文件或文件夹,特别是 Temp 临时文件夹时,可能遇到下列错误信息【文件正在使用】或是【操作无法完成,因为文件已在 XXX 中打开】。 要成功删除这些文件,首先要找出哪些进程调用了它们,然后...
  • maowenge
  • maowenge
  • 2015-03-24 16:08:10
  • 365

Linux 下如何真正地删除一个正在被进程独占的文件

今天工作sever 上的/home目录下磁盘空间满了,找到大文件,用rm 发现删不了,原来有进程占用了它。 那如何知道到底是哪一个进程占用了这个文件呢?用 2. 查看谁正在使用某个文件 lsof...
  • budapest
  • budapest
  • 2011-11-27 20:19:03
  • 5901
收藏助手
不良信息举报
您举报文章:删除正在使用的文件
举报原因:
原因补充:

(最多只允许输入30个字)