Skip to content

Commit

Permalink
Automatically build and include all collector binaries in AndroidQF
Browse files Browse the repository at this point in the history
Resolves #15.
  • Loading branch information
DonnchaC committed Jul 13, 2023
1 parent eb51b11 commit ad867c2
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 66 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ assets/adb
assets/AdbWinApi.dll
assets/AdbWinUsbApi.dll
assets/adb.exe
assets/collector_*
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ deps:
go mod tidy
@echo "[deps] Dependencies installed."

collector:
@mkdir -p $(BUILD_FOLDER)
@echo "Building Android collector..."
cd android-collector && $(MAKE)
@echo "Finished building collector."
@echo "Copying collector binaries to assets folder."
cp android-collector/build/collector_* $(ASSETS_FOLDER)

windows:
@mkdir -p $(BUILD_FOLDER)

Expand Down Expand Up @@ -109,7 +117,9 @@ download:
@cd /tmp && unzip -u $(PLATFORMTOOLS_DARWIN)
@cp $(PLATFORMTOOLS_FOLDER)/adb $(ASSETS_FOLDER)

all: collector windows darwin linux

clean:
rm -rf $(BUILD_FOLDER)
rm -f $(ASSETS_FOLDER)/adb $(ASSETS_FOLDER)/adb.exe $(ASSETS_FOLDER)/AdbWinApi.dll $(ASSETS_FOLDER)/AdbWinUsbApi.dll
rm -f $(ASSETS_FOLDER)/adb $(ASSETS_FOLDER)/adb.exe $(ASSETS_FOLDER)/AdbWinApi.dll $(ASSETS_FOLDER)/AdbWinUsbApi.dll rm -f $(ASSETS_FOLDER)/collector_*
cd android-collector && $(MAKE) clean
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ androidqf is intended to provide a simple and portable cross-platform utility to

Executable binaries for Linux, Windows and Mac should be available in the [latest release](https://github.com/mvt/androidqf/releases/latest). In case you have issues running the binary you might want to build it by yourself.

In order to build androidqf you will need Go 1.15+ installed. You will also need to install `make`. When ready you can clone the repository and run any of the following commands, for your platform of choice:
In order to build androidqf you will need Go 1.15+ installed. You will also need to install `make`. AndroidQF includes a cross-compiled `collector` which runs on the target device to more reliably extract forensically relevant information. Android shell quirkes can make running shell commands to gather information too brittle.

When ready you can clone the repository and first build the `collector` module with:

make collector

You can then compile AndroidQF for your platform of choice:

make linux
make darwin
Expand Down
108 changes: 66 additions & 42 deletions adb/collector.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// androidqf - Android Quick Forensics
// Copyright (c) 2021 Claudio Guarnieri.
// Use of this software is governed by the MVT License 1.1 that can be found at
// https://license.mvt.re/1.1/
// https://license.mvt.re/1.1/

package adb

Expand All @@ -12,53 +12,54 @@ import (
"os"
"path/filepath"
"strings"
"github.com/mvt/androidqf/log"

saveRuntime "github.com/botherder/go-savetime/runtime"
"github.com/mvt/androidqf/assets"
)

type Collector struct {
ExePath string
Installed bool
Adb *ADB
ExePath string
Installed bool
Adb *ADB
Architecture string
}

type FileInfo struct {
Path string `json:"path"`
Size int64 `json:"size"`
Mode string `json:"mode"`
UserId uint32 `json:"user_id"`
UserName string `json:"user_name"`
GroupId uint32 `json:"group_id"`
GroupName string `json:"group_name"`
ChangeTime int64 `json:"changed_time"`
ModifiedTime int64 `json:"modified_time"`
AccessTime int64 `json:"access_time"`
Error string `json:"error"`
Context string `json:"context"`
SHA1 string `json:"sha1"`
SHA256 string `json:"sha256"`
SHA512 string `json:"sha512"`
MD5 string `json:"md5"`
Path string `json:"path"`
Size int64 `json:"size"`
Mode string `json:"mode"`
UserId uint32 `json:"user_id"`
UserName string `json:"user_name"`
GroupId uint32 `json:"group_id"`
GroupName string `json:"group_name"`
ChangeTime int64 `json:"changed_time"`
ModifiedTime int64 `json:"modified_time"`
AccessTime int64 `json:"access_time"`
Error string `json:"error"`
Context string `json:"context"`
SHA1 string `json:"sha1"`
SHA256 string `json:"sha256"`
SHA512 string `json:"sha512"`
MD5 string `json:"md5"`
}

type ProcessInfo struct {
Pid uint32 `json:"pid"`
Uid uint32 `json:"uid"`
Ppid uint32 `json:"ppid"`
Pgroup uint32 `json:"pgroup"`
Psid uint32 `json:"psid"`
Filename string `json:"filename"`
Priority uint32 `json:"priority"`
State string `json:"state"`
UserTime uint32 `json:"user_time"`
KernelTime uint32 `json:"kernel_time"`
Path string `json:"path"`
Context string `json:"context"`
PreviousContext string `json:"previous_context"`
CommandLine []string `json:"command_line"`
Environment []string `json:"env"`
WorkingDirectory string `json:"cwd"`
Pid uint32 `json:"pid"`
Uid uint32 `json:"uid"`
Ppid uint32 `json:"ppid"`
Pgroup uint32 `json:"pgroup"`
Psid uint32 `json:"psid"`
Filename string `json:"filename"`
Priority uint32 `json:"priority"`
State string `json:"state"`
UserTime uint32 `json:"user_time"`
KernelTime uint32 `json:"kernel_time"`
Path string `json:"path"`
Context string `json:"context"`
PreviousContext string `json:"previous_context"`
CommandLine []string `json:"command_line"`
Environment []string `json:"env"`
WorkingDirectory string `json:"cwd"`
}

// Returns a new Collector instance.
Expand Down Expand Up @@ -96,16 +97,39 @@ func (c *Collector) Install() error {
return err
}
}
if !strings.HasPrefix(c.Architecture, "armeabi-v") && !strings.HasPrefix(c.Architecture, "armeabi-v7") && !strings.HasPrefix(c.Architecture, "arm64-v8") {
return fmt.Errorf("unsupported architecture: %s", c.Architecture)

collectorName := ""
switch {
case strings.HasPrefix(c.Architecture, "armeabi-v"):
collectorName = "collector_arm6"
case strings.HasPrefix(c.Architecture, "armeabi-v7"):
collectorName = "collector_arm7"
case strings.HasPrefix(c.Architecture, "arm64-v8"):
collectorName = "collector_arm64"
default:
return fmt.Errorf("unsupported architecture for collector: %s", c.Architecture)
}
collectorPath := filepath.Join(saveRuntime.GetExecutableDirectory(), "collector_arm6")
if _, err := os.Stat(collectorPath); err != nil {

log.Debugf("Deploying collector binary '%s' for architecture '%s'.", collectorName, c.Architecture)
collectorBinary, err := assets.Collector.ReadFile(collectorName);
if err != nil {
// Somehow the file doesn't exist
return errors.New("couldn't find the collector binary")
}

_, err := c.Adb.Push(collectorPath, c.ExePath)
collectorTemp, _ := os.CreateTemp("", "collector_");
if err != nil {
return err
}
defer os.Remove(collectorTemp.Name())

// Write collector binary out to temporary path
if _, err := collectorTemp.Write(collectorBinary); err != nil {
collectorTemp.Close()
return err
}

_, err = c.Adb.Push(collectorTemp.Name(), c.ExePath)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions android-collector/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ fmt:
build:
env GOOS=linux GOARCH=arm GOARM=7 go build -o $(BUILD_FOLDER)/collector_arm7
env GOOS=linux GOARCH=arm GOARM=6 go build -o $(BUILD_FOLDER)/collector_arm6
env GOOS=linux GOARCH=amd64 go build -o $(BUILD_FOLDER)/collector_x86
env GOOS=linux GOARCH=amd64 go build -o $(BUILD_FOLDER)/collector_amd64
env GOOS=linux GOARCH=arm64 go build -o $(BUILD_FOLDER)/collector_arm64

clean:
rm -rf $BUILD_FOLDER
rm -rf $(BUILD_FOLDER)

test: build
adb shell "rm -rf /data/local/tmp/collector"
Expand Down
5 changes: 5 additions & 0 deletions assets/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ package assets
import (
"os"
"path/filepath"
"embed"

saveRuntime "github.com/botherder/go-savetime/runtime"
)


//go:embed collector_*
var Collector embed.FS

type Asset struct {
Name string
Data []byte
Expand Down
8 changes: 0 additions & 8 deletions assets/assets_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,8 @@ import (
//go:embed "adb"
var adbData []byte

//go:embed collector_arm6
var collectorArm6 []byte

//go:embed collector_arm7
var collectorArm7 []byte

func getAssets() []Asset {
return []Asset{
{Name: "adb", Data: adbData},
{Name: "collector_arm6", Data: collectorArm6},
{Name: "collector_arm7", Data: collectorArm7},
}
}
4 changes: 0 additions & 4 deletions assets/assets_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@ import (
//go:embed "adb"
var adbData []byte

//go:embed collector_arm6
var collectorArm6 []byte

func getAssets() []Asset {
return []Asset{
{Name: "adb", Data: adbData},
{Name: "collector_arm6", Data: collectorArm6},
}
}
8 changes: 0 additions & 8 deletions assets/assets_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,10 @@ var adbWinApiData []byte
//go:embed "AdbWinUsbApi.dll"
var adbWinUsbApiData []byte

//go:embed collector_arm6
var collectorArm6 []byte

//go:embed collector_arm7
var collectorArm7 []byte

func getAssets() []Asset {
return []Asset{
{Name: "adb.exe", Data: adbData},
{Name: "AdbWinApi.dll", Data: adbWinApiData},
{Name: "AdbWinUsbApi.dll", Data: adbWinUsbApiData},
{Name: "collector_arm6", Data: collectorArm6},
{Name: "collector_arm7", Data: collectorArm7},
}
}
Binary file removed assets/collector_arm6
Binary file not shown.

0 comments on commit ad867c2

Please sign in to comment.