/* Name: Possibly a Hero Version 1.20 (Tuesday, March 27, 2018) Created: (Thu December 20, 2012) Author: tidbit Credit: Hotkeys: ctrl & w --- Quit (Main window) Description: Parse a script and get some basic information about it, such as if it's threatening or if it creates files on your harddrive. And various other things. Useful if you don't want extra files being created or you don't want a script that needs internet access. dllcall(diiiiiiiiie) Notes: Made in AHK v1.1.09.00 Unicode should be supported If you save with UTF-8 encoding. You may drag-and-drop on the main window or the file.\ ... this is not a proper code parser / interpreter ... */ #NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SendMode Input ; Recommended for new scripts due to its superior speed and reliability. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. ; #SingleInstance, force #SingleInstance, Off ; ignoreComments := 1 cmd = %1% ; Save the first command-line thing-a-ma-doo. actions:=[] ; This contains the "This script contains" list. summary:=[] ; This has the info for what lines contain what stuff. use :=[] ; This is used for the non-repeating list of descriptions. ; ------------------------------ ; ---------- MAIN GUI ---------- ; ------------------------------ Gui, +Resize +hwndHwnd +Minsize ; Gui, color, 0xF5F5F5, Gui, Font, s12 Gui, add, radio, xm checked vradio1 gCodeMode, File Gui, add, radio, x+10 yp vradio2 gCodeMode, Code Gui, add, Checkbox, x+10 yp checked vIgnoreComments gDoTheCrap, Ignore Comments? Gui, add, button, xm w90 vChoose gchoose, New File Gui, add, edit, x+5 yp+5 w250 cGreen vReadFilePath, Gui, add, edit, xm w150 cBlue ReadOnly vDisplayFileName, File: Gui, add, button, x+5 yp vopen1 gopen, Open file location Gui, add, button, x+5 yp vopen2 gopen, Run the file Gui, add, edit, xm y+5 w400 r8 ReadOnly vdisplay, Gui, add, button, xp y+0 w22 h22 gHelp, ? Gui, add, text, x+5 w250 cBlue vSummaryText, Summary: Gui, add, ListView, xm y+2 w400 r8 vMyListView, Type|Line|Text ; ------------------------------ ; ---------- CODE GUI ---------- ; ------------------------------ Gui, code: +Resize +MinSize Gui, code: font, s10, DejaVu Sans Mono Gui, code: add, edit, xm w400 r11 -wrap +WantTab +HScroll vCodeBox, %code% Gui, code: font, s12 Gui, code: add, button, xm w100 vCodeOK gDoTheCrap, OK Gui, code: add, button, x+20 yp w100 Default vCodeApply gCodeApply, Apply Gui, code: add, button, x+80 yp w100 vCodeCancel gCodeGuiClose, Cancel if (cmd!="") Gosub, GuiDropFiles Gosub, CodeMode Gui, Show,,Possibly a Hero ; Gosub, DoTheCrap Return esc:: guiEscape: GuiClose: Exitapp Return ~^w:: If (WinActive("AHK_ID" Hwnd)) Exitapp Return open: Gui, Submit, NoHide Gui, 1: Default if (A_GuiControl="open1" && FileExist(FilePath)) Run, %FilePath% else if (A_GuiControl="open2" && FileExist(File)) Run, %File% else Msgbox, Generic vague error message. Return help: MsgBox, 64, Disclaimer, (LTrim Join`s This system is not 100`% accurate. Due to the systems used, it only detects simple information and potentially harmful stuff. It is best that you review the summary or open the file in an editor and determine if the program is harmful or not and if you want to run the file under question. ) Return Choose: Gui, submit, NoHide if (Radio1=1) { FileSelectFile, file, 3,, Select a file to analyze. if (errorlevel=1) Return SplitPath, file, FileName, FilePath ; Used for the Run buttons GuiControl,, ReadFilePath, %file% GuiControl,, DisplayFileName, %FileName% Gosub, DoTheCrap } else { if (CodeOpen!=1) GuiControl, Code:, CodeBox, %Code% GuiControl,, ReadFilePath, Raw Code GuiControl,, DisplayFileName, Raw Code Gui, code: show,, Raw Code - Possibly a Hero CodeOpen:=1 } Return GuiDropFiles: if (cmd!="") file:=cmd else file:=A_GuiEvent if (inStr(file, "`n")) ; extract only the first item and remove all unwanted spaces/newlines file:=trim(SubStr(file, 1, inStr(file, "`n")-1), "`r`n `t") SplitPath, file, FileName, FilePath ; Used for the Run buttons GuiControl,, Radio1, 1 GuiControl,, ReadFilePath, %file% GuiControl,, DisplayFileName, %FileName% Gosub, CodeMode Gosub, DoTheCrap Return CodeGuiClose: Gui, Code: Cancel CodeOpen:=0 Return CodeApply: ; update the code stuff without closing the editor window Gui, Code: submit, NoHide CodeApply:="ApplyPressed" Gosub, DoTheCrap Return GuiSize: if (A_EventInfo=1) ; The window has been minimized. No action needed. return GuiControlGet, C, Pos, MyListView ; all buttons will be this height, but I also need this width. GuiControl, Move, Display, % "w" A_GuiWidth-18 GuiControl, Move, MyListView, % "w" A_GuiWidth-18 " h" A_GuiHeight-(CY+6) Return CodeGuiSize: if (A_EventInfo=1) ; The window has been minimized. No action needed. return GuiControlGet, C, Pos, CodeCancel ; all buttons will be this height, but I also need this width. GuiControl, Code: Move, CodeOK, % "y" A_GuiHeight-(CH+6) GuiControl, Code: Move, CodeApply, % "y" A_GuiHeight-(CH+6) GuiControl, Code: Move, CodeCancel, % "x" A_GuiWidth-(CW+6) " y" A_GuiHeight-(CH+6) GuiControl, Code: Move, CodeBox, % "w" A_GuiWidth-18 " h" A_GuiHeight-(CH+18) Return CodeMode: Gui, Submit, NoHide if (radio1=1) { Gui, Code: Cancel CodeOpen:=0 GuiControl,, Choose, New File GuiControl, enable, DisplayFileName GuiControl, enable, ReadFilePath GuiControl, enable, Open1 GuiControl, enable, Open2 GuiControl,, ReadFilePath, %file% GuiControl,, DisplayFileName, %FileName% } else { ; if (CodeBox="") GuiControl, Code:, CodeBox, %code% GuiControl,, Choose, Edit Code GuiControl, disable, DisplayFileName GuiControl, disable, ReadFilePath GuiControl, disable, Open1 GuiControl, disable, Open2 GuiControl,, ReadFilePath, Raw Code GuiControl,, DisplayFileName, Raw Code } Return DoTheCrap: Gui, Submit, NoHide Gui, Code: Submit, NoHide Gui, 1: Default ; only hide the code window if Apply *wasn't* clicked if (CodeApply!="ApplyPressed") { Gui, Code: Cancel CodeOpen:=0 } else CodeApply:="" ; what do use as the code source, a file or the Raw Code. if (Radio1=1 && FileExist(ReadFilePath)) FileRead, code, %ReadFilePath% ; This uses the inputbox, which allows you to paste in your path without needing the dialogue. else if (Radio2=1) code:=CodeBox else Return LV_Delete() ; Clear the ListView out:=scanScript(code) ; Msgbox % st_printArr(out) warnList:="" for k, v in out.Actions warnList.="* " v "`n" if (warnList="") warnList:="Hooray! This file does nothing to worry about. :)" Sort, warnList ; GuiControl,, display, | GuiControl,, display, % "This file:`n" trim(warnList, "`r`n") ; update the Summary ListView for line, text in out.Summary { LV_Add("", text.category, text.line, trim(text.code)) ; Insert the rows and trim off all the indentation that the line might have. } LV_ModifyCol() LV_ModifyCol(1, "Sort") LV_ModifyCol(2, "AutoHdr Integer") GuiControl,, SummaryText, % "Summary (" LV_GetCount() "):" return scanScript(inCode, ignoreComments:=1, ignoreContSec:=0) { actions:=[] ; a list of actions that inCode might contain. column 1 of scans[] summary:=[] ; summary of everything. line number, category (column 2 of scans[]) and the line of code. use :=[] ; Keep track of what was already added to actions[], so we don't get dupes. ; regex detection rules. ; Each item/option/rule is separated by a |. ; [short description, category, v3=regex] scans:=[["Modifies System" , "System" , "^(?:" "Process,?\s*Priority|MaxMem|InstallMouseHook|UseHook|InstallKeybdHook" ")"] , ["Registry" , "Registry" , "^(?:" "RegRead|RegWrite|RegDelete|HKEY_LOCAL_MACHINE|HKLM|HKEY_USERS|HKU|HKEY_CURRENT_USER|HKCU|HKEY_CLASSES_ROOT|HKCR|HKEY_CURRENT_CONFIG|HKCC REG_SZ|REG_EXPAND_SZ|REG_MULTI_SZ|REG_DWORD|REG_BINARY" ")"] , ["!!Possible Danger!!", "!!Sketchy!!", "%[\w$#@]+%\s*\(|DllCall|\bShutdown|BlockInput|\.Call\("] , ["Internet access" , "Internet" , "\.Navigate|Web.*Request|HTTP.*Request|UrlDownloadToFile|\w*Explorer\.App"] , ["Creates on disk" , "Create" , "^(?:" "FileAppend|FileCopy|FileCopyDir|FileCreateDir|FileCreateShortcut" ")"] , ["Writes on disk" , "Write" , "FileAppend|RegWrite|IniDelete|\.Write|\.RawWrite"] , ["Deletes on disk" , "Delete" , "^(?:" "FileDelete" ")"] , ["Reads on disk" , "Read" , "Fileread|RegRead|IniRead|\.Read\b|\.ReadLine\b|\.RawRead\b"] , ["Mouse hijack" , "Mouse" , "^(?:" "MouseClick|MouseClickDrag|MouseMove|(?=1 && LoopField=")") ? -1 : 0 if (ignoreComments=1) { if (SubStr(LoopField,1,1)=";") Continue ignore+=(SubStr(LoopField,1,2)="/*") ? 1 : (ignore>=1 && inStr(LoopField, "*/")) ? -1 : 0 } if (ignore>=1) Continue for k, v in scans { ; v1 = short description, v2=category, v3=regex if (RegExMatch(LoopField, "i)" v[3], mmm)) { ttt:=v[2] ; crude check if certain things are inside of quotes or not if (RegExMatch(LoopField, "i)" """.*?" mmm ".*""")) break ; if ttt not in %skipTheseCategoriesInsideOfStrings% ; if (instr(SubStr(LoopField, 1, pos) , """")>0 ; && instr(SubStr(LoopField, pos+len), """")>0) ; break if (use[k]!=1) ; Determines if we have done this section yet. if not add the message to the array. actions.insert(v[1]) use[k]:=1 summary.push({Line:cLine, Category:v[2], Code:LoopField}) ; break } } } return {Actions:actions, Summary:summary} } st_printArr(array, depth=5, indentLevel="") { for k,v in Array { list.= indentLevel "[" k "]" if (IsObject(v) && depth>1) list.="`n" st_printArr(v, depth-1, indentLevel . " ") else list.=" => " v list:=rtrim(list, "`r`n `t") "`n" } return rtrim(list) }