Visual Studioã§Webãããžã§ã¯ããæäœãããšããäžå¿«ãªäºçŽ°ãªããšã1ã€ãããŸã-éçºããã»ã¹äžã«è€æ°ã®ãã©ã³ãã䜿çšãããããããç°å¢ã®ç¬èªã®ã³ããŒïŒããŒã¿ããŒã¹ããŸãã¯å€éšãµãŒãã¹ãªã©ïŒã䜿çšããå¿ èŠãããå Žåããããã°æã«æ§æãã¡ã€ã«ã«åé¡ããããŸã-IISExpressã¯ããããžã§ã¯ããã©ã«ããŒå ã®ã¡ã€ã³web.configã®ã¿ã䜿çšããŸããéåžžããã¹ãŠã®æ¥ç¶æååã«ã¯ããã©ã«ãå€ãå«ãŸãããã©ã³ãåºæã®èšå®ã¯ãªããèµ·åæã«å€æã¯é©çšãããŸããã ãã¡ãããèªåãŸãã¯æåã§åŒ·å¶çã«web.configã«å€æãé©çšã§ããŸãããæåã«ãå€æŽããããã¡ã€ã«ã¯ä¿çäžã®å€æŽã§åžžã«ãã³ã°ããŸããããã«ãããäžèŠãªå€æŽãã³ããããããŠä»ã®ãã©ã³ãã«ç§»åãããªã¹ã¯ãçãã次ã«å€ãã®ãã¡ã€ã«ãäœæãããŸãæ§æãã¡ã€ã«ãžã®å€æŽãã³ãããããåã«ããã®ãããªå€æãæåã§åé€ããå¿ èŠããããããç·šéããéã«äžäŸ¿ã§ãã
ãããåé¿ããæ¹æ³ãæ€èšããŠãã ããã
ãœãªã¥ãŒã·ã§ã³ã¯éåžžã«ç°¡åã§ã-IISExpressããã»ã¹ã«ããæ§æãã¡ã€ã«ã®èªã¿åããã€ã³ã¿ãŒã»ããããå¿ èŠãããããœãŒã¹ãã¡ã€ã«ã®ä»£ããã«ãå¥ã®ãã¡ã€ã«ã察å¿ããä¿®æ£ãè¡ããããœãŒã¹ç®¡çã«è¿œå ãããŠããªãäžæãã¡ã€ã«ãã¹ãªããããŸãã ãããžã§ã¯ãã®èµ·åå ã®ãã©ã«ããŒã«å¿ããŠé©çšããå¿ èŠãããä¿®æ£ã®ãªã¹ãã¯ãããšãã°åçŽãªxmlãã¡ã€ã«ã§æå®ã§ããŸãã
ãããè¡ãã«ã¯ã次ã®ãã®ãå¿ èŠã§ãã
æ°ããããã»ã¹ãããã¯ä»ã32ãããããã³64ãããdllãããã¯ã°ã©ãŠã³ããŠãŒãã£ãªãã£ã«ãã£ãŠå®è¡ããã32ãããããã³64ãããexeã®äœæãç£èŠããããã¯ä»ãã®å¯Ÿå¿ããdllã察å¿ããããã深床ã®ããã»ã¹ã«ããŒãããããã¯ã°ã©ãŠã³ããŠãŒãã£ãªãã£ã
ããã¯ã°ã©ãŠã³ããŠãŒãã£ãªãã£ã¯ãManagementEventWatcherã¯ã©ã¹ãšãWin32_Processãªããžã§ã¯ãã®çš®é¡ãšå¿ èŠãªããã»ã¹åã«ãããã£ã«ã¿ãªã³ã°ã䜿çšãã__InstanceOperationEventãžã®èŠæ±ã䜿çšããŠãWMIãéããŠããã»ã¹ãç£èŠããŸãã ____InstanceCreationEventã€ãã³ããåãåãããšã¯ãããã»ã¹ãäœæãããããšãæå³ãããã®æ å ±ã¯EventArrivedEventArgs.NewEventããååŸã§ããŸãã ãã®å Žåãå¿ èŠãªã®ã¯ProcessIdã®ã¿ã§ãã
processWatcher.Query.QueryString = @"SELECT * FROM __InstanceOperationEvent WITHIN 1" + "WHERE TargetInstance ISA 'Win32_Process' AND (" + string.Join(" OR ", processNames.Select(x => "TargetInstance.Name = '" + x + ".exe'")) + ")"; processWatcher.EventArrived += (sender, e) => { if (e.NewEvent.ClassPath.ClassName == "__InstanceCreationEvent") { var processId = (uint)((ManagementBaseObject)e.NewEvent["TargetInstance"]) .Properties["ProcessId"].Value; // ... Do smth useful } };
DLLãå€éšããã»ã¹ã«ããŒãããã¢ã«ãŽãªãºã ã¯æšæºã§ã-å€éšããã»ã¹ã§ã¯ãVirtualAllocExãä»ããŠã¡ã¢ãªãdllãžã®ãã¹ã®äžã«å²ãåœãŠãããLoadLibraryã¢ãã¬ã¹ãCreateRemoteThreadã«æž¡ãããšã§ã¹ããªãŒã ãäœæãããŸãã ããã¯åæåã³ãŒããDllMainã«ããå Žåãè¿œå ã®ã¢ã¯ã·ã§ã³ã¯å¿ èŠãããŸããã ãã ããããã¯ã°ã©ãŠã³ããŠãŒãã£ãªãã£ã¯ã32ãããããã»ã¹ãš64ãããããã»ã¹ã®äž¡æ¹ã«åæã«dllãåå¥ã«å®è£ ããããšã¯ã§ããŸããã çè«çã«ã¯ã64ãããããã»ã¹ããCreateRemoteThreadãåŒã³åºããšããã¡ãã32ãããããã»ã¹ã§ã¹ã¬ãããäœæã§ããŸããããã®å ŽåãLoadLibraryã¯ã¹ã¬ããã®é¢æ°ãšããŠäœ¿çšãããŸãã ãããŠãæãç°¡åãªæ¹æ³ã§ã¯ãGetProcAddressã䜿çšããŠãçŸåšã®ããã»ã¹ãšåãããã深床ã®ã¢ãã¬ã¹ã®ã¿ãååŸã§ããŸãã Kernel32.dllã®ããŒã¹ã¢ãã¬ã¹ã¯åºå®ãããŠãããããåãããã容éã®ç°ãªãããã»ã¹ã®å Žåãé¢æ°ã®ã¢ãã¬ã¹ã¯åãã§ãã ãã¡ããçè«çã«ã¯ãPEããããŒãæåã§è§£æããå®è£ ã«è¿œå ã®ããã»ã¹ã䜿çšããããšã¯ã§ããŸããããããã¯ããè€éã§ãã
ãã¡ãããCreateFileWé¢æ°ãã€ã³ã¿ãŒã»ããããå¿ èŠããããŸãã æåã¯ãã¹ãŠã®ã³ãŒããå®å šã«CïŒã§èšè¿°ããŸããããå®éã«ã¯ãã®ãããªåºæ¬çãªæ©èœãã€ã³ã¿ãŒã»ãããããšããããŒãžã³ãŒããããšãã°ããã»ã¹ã«ãã£ãŠèªã¿èŸŒãŸãããµãŒãããŒãã£ã©ã€ãã©ãªã«ãã£ãŠDllMainããåŒã³åºããããšãã«ãããŒããŒããã¯ãªã©ã§ãšã©ãŒãçºçããŸãã ãããã£ãŠãCãã€ãã£ãdllã§åŠçããå¿ èŠã®ããããã¯ãšãã£ã«ã¿ãŒåŒã³åºããã€ã³ã¹ããŒã«ããå¿ èŠããããŸãããCãã€ãã£ãdllã¯ã.configãã¡ã€ã«ã«å¯ŸããŠCreateFileWãåŒã³åºãããå Žåã«ã®ã¿ãããŒãždllãèªã¿èŸŒã¿ããããããããŒãžã³ãŒããåŒã³åºããŸãã ããã¯ãã€ã³ã¹ããŒã«ããã«ã¯ã å®çžŸã®ãããµãŒãããŒãã£ã®ã©ã€ãã©ãªMinHookã䜿çšããŸãããã€ã³ã¿ãŒãããã«ã¯å€ãã®æ å ±ãããããã®èª¬æã«ã€ããŠã¯è©³ãã説æããŸããã ãCã§ãã¹ãŠãå®å šã«å®è¡ãã.netã¢ã»ã³ããªã®æãäœæããªãæ¹ãç°¡åã§ã¯ãªãã£ãããšãã質åã誰ããå°ãããããããŸãããããã¶ãéå±ã§ãã
ãã£ã«ã¿ãªã³ã°ããžãã¯ã¯ããã¡ã€ã«ãååšããããšããã£ã¬ã¯ããªã§ã¯ãªããã¡ã€ã«ã§ããããšãååã«web.configãå«ãŸããŠããããšãwindows \ microsoft.net \ ...ãã©ã«ããŒã«ãªãããšã確èªããå¿ èŠããããŸãïŒã·ã¹ãã æ§æã«ã¯é¢å¿ããããŸããïŒã ãããã®ãã¹ãŠã®æ¡ä»¶ãæºããããå Žåãã€ã³ã¿ãŒã»ãã¿ãŒã«ãã£ãŠå ã®ã·ã¹ãã é¢æ°CreateFileWãžã®åŒã³åºãããåä¿¡ããHANDLEãšããã®HANDLEã®å 容ãèªã¿åããããŒãžãã³ãã©ãŒãžã®ãã¹ãŠã®CreateFileWãã©ã¡ãŒã¿ãŒã転éããŸãã ç°¡åã«ããããã«ãå ã®HANDLEã䜿çšããŠååž°ãé²ãããšããå§ãããŸããããã«ãããåãããã¯ãæ©èœãããããFile.ReadAllTextã§åããã¡ã€ã«ãèªã¿åãããšã«ãªããŸãã ããã«ãåä¿¡ããã³ã³ãã³ãã§ã¯ãå¿ èŠãªãã¹ãŠã®è¡ã眮ãæããããå€æŽãããã³ã³ãã³ãã¯ãååãäžèšã®ãã£ã«ã¿ãŒåºæºãæºãããªãäžæãã¡ã€ã«ã«æžã蟌ãŸããŸãïŒç¹°ãè¿ãã«ãªããŸããïŒã web.configãéãããšããšåããã©ã¡ãŒã¿ãŒã§ãã®äžæãã¡ã€ã«ã«å¯ŸããŠCreateFileWãåŒã³åºããCreateFileWã€ã³ã¿ãŒã»ãã¿ãŒããåä¿¡ããHANDLEãè¿ããŸãã å ã®ãã³ãã«ã¯äžèŠã«ãªã£ããããéããå¿ èŠããããŸãã
ããã¯
HANDLE WINAPI _CreateFileW( LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { DWORD attributes = GetFileAttributesW(lpFileName); HANDLE result = CreateFileWOriginal(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); HANDLE newFile = NULL; if (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0 && (StrStrI(lpFileName, L"web.config") != NULL || StrStrI(lpFileName, L"app.config") != NULL) && StrStrI(lpFileName, L"Windows") == NULL) { fileHandler(result, &newFile, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } if (newFile != NULL) { CloseHandle(result); result = newFile; } return result; }
ãããŒãžããã³ãã©ãŒ
public static void GetUpdatedConfigF(IntPtr handle, IntPtr newHandleAddress, uint access, uint share, IntPtr securityAttributes, uint creationDisposition, uint flagsAndAttributes, IntPtr templateFile) { try { if (config == null) return; var path = new StringBuilder(260); if (GetFinalPathNameByHandle(handle, path, (uint)path.Capacity, 0) == 0) return; var matchedSection = config.FirstOrDefault(x => path.ToString().IndexOf(x.Branch, StringComparison.OrdinalIgnoreCase) >= 0); if (matchedSection == null) return; var size = GetFileSize(handle, IntPtr.Zero); if (size == 0) return; var buffer = new byte[size]; uint bytesRead; if (!ReadFile(handle, buffer, (uint)buffer.Length, out bytesRead, IntPtr.Zero)) return; var content = Encoding.UTF8.GetString(buffer); foreach (var replacement in matchedSection.Replacements) content = content.Replace(replacement.Find, replacement.ReplaceWith); var tempFile = Path.GetTempFileName(); MoveFileEx(tempFile, null, 4); File.WriteAllText(tempFile, content); var newHandle = CreateFileW(tempFile, access, share, securityAttributes, creationDisposition, flagsAndAttributes, templateFile); Marshal.WriteIntPtr(newHandleAddress, newHandle); } catch { } }
ããã¯ãæã€ãã€ãã£ãdllã¯ãLoadLibraryããã³GetProcAddressãä»ããŠãããŒãždllãããã³ãã©ãŒãåŒã³åºããŸãã ãããè¡ãã«ã¯ãéçã¡ãœãããéåžžã®dllé¢æ°ãšããŠãšã¯ã¹ããŒãããå¿ èŠããããŸãã ããã¯ãildasmã§éã¢ã»ã³ãã«ããilã³ãŒãã®ã¡ãœããã«ç¹å¥ãªãªãã·ã§ã³ãè¿œå ãããããdllã«ã¢ã»ã³ãã«ããããšã«ãããå°ãã·ã£ãŒããã¹ãã£ãã¯ãªæ¹æ³ã§è¡ãããŸãã ããã«ã€ããŠã¯ã€ã³ã¿ãŒãããã§ãå€ãã®èšäºããããŸãããç¹°ãè¿ãã¯ããŸããããããvtentryããæ€çŽ¢ããããšã§ç°¡åã«èŠã€ããããšãã§ããŸãã ãœãŒã¹ã³ãŒãã«ã¯ããã®æ¹æ³ã§ã¢ã»ã³ããªãåŠçããç°¡åãªãŠãŒãã£ãªãã£ãå«ãŸããŠããŸãã
IISExpressã«å ããŠãåæ§ã®åé¡ã¯wcfsvchostãä»ããŠèµ·åãããwcfãµãŒãã¹ã«ãé¢é£ããŠããŸãã 確ãã«ããã®å Žåãå€æã®äœ¿çšã¯æ£åžžã«æ©èœããŸããããã¹ãŠãäžè²«ããŠãããããå€æã§äœåãªãã¡ã€ã«ãè€è£œãããConfiguration Managerã§äœãåãæ¿ããªãããã«ããã®å Žåãèæ ®ããŸãã ããã€ãã®éãããããŸã-wcfsvchostã¯ããã»ã¹ã®éå§æã«ããã«æ§æãèªã¿åããWMIã€ãã³ãã®å°çãé ãããå¿ èŠä»¥äžã«ããã¯ãèšå®ãããŸãã ãã ããæ§æãã¡ã€ã«ãžã®ãã¹ã¯ã³ãã³ãã©ã€ã³çµç±ã§æž¡ãããããã芪ããã»ã¹ã«åã蟌ã¿ãCreateProcessWãã€ã³ã¿ãŒã»ããããå¿ èŠããããŸãã
ãã®å Žåã®èŠªããã»ã¹ã¯devenv.exeãã€ãŸã Visual Studio ãã®å Žåãåæã·ã¹ãã é¢æ°CreateProcessWãåŒã³åºãåã«ããããŒãžãã³ãã©ãŒã§ãããã»ã¹ãäœæããããã©ã¡ãŒã¿ãŒã®æååãšãä¿®æ£ãããæååãæžã蟌ãŸããé åã®ã¢ãã¬ã¹ãæž¡ããŸãã ãã³ãã©ãŒã§ã¯ãCommandLineToArgvWãåŒã³åºãããšã§è¡ããã©ã¡ãŒã¿ãŒã«åå²ãããæ§æãã¡ã€ã«ãžã®ãã¹ããããã®éã§æ±ºå®ãããä¿®æ£ãããå 容ã®äžæãã¡ã€ã«ãåãæ¹æ³ã§äœæããããã©ã¡ãŒã¿ãŒã®ãã¹ãããã«çœ®ãæããããŸãã
ããã¯
BOOL WINAPI _CreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) { BOOL result; LPWSTR buffer = NULL; if (lpCommandLine != NULL && StrStrI(lpCommandLine, L".config") != NULL) { buffer = (LPWSTR)malloc(BUFFER_SIZE); memset(buffer, 0, BUFFER_SIZE); processHandler(lpCommandLine, buffer); lpCommandLine = buffer; } result = CreateProcessWOriginal(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation); if (buffer != NULL) free(buffer); return result; }
ãããŒãžããã³ãã©ãŒ
public static void GetUpdatedConfigP(IntPtr commandLine, IntPtr newCommandLine) { var commandLineText = Marshal.PtrToStringUni(commandLine); try { int numArgs; var argArray = CommandLineToArgvW(commandLineText, out numArgs); if (argArray != IntPtr.Zero) { var pointerArray = new IntPtr[numArgs]; Marshal.Copy(argArray, pointerArray, 0, numArgs); var arguments = pointerArray.Select(x => Marshal.PtrToStringUni(x)).ToArray(); var configFile = arguments.FirstOrDefault(x => x.EndsWith(".config", StringComparison.OrdinalIgnoreCase)); var matchedSection = config.FirstOrDefault(x => configFile.ToString() .IndexOf(x.Branch, StringComparison.OrdinalIgnoreCase) >= 0); if (matchedSection != null && configFile != null && configFile.StartsWith("/config:", StringComparison.OrdinalIgnoreCase) && commandLineText.IndexOf("wcfsvchost", StringComparison.OrdinalIgnoreCase) >= 0) { configFile = configFile.Substring("/config:".Length); var content = File.ReadAllText(configFile); foreach (var replacement in matchedSection.Replacements) content = content.Replace(replacement.Find, replacement.ReplaceWith); var tempFile = Path.GetTempFileName(); MoveFileEx(tempFile, null, 4); File.WriteAllText(tempFile, content); commandLineText = commandLineText.Replace(configFile, tempFile); } } } catch { } Marshal.Copy(commandLineText.ToCharArray(), 0, newCommandLine, commandLineText.Length); }
â èšäºã®ã³ãŒãïŒå®ç§äž»çŸ©è ã«resããªãã§ãã ãã-ããã¯ããšã©ãŒåŠçããªããå€ãã®ä»®å®ããããæ¥ãã§äœãããæå°éã®äœæ¥ããŒãžã§ã³ã§ãïŒ