~shabbyrobe/bumpy

15f52b931cbd159864d1637d9c38e805bac7f66a — Blake Williams 11 months ago 2aae13d
Add scour command
3 files changed, 67 insertions(+), 0 deletions(-)

A cmd/bumpy/cmd_scour.go
M cmd/bumpy/main.go
M rules.go
A cmd/bumpy/cmd_scour.go => cmd/bumpy/cmd_scour.go +65 -0
@@ 0,0 1,65 @@
package main

import (
	"fmt"

	"github.com/shabbyrobe/cmdy"
	"github.com/shabbyrobe/cmdy/arg"
	"github.com/shabbyrobe/cmdy/cmdyutil"
	"go.shabbyrobe.org/bumpy"
)

type scourCommand struct {
	start int
	end   int
	file  string
}

func (cmd *scourCommand) Help() cmdy.Help {
	return cmdy.Synopsis("Scour a binary file at every offset looking for embedded assets")
}

func (cmd *scourCommand) Configure(flags *cmdy.FlagSet, args *arg.ArgSet) {
	flags.IntVar(&cmd.start, "start", -1, "Start index (inclusive)")
	flags.IntVar(&cmd.end, "end", -1, "End index (exclusive)")
	args.String(&cmd.file, "file", "File name ('-' for stdin)")
}

func (cmd *scourCommand) Run(ctx cmdy.Context) error {
	bts, err := cmdyutil.ReadStdinOrFile(ctx, cmd.file, cmdyutil.HyphenStdin)
	if err != nil {
		return err
	}

	start := 0
	if cmd.start >= 0 {
		start = cmd.start
		if cmd.start >= len(bts) {
			return fmt.Errorf("start exceeds bounds of file")
		}
	}

	end := len(bts)
	if cmd.end >= 0 {
		if cmd.end >= len(bts) {
			return fmt.Errorf("start exceeds bounds of file")
		} else if cmd.end <= start {
			return fmt.Errorf("end must be greater than start")
		}
		end = cmd.end
	}

	for i := start; i < end; i++ {
		_, hdr, err := bumpy.DecodeBitmapHeader(bts[i:], 0)
		if err != nil {
			continue
		} else if hdr.FileHeader.Kind.Valid() {
			fmt.Printf("bitmap type %q of size %d detected at offset %d\n",
				hdr.FileHeader.Kind,
				hdr.FileHeader.FileSize,
				i)
		}
	}

	return nil
}

M cmd/bumpy/main.go => cmd/bumpy/main.go +1 -0
@@ 20,6 20,7 @@ func run() error {
			"check":  func() cmdy.Command { return &checkCommand{} },
			"hdr":    func() cmdy.Command { return &hdrCommand{} },
			"region": func() cmdy.Command { return &regionCommand{} },
			"scour":  func() cmdy.Command { return &scourCommand{} },
		})
	}


M rules.go => rules.go +1 -0
@@ 11,3 11,4 @@ package bumpy
// if c.Compression == BI_RLE4 && c.BitsPerPixel != 4 { bork }
// bits per pixel must be 1, 4, 8, 16, 24, 32
//   perhaps this is per-header-version
//