Skip to content

Commit 5c586ce

Browse files
committed
Migrated to tcell for UI. Code cleanup. Features in progress. See prev version for working copy.
1 parent 34b06b2 commit 5c586ce

13 files changed

+419
-294
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*.dll
55
*.so
66
*.dylib
7+
flshell
78

89
# Test binary, build with `go test -c`
910
*.test
@@ -14,3 +15,4 @@
1415
#Random
1516
*.txt
1617
.vscode/
18+

README.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# FLShell
22

3-
### Usage: ./flshell imagename offset(in sectors)
3+
### Usage: ./flshell -d=imagename -o=offset(in sectors)
4+
5+
```
6+
FLShell is being rewritten to use tcell rather than termbox-go, to improve modularity and code quality.
7+
Currently doesn't operate as advertised, see previous version for an operational version.
8+
```
49

510
FLShell is designed to decrease the time taken to navigate through a disk image using The Sleuthkit's fls tool by providing an interactive shell.
611

@@ -24,9 +29,9 @@ go build ./...
2429
2. Unable to enter unallocated directories.
2530

2631
### Coming features/To do
27-
1. Dump directories utilising tsk recover
28-
2. Do error handling
29-
3. Confirmation prior to dumping files
30-
4. Gather more information on current directory and display it back to the user (timestamps, filesize?)
31-
5. Huge code cleanup
32+
1. listChildren() to return on a string slice rather than string to save effort & memory expanding functionality.
33+
2. Gather more information on current directory and display it back to the user (timestamps, filesize?).
34+
3. Search for files by timestamps.
35+
4. Add method to Item struct to get a 'pwd' equivalent.
36+
3237

cache.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"strings"
66
)
77

8-
// Item ... Basic struct for all items in file system.
8+
// Item ... Basic struct for all items in file system. Type describes if the item is a directory or file.
99
type Item struct {
1010
Type string
1111
Inode string
@@ -52,7 +52,7 @@ func (f *Item) sortChildrenByAlphaDescending() {
5252
func (f *Item) listChildren() string {
5353
var msg strings.Builder
5454
for _, child := range f.Children {
55-
msg.WriteString(child.Type + " " + child.Inode + ":\t" + child.Name + "\n")
55+
msg.WriteString(child.Type + " " + child.Inode + " " + child.Name + "\n")
5656
}
5757
return msg.String()
5858

@@ -93,3 +93,8 @@ func (f *Item) goDown(parent Item, itemType string, inode string) *Item {
9393
}
9494
return nil
9595
}
96+
97+
// getPath ... TODO - Return a string containing the path of the current directory
98+
func (f *Item) getPath() string {
99+
return ""
100+
}

cmdcontroller.go

-82
This file was deleted.

debug

4.15 MB
Binary file not shown.

executer.go

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
)
8+
9+
//Reading executer.go
10+
// This file flows in building blocks, initially constructing the arguments that are passed.
11+
// Then the struct that is used to execute a command
12+
// The code that enables execution of the given struct
13+
14+
// argsUpdater ... Updates the slice of arguments that are passed with the command to be executed.
15+
// if there are less than 4 arguments (ie, a path to an image, -o, and an offset (with no inode))
16+
// Then the arguments are updated and the inode string is appended. Otherwise, just update the inode
17+
// value to the requested one.
18+
func argsUpdater(arguments []string, inode string) []string {
19+
if len(arguments) < 4 {
20+
arguments = append(arguments, inode)
21+
}
22+
arguments[3] = inode
23+
return arguments
24+
}
25+
26+
// argsUpdaterRecover ... Updates the slice of arguments that are passed with the command to be executed.
27+
// if there are less than 5 arguments (ie, a path to an image, -o, an offset, -d and no inode)
28+
// Then the arguments are updated and the inode string is appended. Otherwise, just update the inode
29+
// value to the requested one.
30+
func argsUpdaterRecover(arguments []string, inode string, carveunallocated bool) []string {
31+
if len(arguments) < 6 {
32+
arguments = append(arguments, inode, "a")
33+
}
34+
if carveunallocated {
35+
arguments[5] = "e"
36+
} else {
37+
arguments[5] = "a"
38+
}
39+
arguments[4] = inode
40+
return arguments
41+
}
42+
43+
// executeFLS ... Pass the command to be executed and its arguments as a slice of strings.
44+
// fills an item object with the current items for fls, for icat and tsk_recover it writes to a file.
45+
func executeFLS(args []string) bool {
46+
cmdStruct := exec.Command("fls", args...)
47+
cmdOutput := commandExecuter(cmdStruct)
48+
49+
// Only attempt to populate the directory if the output of the fls command run contains stuff.
50+
if len(cmdOutput) > 0 {
51+
directory.populate(cmdOutput)
52+
return true
53+
}
54+
55+
return false
56+
}
57+
58+
// executeCarvers ... Pass the command to be executed and its arguments as a slice of strings.
59+
// Writes a directory or file and its mft information to a file specified by itemname.
60+
// Returns true on successful completion, false if no cases are met.
61+
func executeCarvers(cmd string, args []string, itemname string) bool {
62+
switch cmd {
63+
case "icat":
64+
icatstruct := exec.Command(cmd, args...)
65+
writeCmdToFile(itemname, icatstruct)
66+
istatstruct := exec.Command(cmd, args...)
67+
writeCmdToFile(itemname+".mft", istatstruct)
68+
return true
69+
case "tsk_recover":
70+
recoverstruct := exec.Command(cmd, args...)
71+
writeCmdToFile(itemname, recoverstruct)
72+
return true
73+
}
74+
return false
75+
}
76+
77+
// commandExecuter ... Executes a command on the host given a command structure and
78+
// returns the output as a string.
79+
func commandExecuter(cmdstruct *exec.Cmd) string {
80+
// Define vars that will be used to store output and error of running the command.
81+
var (
82+
cmdOutput []byte
83+
cmdErr error
84+
)
85+
if cmdOutput, cmdErr = cmdstruct.Output(); cmdErr != nil {
86+
fmt.Fprintln(os.Stderr, cmdErr)
87+
os.Exit(1)
88+
}
89+
return string(cmdOutput)
90+
}

flshell

1.09 MB
Binary file not shown.

interfacecontroller.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// interfacecontroller.go contains functions to manage the execution of programs interacting with the OS
2+
// it handles the conditions under which certain calls to functions within executer.go are made and returns
3+
// messages avaiable for use in view.go
4+
5+
package main
6+
7+
// messageRetrieve ... Pass the users selection as an inode for fls or command+inode for carving and a slice of the current
8+
// directory to retrieve a single element of the slice.
9+
func messageRetrieve(selection string, input []string) string {
10+
11+
//Pull the inode and name from the selection.
12+
// TODO Test this on selection without a slice to determine how robust the regex is.
13+
selectionInode := inodeMatcher(selection)
14+
selectionName := nameMatcher(selection)
15+
16+
// Does not matter that this is not robust logic, input will be locked down by line selection in tcell version.
17+
// References to global executionArgs and the unallocatedRecover command line parameter
18+
// Return a success message if executeCarvers completes successfully, else return a failure message to the user.
19+
if selection[0] == 't' {
20+
if executeCarvers("tsk_recover", argsUpdaterRecover(executionArgsRecover, selectionInode, *unallocatedRecover), selectionName) {
21+
return "Successfully carved " + selectionName
22+
}
23+
return "Failed to carve " + selectionName
24+
}
25+
26+
if selection[0] == 'i' {
27+
if executeCarvers("icat", argsUpdater(executionArgs, selectionInode), selectionName) {
28+
return "Successfully carved " + selectionName
29+
}
30+
return "Failed to carve " + selectionName
31+
} else {
32+
// If there's nothing in the selection string providing direction to carve,
33+
// then iterate through input and return a line that has an inode matching to the
34+
// selectionInode.
35+
for _, inputLine := range input {
36+
if selectionInode == inodeMatcher(inputLine) {
37+
return inputLine
38+
}
39+
}
40+
}
41+
return "Unable to find a line in the input that matches the input string."
42+
}

ioutil.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ func check(e error) {
1313
}
1414
}
1515

16+
// writeCmdToFile ... Writes the output of a command passed to the OS to a file in the current directory.
1617
func writeCmdToFile(filename string, cmdstruct *exec.Cmd) {
1718
outfile, err := os.Create("./" + filename)
1819
check(err)
@@ -32,6 +33,7 @@ func writeCmdToFile(filename string, cmdstruct *exec.Cmd) {
3233
cmdstruct.Wait()
3334
}
3435

36+
// writeStringToFile ... Writes a string to a file in the current directory.
3537
func writeStringToFile(filename string, input string) {
3638
f, err := os.Create("./" + filename)
3739
check(err)

0 commit comments

Comments
 (0)