设为主页 | 加入收藏 | 繁體中文

在Win2K/XP上替换正在使用的系统文件

  微软有两个工具可以替换正在使用的文件,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 fileNeedToDel\n", n);
  exit(0);
  }
  int main(int argc, char* argv[])
  {
  printf("Zap programed by bgate. :) *\n\n");
  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. :) *\n\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---------
  在运行zap替换体系文件前运行一下antisfc就行了, 你也可以把它们写到一同. 理论上他能在2000, xp, 2003?的任何版本上使用. 不外我只在Win2K sp4+, WinXP sp1+上测试过.
  本文的缺点是替换的体系文件只能在重启后见效, 写完了.
 


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: