Skip to content

Instantly share code, notes, and snippets.

@iglezz
Last active March 6, 2023 19:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iglezz/ba6442c57b48aab0d818411e8485a9ba to your computer and use it in GitHub Desktop.
Save iglezz/ba6442c57b48aab0d818411e8485a9ba to your computer and use it in GitHub Desktop.
NSIS hostsfile blocker
RequestExecutionLevel user
AutoCloseWindow false
ShowInstDetails show
InstallColors /windows
SetFont "Fira Code" 9
SetFont "Consolas" 9
!define DEBUG
!include "x64.nsh"
!include "LogicLib.nsh"
!include "hostsblock.nsh"
Section Prepare
SetDetailsView hide
SetDetailsPrint none
InitPluginsDir
${IfThen} ${RunningX64} ${|} ${DisableX64FSRedirection} ${|}
StrCpy $0 '$SYSDIR\drivers\etc\hosts'
StrCpy $1 '$EXEDIR\hosts.example.txt'
StrCpy $2 '$EXEDIR\hosts.modified.txt'
CopyFiles /SILENT $0 $1
FileOpen $3 $1 A
FileSeek $3 0 END
FileWrite $3 '## 0.0.0.0 www.total-uninstall.com # $\n'
FileWrite $3 '#'
FileClose $3
CopyFiles /SILENT $1 $2
SetDetailsPrint listonly
SectionEnd
Section Check_IsWriteable
FileOpen $3 $2 A
${If} ${Errors}
DetailPrint 'FileOpen ERROR !'
SetDetailsView show
Abort
${EndIf}
FileClose $3
SectionEnd
Section Test
DetailPrint -------------------------------
${hostsfile_BlockHost} $2 'martau.com'
${hostsfile_BlockHost} $2 'www.martau.com'
${hostsfile_BlockHost} $2 'www.total-uninstall.com'
${hostsfile_BlockHost} $2 'total-uninstall.com'
DetailPrint -------------------------------
nsExec::ExecToLog /OEM '$SYSDIR\fc.exe /l /c /n "$1" "$2" '
DetailPrint -------------------------------
SectionEnd
Section
SetDetailsView show
SectionEnd
!ifndef __hostsblock__nsh__
!define __hostsblock__nsh__
!include "Util.nsh"
!include "LogicLib.nsh"
!include "StrFunc.nsh"
${Using:StrFunc} StrLoc
${Using:StrFunc} StrRep
${Using:StrFunc} StrTrimNewLines
!define _DebugPrint `!insertmacro _DebugPrint`
!macro _DebugPrint MESSAGE
!ifdef DEBUG
DetailPrint '${MESSAGE}'
!endif
!macroend
!define hostsfile_ValidateIPv4Addr `!insertmacro hostsfile_ValidateIPv4Addr`
!macro hostsfile_ValidateIPv4Addr RESULT IPADDR
Push "${IPADDR}"
${CallArtificialFunction} hostsfile_ValidateIPv4Addr_macro
Pop ${RESULT}
!macroend
!macro hostsfile_ValidateIPv4Addr_macro
Exch $0 ; IP str
Push $1 ; IP len
Push $2 ; loop counter
Push $3 ; IP dots counter
Push $4 ; IP octet
Push $5 ; getchar
StrLen $1 $0
IntCmp $1 7 0 hostsfile_ValidateIPv4Addr_error 0
IntCmp $1 15 0 0 hostsfile_ValidateIPv4Addr_error
StrCpy $2 0
StrCpy $3 0
StrCpy $4 ''
hostsfile_ValidateIPv4Addr_loop:
StrCpy $5 $0 1 $2
StrCmp $5 '.' 0 +7
IntOp $3 $3 + 1
IntCmp $3 3 0 0 hostsfile_ValidateIPv4Addr_error
StrCmp $4 '' hostsfile_ValidateIPv4Addr_error 0
IntCmp $4 255 0 0 hostsfile_ValidateIPv4Addr_error
StrCpy $4 ''
Goto +4 ; continueloop
StrCmp $5 '0' +2 0
IntCmp $5 '1' 0 hostsfile_ValidateIPv4Addr_error 0
StrCpy $4 $4$5
IntOp $2 $2 + 1
IntCmp $2 $1 hostsfile_ValidateIPv4Addr_loop_exit hostsfile_ValidateIPv4Addr_loop
hostsfile_ValidateIPv4Addr_loop_exit:
IntCmp $3 3 0 hostsfile_ValidateIPv4Addr_error hostsfile_ValidateIPv4Addr_error
IntCmp $4 255 0 0 hostsfile_ValidateIPv4Addr_error
; hostsfile_ValidateIPv4Addr_ok
StrCpy $0 1
Goto hostsfile_ValidateIPv4Addr_done
hostsfile_ValidateIPv4Addr_error:
StrCpy $0 0
hostsfile_ValidateIPv4Addr_done:
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Exch $0
!macroend
!define hostsfile_BlockHost `!insertmacro hostsfile_BlockHost `
!macro hostsfile_BlockHost HOSTSFILE HOSTNAME
Push '${HOSTNAME}'
Push '${HOSTSFILE}'
${CallArtificialFunction} hostsfile_BlockHost_macro
!macroend
!define hostsfile_BlockHost_macro_GetChunk `!insertmacro hostsfile_BlockHost_macro_GetChunk`
!macro hostsfile_BlockHost_macro_GetChunk OUTVAR STR STARTPOS
StrCpy ${OUTVAR} ${STARTPOS} ; start pos, reuse OUTVAR for counter
; loop:
IntOp ${OUTVAR} ${OUTVAR} + 1
StrCpy ${_VTMP} ${STR} 1 ${OUTVAR} ; getchar
StrCmp ${_VTMP} ' ' 0 -2
; exitloop:
IntOp ${_VTMP} ${OUTVAR} - ${STARTPOS} ; out_var len
StrCpy ${OUTVAR} ${STR} ${_VTMP} ${STARTPOS} ; save out_var
!macroend
!define hostsfile_BlockHost_macro_Write `!insertmacro hostsfile_BlockHost_macro_Write`
!macro hostsfile_BlockHost_macro_Write H STR
${_DebugPrint} 'Write [${STR}]'
FileWrite ${H} $3
!macroend
!define hostsfile_BlockHost_macro_WriteAndContinue `!insertmacro hostsfile_BlockHost_macro_WriteAndContinue`
!macro hostsfile_BlockHost_macro_WriteAndContinue H STR
${hostsfile_BlockHost_macro_Write} ${H} $3
${Continue}
!macroend
; LogicLib Function
!define SingleHostInString `"" SingleHostInString`
!macro _SingleHostInString _a _b _t _f
; _b == inputstring
${_DebugPrint} 'single/multi-host string?'
StrLen ${_VTMP} ${_VIPSTR}
IntOp ${_VTMP} ${_VTMP} + ${_VIPPOS}
StrCpy ${_VTMP} `${_b}` '' ${_VTMP}
${_DebugPrint} ' cut ipaddr: [${_VTMP}]'
${StrLoc} ${_VTMP2} ${_VTMP} '#' >
StrCmp ${_VTMP2} '' +2
StrCpy ${_VTMP} ${_VTMP} ${_VTMP2}
${_DebugPrint} ' cut comment:[${_VTMP}]'
${StrRep} ${_VTMP} ${_VTMP} ' $1 ' ''
${_DebugPrint} ' cut host: [${_VTMP}]'
${StrRep} ${_VTMP} ${_VTMP} ' ' ''
${_DebugPrint} ' cut spaces: [${_VTMP}]'
${_DebugPrint} ' single if "${_VTMP}"==""'
StrCmp ${_VTMP} '' `${_t}` `${_f}`
!macroend
; LogicLib Function
!define StringIsCommented `"" StringIsCommented`
!macro _StringIsCommented _a _b _t _f
; _b == inputstring
${_DebugPrint} ' string is commented?'
StrCpy ${_VTMP} `${_b}` ${_VIPPOS}
${StrLoc} ${_VTMP} ${_VTMP} '#' >
StrCmp ${_VTMP} '' `${_f}` `${_t}`
!macroend
!macro hostsfile_BlockHost_macro
!define _VIPSTR $5
!define _VIPPOS $6
!define _VHOSTPOS $7
!define _VTMP $8
!define _VTMP2 $9
Exch $0 ; hostsfile
Exch 1
Exch $1 ; host
Push $2 ; temp hostsfile
Push $3 ; readstr
Push $4 ; readstr prep. for parsing
Push $5 ;
Push $6 ;
Push $7 ;
Push $8 ;
Push $9 ;
Push $R0 ; hostsfile handle
Push $R1 ; flag:modified
Push $R2 ; temp hostsfile handle
ClearErrors
StrCpy $R1 0
StrCpy $2 '$PLUGINSDIR\hosts.tmp'
FileOpen $R2 $2 W
${_DebugPrint} '-------------------------------------'
${_DebugPrint} 'Block host: $1'
${If} ${FileExists} $0
FileOpen $R0 $0 R
${_DebugPrint} 'Read/Write...'
${Do}
FileRead $R0 $3
${IfThen} ${Errors} ${|} ${ExitDo} ${|}
${_DebugPrint} 'Read [$3]'
${StrTrimNewLines} $4 $3
${StrRep} $4 ' $4 ' '$\t' ' '
${IfThen} $R1 == 1 ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
; find host
${StrLoc} ${_VHOSTPOS} $4 ' $1 ' >
${IfThen} ${_VHOSTPOS} == '' ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
${_DebugPrint} 'host found..'
; find ipaddr
${StrLoc} ${_VIPPOS} $4 '.' >
${IfThen} ${_VIPPOS} == '' ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
${IfThen} ${_VIPPOS} >= ${_VHOSTPOS} ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
; ipaddr capture & validate
IntOp ${_VIPPOS} ${_VIPPOS} - 1
StrCpy ${_VTMP} $4 1 ${_VIPPOS}
StrCmp ${_VTMP} ' ' +2 0
StrCmp ${_VTMP} '#' 0 -3
IntOp ${_VIPPOS} ${_VIPPOS} + 1
${hostsfile_BlockHost_macro_GetChunk} ${_VIPSTR} $4 ${_VIPPOS}
${hostsfile_ValidateIPv4Addr} ${_VTMP} ${_VIPSTR}
${IfThen} ${_VTMP} = 0 ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
${_DebugPrint} 'ipaddr ok..'
; look for # between ipaddr pos & host pos
IntOp ${_VTMP} ${_VHOSTPOS} - ${_VIPPOS}
StrCpy ${_VTMP} $4 ${_VTMP} ${_VIPPOS}
${StrLoc} ${_VTMP} ${_VTMP} '#' > ; unwanted # pos
${IfThen} ${_VTMP} != '' ${|} ${hostsfile_BlockHost_macro_WriteAndContinue} $R2 $3 ${|}
${_DebugPrint} 'host ok..'
${_DebugPrint} 'Analyze [$4]'
${If} ${_VIPSTR} == '0.0.0.0'
${_DebugPrint} 'Good IP (0.0.0.0)..'
${IfNot} ${StringIsCommented} $4
${_DebugPrint} '..uncommented out string -> pass'
${_DebugPrint} 'writestr[$3]'
StrCpy $R1 1 ; set flag:modified
${ElseIf} ${SingleHostInString} $4
${_DebugPrint} '..commented out single-host string -> uncomment string'
StrCpy ${_VTMP} $3 ${_VIPPOS}
${StrRep} ${_VTMP} ${_VTMP} '#' ''
StrCpy ${_VIPPOS} $3 '' ${_VIPPOS}
StrCpy $3 ${_VTMP}${_VIPPOS}
StrCpy $R1 1 ; set flag:modified
${_DebugPrint} 'writestr[$3]'
${Else}
${_DebugPrint} '..commented out multi-host string -> pass, set append flag'
${_DebugPrint} 'writestr[$3]'
${EndIf}
${ElseIfNot} ${StringIsCommented} $4
${_DebugPrint} 'Bad IP (${_VIPSTR})..'
${If} ${SingleHostInString} $4
${_DebugPrint} '..uncommented single-host string ->'
StrCpy $3 '# $30.0.0.0 $1$\r$\n'
${_DebugPrint} 'writestr[$3]'
StrCpy $R1 1 ; set flag:modified
${Else}
${_DebugPrint} '..uncommented multi-host string ->'
${_DebugPrint} '-> backup'
StrCpy $4 '# $3'
${_DebugPrint} '-> remove host from string'
${StrLoc} ${_VTMP} $3 '#' > ; # pos
StrCmp ${_VTMP} '' 0 +2 ; if no # pos...
StrLen ${_VTMP} $3 ; st to strlen
StrCpy ${_VTMP2} $3 ${_VTMP} ; copy w/o comment
${StrRep} ${_VTMP2} '${_VTMP2} ' ' $1 ' ' ' ; repl
StrCpy ${_VTMP} $3 '' ${_VTMP} ; copy comment
StrCpy $3 ${_VTMP2}${_VTMP} ; concat backup+modded
${_DebugPrint} 'backup [$4]'
${_DebugPrint} 'modded [$3]'
StrCpy $3 $4$3
${_DebugPrint} '-> set append flag'
; flag:modified is not set -> append record to the end of file
${EndIf}
${Else}
${_DebugPrint} 'commented out string -> pass, set append flag'
${EndIf}
${hostsfile_BlockHost_macro_Write} $R2 $3
${Loop}
; file must end with \r or \n
FileSeek $R0 -1 END
FileRead $R0 $3
${If} $3 == '$\r'
${OrIf} $3 == '$\n'
${OrIf} $3 == '' ; hostsfile is empty
StrCpy $3 ''
${Else}
${_DebugPrint} 'Append \r\n'
FileWrite $R2 '$\r$\n'
${EndIf}
FileClose $R0
${EndIf}
${If} $R1 == 0
${_DebugPrint} 'Append [$30.0.0.0 $1]'
FileWrite $R2 '0.0.0.0 $1$\r$\n'
${EndIf}
FileClose $R2
SetDetailsPrint none
CopyFiles /SILENT $2 $0
Delete $2
SetDetailsPrint lastused
Pop $R2
Pop $R1
Pop $R0
Pop $9
Pop $8
Pop $7
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
!undef _VIPPOS
!undef _VIPSTR
!undef _VHOSTPOS
!undef _VTMP
!undef _VTMP2
!macroend
!endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment