cli

package
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2025 License: GPL-3.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const SQL_INSERT_HISTORY = `INSERT INTO history (executable, arguments, environment) VALUES (?, ?, ?)`
View Source
const SQL_INSERT_OUTPUT = `INSERT INTO output (history_id, stdout, stderr, exitcode) VALUES (?, ?, ?, ?)`
View Source
const SQL_UPSERT_OUTPUT = `` /* 197-byte string literal not displayed */
View Source
const VERSION = "2025.02.17"

Variables

View Source
var DocCmd = &cobra.Command{
	Use:   "doc",
	Short: fmt.Sprintf("Build documentation under %s", documentationBasepath),
	Long:  fmt.Sprintf(`Generate documentation for command line usage under %s`, documentationBasepath),
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		CallPersistentPreRun(cmd, args)
	},
	Run: func(cmd *cobra.Command, args []string) {
		err := os.MkdirAll(documentationBasepath, 0750)
		if err != nil {
			log.Fatal(err)
		}

		err = doc.GenMarkdownTree(cmd.Root(), documentationBasepath)
		if err != nil {
			log.Fatal(err)
		}
	},
}
View Source
var ExecuteCmd = &cobra.Command{
	Use:                "execute",
	Short:              "Wrap and collect executing command and resulting output",
	Long:               "Provided with a command to execute, record it and the returned output from execution (including exitcode)",
	DisableFlagParsing: true,
	Run: func(_ *cobra.Command, args []string) {
		executable := args[0]

		db, err := util.CreateSQLite3Database()
		if db != nil {
			defer db.Close()
		}
		if err != nil {
			fmt.Printf("error creating database: %v", err)
			return
		}

		arguments := strings.Join(args[1:], " ")

		envVars := os.Environ()
		environment := strings.Join(envVars, ":")

		result, err := db.Exec(SQL_INSERT_HISTORY, executable, arguments, environment)
		if err != nil {
			fmt.Printf("error inserting record: %v", err)
			return
		}
		historyId, err := result.LastInsertId()
		if err != nil {
			fmt.Printf("error obtaining historyId: %v", err)
			return
		}

		cmd := exec.Command(executable, args[1:]...)

		stdoutPipe, err := cmd.StdoutPipe()
		if err != nil {
			log.Fatalf("Failed to create stdout pipe: %v", err)
		}

		stderrPipe, err := cmd.StderrPipe()
		if err != nil {
			log.Fatalf("Failed to create stderr pipe: %v", err)
		}

		ptmx, err := pty.Start(cmd)
		if err != nil {
			log.Fatalf("Failed to start pty: %v", err)
		}
		defer ptmx.Close()

		var stdoutOutput, stderrOutput string

		go func() {
			buf := make([]byte, 1024)
			for {
				n, err := ptmx.Read(buf)
				if err != nil {
					break
				}

				os.Stdout.Write(buf[:n])
				stdoutOutput += string(buf[:n])
			}
		}()

		go func() {

			scanner := bufio.NewScanner(os.Stdin)

			for scanner.Scan() {

				_, err = db.Exec(SQL_UPSERT_OUTPUT, historyId, stdoutOutput, stderrOutput, 99)
				if err != nil {
					fmt.Printf("error inserting record: %v", err)
					return
				}

				stdoutOutput = ""
				stderrOutput = ""

				commandLine := scanner.Text()
				args := strings.Split(commandLine, " ")
				result, err := db.Exec(SQL_INSERT_HISTORY, args[0], strings.Join(args[1:], " "), "")
				if err != nil {
					fmt.Printf("error inserting record: %v", err)
					return
				}
				historyId, err = result.LastInsertId()
				if err != nil {
					fmt.Printf("error obtaining historyId: %v", err)
					return
				}

				if _, err := io.WriteString(ptmx, commandLine+"\n"); err != nil {
					log.Fatalf("Failed to write to pty: %v", err)
				}
			}
		}()

		go func() {
			stdoutScan := bufio.NewScanner(stdoutPipe)
			for stdoutScan.Scan() {
				data := stdoutScan.Text() + "\n"
				os.Stdout.WriteString(data)
				stdoutOutput += data
			}
		}()

		go func() {
			stderrScan := bufio.NewScanner(stderrPipe)
			for stderrScan.Scan() {
				data := stderrScan.Text() + "\n"
				os.Stderr.WriteString(data)
				stderrOutput += data
			}
		}()

		var exitcode = -1

		if err := cmd.Wait(); err != nil {
			if exitError, ok := err.(*exec.ExitError); ok {
				exitcode = exitError.ExitCode()
				fmt.Fprintln(os.Stderr, exitError.Stderr)
			} else {
				err := fmt.Sprintf("Error waiting for command: %v", err)
				fmt.Fprintln(os.Stderr, err)
				stderrOutput += err
				exitcode = cmd.ProcessState.ExitCode()
			}
		} else {
			exitcode = cmd.ProcessState.ExitCode()
		}

		_, err = db.Exec(SQL_UPSERT_OUTPUT, historyId, stdoutOutput, stderrOutput, exitcode)
		if err != nil {
			fmt.Printf("error inserting record: %v", err)
			return
		}
	},
}
View Source
var NoteCmd = &cobra.Command{
	Use:   "note",
	Short: "Record history as notes for a project",
	Long:  `Having used the 'execute' command to record execution, record the results to a project`,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		CallPersistentPreRun(cmd, args)
		config.Load()

		if rootConfig.Setting.Debug {
			util.Logger.SetReportCaller(true)
			config.Setting.Print()
		}
	},
	Run: func(cmd *cobra.Command, args []string) {

		if !config.Setting.Local {
			if config.Setting.SSHKey == "" || config.Setting.SSHUser == "" || config.Setting.IP == "" || config.Setting.Port == "" {
				util.Logger.Error("When not in local mode - sshkey, sshuser, ip, and port are all required")
				os.Exit(1)
			}

			if config.Setting.SSHUser != "" {
				usernamePlain, _, projectId := util.GetUsernameProjectIfPresent(config.Setting.SSHUser)
				config.Setting.SSHUser = usernamePlain

				if config.Setting.ProjectId == "" {
					config.Setting.ProjectId = projectId
				}
			}
		}

		if config.Setting.ProjectId == "" {
			util.Logger.Error("project id is required")
			os.Exit(2)
		}

		if config.Setting.Export {

			if config.Setting.Local {
				_ = app.SetupPocketbase(config.Setting.StoragePath)

				data, err := database.GetNotesAsMarkdown(config.Setting.ProjectId)
				if err != nil {
					util.Logger.Error(fmt.Sprintf("error reading note: %v", err))
					os.Exit(3)
				}

				fmt.Println(string(data))

			} else {
				err := util.ReadNote(config.Setting.SSHUser, config.Setting.SSHKey, config.Setting.ProjectId, config.Setting.IP, config.Setting.Port)
				if err != nil {
					util.Logger.Error(fmt.Sprintf("error reading note: %v", err))
					os.Exit(3)
				}
			}
		} else {
			db, err := util.CreateSQLite3Database()
			if db != nil {
				defer db.Close()
			}
			if err != nil {
				util.Logger.Error(fmt.Sprintf("error creating database: %v", err))
				os.Exit(3)
			}

			historySelection, err := util.GetHistory(db, 2000)
			if err != nil {
				util.Logger.Error(fmt.Sprintf("error querying database: %v", err))
				os.Exit(3)
			}

			var options []huh.Option[util.HistorySelection]
			var selectedHistoryItems []util.HistorySelection
			for _, cmd := range historySelection {
				options = append(options, huh.NewOption(fmt.Sprintf("%d] %s", cmd.Id, cmd.Command), cmd))
			}
			var noteTitle = ""
			var noteComment = ""

			_ = tea.ClearScreen()

			form := huh.NewForm(
				huh.NewGroup(
					huh.NewInput().
						Title("Title").
						Placeholder("The title for the note").
						Value(&noteTitle).
						Description("The contents of the following commands/arguments + output if any will be used to create the note"),
					huh.NewText().
						Title("Comment").
						Placeholder("Any context you wish to add for the command('s) that were executed").
						CharLimit(5000).
						Value(&noteComment).
						WithHeight(5),
					huh.NewMultiSelect[util.HistorySelection]().
						Title("Select 1..N to create a new note").
						Description("If a command starts with `[!]` - its exitcode was none 0").
						Height(25).
						Value(&selectedHistoryItems).
						Key("Id").
						Options(options...),
				),
			).WithTheme(huh.ThemeCharm())

			if err := form.Run(); err != nil {
				if form.State == huh.StateAborted {
					util.Logger.Error("aborting note selection/upload")
					os.Exit(0)
				}

				util.Logger.Error(fmt.Sprintf("error querying database: %v", err))
				os.Exit(4)
			}

			sort.Slice(selectedHistoryItems, func(x, y int) bool {
				return selectedHistoryItems[x].Id > selectedHistoryItems[y].Id
			})

			var ids []int
			for _, c := range selectedHistoryItems {
				ids = append(ids, c.Id)
			}

			note, err := util.GetNote(db, ids, noteTitle, noteComment)
			if err != nil {
				util.Logger.Error(fmt.Sprintf("error querying database: %v", err))
				os.Exit(4)
			}

			if config.Setting.Local {
				_ = app.SetupPocketbase(config.Setting.StoragePath)

				err := database.AddNote(config.Setting.ProjectId, noteTitle, note)

				if err != nil {
					util.Logger.Error(fmt.Sprintf("error saving note: %v", err))
					os.Exit(5)
				}
			} else {

				note = fmt.Sprintf("%s\r\n%s", noteTitle, note)

				err = util.SendNote(note, config.Setting.SSHUser, config.Setting.SSHKey, config.Setting.ProjectId, config.Setting.IP, config.Setting.Port)
				if err != nil {
					util.Logger.Error(fmt.Sprintf("error sending note: %v", err))
					os.Exit(5)
				}
			}
		}
	},
}
View Source
var RootCmd = &cobra.Command{
	Version: VERSION,
	Use:     "hexer",
	Short:   "A place to organize HTB activities",
	Long:    "Leverage SSH or just stay local - an organize those HTB labs",
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		CallPersistentPreRun(cmd, args)
		config.Load()

		logger := util.SetLogger(fmt.Sprintf("%s/system.log", config.Setting.LogBasepath))

		if logger == nil {
			logger := util.SetLogger("./system.log")

			if logger == nil {
				err := cmd.Help()

				if err != nil {
					log.Fatal(err)
					os.Exit(1)
				}

				os.Exit(0)
			}
		}

		if config.Setting.Debug {
			config.Setting.Print()
		}
	},
	Run: func(cmd *cobra.Command, args []string) {

		if len(args) == 0 {
			err := cmd.Help()

			if err != nil {
				util.Logger.Error(err)
				os.Exit(1)
			}

			os.Exit(0)
		}

		version, _ := cmd.Flags().GetBool("version")

		if version {
			util.Logger.Infof("Version %s\n", VERSION)
			os.Exit(0)
		}
	},
}
View Source
var ServeCmd = &cobra.Command{
	Use:   "serve",
	Short: "Start the server on the desired ip/port",
	Long:  `Leveraging the goodness of Golang and SSH - setup a local server for recording HTB credentials & flags`,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		CallPersistentPreRun(cmd, args)
		config.Load()

		if rootConfig.Setting.Debug {
			util.Logger.SetReportCaller(true)
			config.Setting.Print()
		}
	},
	Run: func(cmd *cobra.Command, args []string) {
		err := app.NewApplication().Start()

		if err != nil {
			util.Logger.Error(err)
		}
	},
}

Functions

func CallPersistentPreRun

func CallPersistentPreRun(cmd *cobra.Command, args []string)

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL