设为首页 收藏本站
查看: 857|回复: 0

[经验分享] 在重启过程中替换windows保护的系统文件

[复制链接]

尚未签到

发表于 2016-5-21 11:00:27 | 显示全部楼层 |阅读模式
  

  在重启过程中替换windows保护的系统文件 
  作者:ClassyK 日期:2006-01-25
  

  这最先缘起写一个3721的卸载软件,当时把系统文件都删除了,可是搜索依然会定位到3721,譬如当我在地址栏输入"好的"然后按回车,网页先定位去microsoft的搜索引擎,可是很快,被3721的引擎给替换了。变成了如下地址hxxp://cns.3721.com/cns.dll?coagent=dh&fw=dh&name=%BA%C3%B5%C4&pid=1000026&cnspid=401742_1006
  

  在网上查阅了一下资料,这问题的引起在于广东电信将http://auto.search.msn.com重定位到hxxp://cns.3721.com,估计是跟3721有合作协议吧。现在的问题,让我们把系统里原来的搜索引擎替换为google,后来检查发现,原来的搜索引擎竟然是固化在一个系统文件shdoclc.dll里头,这文件被explorer使用。要替换此地址,唯有修改文件了。
  

  但是修改远没想象中那么简单,最开始用了MoveFileEx,希望能在重启时替换此文件,但这函数只能应付普通的文件,对被windows保护的文件无能为力。只能另开道路了。在网上找了好多的资料,虽然有些是关于无提示替换系统文件的,但是都不够满意,或者实现非常复杂。我要做的,是安安静静的替换掉此文件。
  

  最后灵机一动,答案就出来了。临时替换掉windows shell,这个文件通常就是explorer了。可以通过注册表获得当前的shell是啥。(不过我下面的代码,并没有这样去考虑这么多。)
  

  附各部分代码如下(只适用于win 2000/XP/2003,不适合win9x):
  

  //C++代码 替换系统文件、Shell
  
void CRemove3721Dlg::ReplaceSystemFile(void)   
{   
CString strShdoclc = "\\shdoclc.dll";  // 要被替换的文件名   
WCHAR wszSearch[]= L"http://auto.search.msn.com/response.asp?MT=%1&srch=%2&prov=%3&utf8";  //原搜索引擎   
WCHAR wszReplace[]= L"http://www.google.com/search?inlang=zh-CN&q=%1&lr=lang_zh-CN"; //替换后的引擎   
char szWindows[MAX_PATH];   
GetWindowsDirectory( szWindows, sizeof szWindows);   
CString strTempPath = szWindows;   
strTempPath += "\\TEMP";  // 通常指向C:\windows\Temp  ,不使用GetTempPath得到的路径,为movefileex作准备  // MoveFileEx在重启时的替换只能是同分区(同一卷)的文件!   
char szSystem[MAX_PATH];   
GetSystemDirectory( szSystem, sizeof szSystem);   
CString strSystemDll = szSystem;   
strSystemDll += strShdoclc;   
// --------- 拷贝shdoclc.dll到临时目录   
char szTempFile1[MAX_PATH];   
GetTempFileName( strTempPath, "_@", 0, szTempFile1);   
CopyFile( strSystemDll, szTempFile1, FALSE);
//CopyFile( strSystemDll, "C:\\shdoclc.dll.bak", TRUE);  //备份,如果已存在,就不再替换   
// --------- 创建文件映像   
HANDLE hProFile = CreateFile( szTempFile1, GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);   
HANDLE hFileMap = CreateFileMapping( hProFile, NULL, PAGE_READWRITE, 0, 0, 0);   
if( hFileMap == NULL || hFileMap == INVALID_HANDLE_VALUE)   
{   
MessageBox( "CreateFileMapping Error", 0, MB_OK|MB_ICONERROR);   
return;   
}   
LPVOID lpBuf = MapViewOfFile( hFileMap, FILE_MAP_WRITE, 0, 0, 0);   
// --------- 查找   
DWORD dwLength = GetFileSize( hProFile, 0) / 2;   
wchar_t *wpFind = NULL;   
for( DWORD i=0; i<dwLength; i++)   
{   
wpFind = wcsstr(&((WCHAR*)lpBuf), wszSearch);   
if( wpFind != 0) break;   
}   
if( wpFind == 0)  //查找失败... 原文件已经被修改过   
{   
UnmapViewOfFile( lpBuf);   
CloseHandle( hFileMap);   
CloseHandle( hProFile);   
return;   
}   
// ---------- 替换   
wcscpy( wpFind, wszReplace);   
UnmapViewOfFile( lpBuf);   
CloseHandle( hFileMap);   
CloseHandle( hProFile);   
// 获取windows文件保护目录   // 以下获取各目录极为重要,如果漏掉将被windows替换回来   
CString strSFCDll = szSystem;   
strSFCDll += "\\dllcache";   
strSFCDll += strShdoclc;   
// 获取servicepack备份目录   
char szSP[MAX_PATH]; memset( szSP, 0, sizeof szSP);   
DWORD dwTemp1 = REG_SZ; DWORD dwTemp2= sizeof szSP;   
SHGetValue( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup", "ServicePackSourcePath",   
&dwTemp1, szSP, &dwTemp2);   
CString strSPDll = szSP;   
if( strSPDll.GetLength() != 0)   
{   
strSPDll += "\\i386";   
strSPDll += strShdoclc;   
}
// OK,现在这种方法不需要关闭文件保护,因为我们在文件保护前就替换了文件   
// 建立bat文件, 此文件用于替换文件   
CString strBat = strTempPath;   
strBat += "\\_@replace.bat";   
CFile fBat( strBat, CFile::modeCreate | CFile::modeWrite);   
CString strBuf;   
strBuf.Format( "Copy %s %s /y\n", szTempFile1, strSystemDll);   
fBat.Write( strBuf, strBuf.GetLength());   
strBuf.Format( "Copy %s %s /y\n", szTempFile1, strSFCDll);   
fBat.Write( strBuf, strBuf.GetLength());   
if( strSPDll.GetLength() != 0)   
{   
strBuf.Format( "Copy %s %s /y\n", szTempFile1, strSPDll);   
fBat.Write( strBuf, strBuf.GetLength());   
}   
strBuf.Format( "Del %s \n", szTempFile1);   
fBat.Write( strBuf, strBuf.GetLength());   
strBuf.Format( "Del %s \n", strBat);   
fBat.Write( strBuf, strBuf.GetLength());   
fBat.Close();   
// 用自身去替换系统shell,将bat文件名作参数传入   
// 这里没有去获取原来的shell,并非完美   
char szModule[MAX_PATH];   
GetModuleFileName( NULL, szModule, MAX_PATH);   
strcat( szModule, " ");   
strcat( szModule, strBat);   
SHSetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "Shell", REG_SZ,   
szModule, strlen( szModule));   
}
 

  

  //接下来要做的就是重启系统,这段代码没什么可提的了
  //C++代码 <重启系统: 如果只是替换此文件,只需要注销即可>

void CRemove3721Dlg::RestartMyComputer(void)  
{  
HANDLE hToken;   
TOKEN_PRIVILEGES tkp;  
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);  
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);   
tkp.PrivilegeCount = 1;  
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);   
ExitWindowsEx(EWX_REBOOT, 0);  
}  
    
  

  //现在,让我们看看启动的时候做些什么
  //C++代码 <重启过程中完成文件替换>
  
BOOL CRemove3721App::InitInstance()  
{  
InitCommonControls();  
CWinApp::InitInstance();  
AfxEnableControlContainer();  
//========== 以上是向导生成的代码 ===========
int nArgs;  
LPWSTR *szArg = CommandLineToArgvW( GetCommandLineW(), &nArgs);  
if( nArgs == 2)  
{  
CString  strBat(szArg[1]);  //利用构造函数完成unicode到multibyte的转换  
GlobalFree(szArg);  
//创建一个自定义desktop,防止出现dos窗口  
LPSTR lpDeskName = "ClassyK_Replace_Windows_File";  // 随便给一个名字  
HDESK hDesk = CreateDesktop( lpDeskName, NULL, NULL, 0, GENERIC_ALL, NULL);  
//以下启动开始创建的bat文件来进行替换
STARTUPINFO si;  
PROCESS_INFORMATION pi;  
ZeroMemory( &si, sizeof(si) );  
si.lpDesktop = lpDeskName;  
si.wShowWindow = SW_HIDE;  
si.dwFlags = STARTF_USESHOWWINDOW;  
si.cb = sizeof(si);  
ZeroMemory( &pi, sizeof(pi) );  
CreateProcess( NULL, strBat.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);  
WaitForSingleObject( pi.hProcess, INFINITE ); // 等待进程完成,否则可能因为shdoclc.dll正使用而无法完成替换。  
CloseDesktop( hDesk);  
CloseHandle( pi.hProcess );  
CloseHandle( pi.hThread );  
// 重置shell为explorer  
CString strShell = "Explorer.exe";  
SHSetValue(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "Shell", REG_SZ,   
strShell, strShell.GetLength());
// 运行原来的windows shell  
WinExec( strShell, SW_SHOW);
return FALSE;   // 直接返回,退出本程序。
}
//========== 以下是向导生成的代码 ===========  
CRemove3721Dlg dlg;  
m_pMainWnd = &dlg;  
INT_PTR nResponse = dlg.DoModal();  
if (nResponse == IDOK)  
{  
}  
else if (nResponse == IDCANCEL)  
{  
}  
return FALSE;  
}
 

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-219858-1-1.html 上篇帖子: Windows系统的桌面部署Desktop Deployment(3) 下篇帖子: 安装IIS的方法及windows组件向导没有IIS的解决办法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表