删除正在使用的文件

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

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值