/*** * Module to manipulate windows .lnk files * modified from: https://github.com/nyaosorg/go-windows-shortcut * Typical usage: //import shortcut "InfectShortcuts/Modules/WindowsShortcutFull" //main // read shortcut data Description, workingDir, targetPath, Arguments, Icon, err := shortcut.Read("C:\\Users\\User\\Desktop\\vlc.lnk") // create new OR update existing shortcut err := shortcut.Make("C:\\Users\\User\\Desktop\\vlc.lnk", newDescription, newWorkingDir, newTarget, newArgs, newIcon) // create VB script to generate/update a .lnk file (useful for debugging) shortcut.CreateVBS("C:\\Users\\User\\Desktop\\vlc.lnk", newTarget, newArgs, newWorkingDir, newDescription, newScriptName) */ package WindowsShortcutFull import ( "bytes" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" ) // _WShell is the OLE Object for "WScript.Shell" type _WShell struct { agent *ole.IUnknown dispatch *ole.IDispatch } // _NewWShell creates OLE Object for "WScript.Shell". func _NewWShell() (*_WShell, error) { agent, err := oleutil.CreateObject("WScript.Shell") if err != nil { return nil, err } dispatch, err := agent.QueryInterface(ole.IID_IDispatch) if err != nil { agent.Release() return nil, err } return &_WShell{agent: agent, dispatch: dispatch}, nil } // Close releases the OLE Object for "WScript.Shell". func (wsh *_WShell) Close() { wsh.dispatch.Release() wsh.agent.Release() } // Read reads the data of shortcut file. `path` must be absolute path. func (wsh *_WShell) Read(path string) (description string, workingdir string, targetpath string, arguments string, icon string, err error) { shortcut, err := oleutil.CallMethod(wsh.dispatch, "CreateShortCut", path) if err != nil { return "", "", "", "", "", err } shortcutDis := shortcut.ToIDispatch() defer shortcutDis.Release() Description, err := oleutil.GetProperty(shortcutDis, "Description") if err != nil { return "", "", "", "", "", err } workingDir, err := oleutil.GetProperty(shortcutDis, "WorkingDirectory") if err != nil { return "", "", "", "", "", err } targetPath, err := oleutil.GetProperty(shortcutDis, "TargetPath") if err != nil { return "", "", "", "", "", err } Arguments, err := oleutil.GetProperty(shortcutDis, "Arguments") if err != nil { return "", "", "", "", "", err } Icon, err := oleutil.GetProperty(shortcutDis, "IconLocation") if err != nil { return "", "", "", "", "", err } return Description.ToString(), workingDir.ToString(), targetPath.ToString(), Arguments.ToString(), Icon.ToString(), err } func _read(path string) (Description string, workingDir string, targetPath string, Arguments string, Icon string, err error) { path, err = filepath.Abs(path) if err != nil { return "", "", "", "", "", err } wsh, err := _NewWShell() if err != nil { return "", "", "", "", "", err } defer wsh.Close() return wsh.Read(path) } // Make makes a shortcut file. `to` must be absolute path. func (wsh *_WShell) Make(to string, newDescription string, newWorkingDir string, newTarget string, newArgs string, newIcon string) error { shortcut, err := oleutil.CallMethod(wsh.dispatch, "CreateShortCut", to) if err != nil { return err } shortcutDis := shortcut.ToIDispatch() defer shortcutDis.Release() _ = oleutil.MustPutProperty(shortcutDis, "TargetPath", newTarget) if err != nil { return err } _, err = oleutil.PutProperty(shortcutDis, "WorkingDirectory", newWorkingDir) if err != nil { return err } _, err = oleutil.PutProperty(shortcutDis, "Arguments", newArgs) if err != nil { return err } _, err = oleutil.PutProperty(shortcutDis, "Description", newDescription) if err != nil { return err } _, err = oleutil.PutProperty(shortcutDis, "IconLocation", newIcon) if err != nil { return err } _, err = oleutil.CallMethod(shortcutDis, "Save") return err } func _make(to string, newDescription string, newWorkingDir string, newTarget string, newArgs string, newIcon string) error { to, err := filepath.Abs(to) if err != nil { return err } wsh, err := _NewWShell() if err != nil { return err } defer wsh.Close() return wsh.Make(to, newDescription, newWorkingDir, newTarget, newArgs, newIcon) } func CreateVBS(linkName string, target string, arguments string, directory string, description string, destination string) { var scriptTxt bytes.Buffer scriptTxt.WriteString("option explicit\n\n") scriptTxt.WriteString("sub CreateShortCut()\n") scriptTxt.WriteString("dim objShell, strDesktopPath, objLink\n") scriptTxt.WriteString("set objShell = CreateObject(\"WScript.Shell\")\n") scriptTxt.WriteString("set objLink = objShell.CreateShortcut( \"") scriptTxt.WriteString(linkName) scriptTxt.WriteString(".lnk\")\n") scriptTxt.WriteString("objLink.Arguments = \"") scriptTxt.WriteString(arguments) scriptTxt.WriteString("\"\n") scriptTxt.WriteString("objLink.Description = \"") scriptTxt.WriteString(description) scriptTxt.WriteString("\"\n") scriptTxt.WriteString("objLink.TargetPath = \"") scriptTxt.WriteString(target) scriptTxt.WriteString("\"\n") scriptTxt.WriteString("objLink.WindowStyle = 1\n") scriptTxt.WriteString("objLink.WorkingDirectory = \"") scriptTxt.WriteString(directory) scriptTxt.WriteString("\"\n") scriptTxt.WriteString("objLink.Save\nend sub\n\n") scriptTxt.WriteString("call CreateShortCut()") fmt.Print(scriptTxt.String()) filename := fmt.Sprintf("lnkTo%s.vbs", destination) ioutil.WriteFile(filename, scriptTxt.Bytes(), 0777) cmd := exec.Command("wscript", filename) err := cmd.Run() if err != nil { fmt.Println(err) } cmd.Wait() os.Remove(filename) return }