-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 18ab4c5
Showing
20 changed files
with
1,538 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
github: botherder | ||
patreon: botherder | ||
ko_fi: botherder |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, built with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
|
||
# Dependency directories (remove the comment below to include it) | ||
# vendor/ | ||
|
||
build/ | ||
assets/ | ||
bindata.go |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
BUILD_FOLDER = $(shell pwd)/build | ||
ASSETS_FOLDER = $(shell pwd)/assets | ||
|
||
FLAGS_DARWIN = GOOS=darwin | ||
FLAGS_WINDOWS = GOOS=windows GOARCH=386 CC=i686-w64-mingw32-gcc CGO_ENABLED=1 | ||
|
||
PLATFORMTOOLS_URL = https://dl.google.com/android/repository/ | ||
PLATFORMTOOLS_WINDOWS = platform-tools-latest-windows.zip | ||
PLATFORMTOOLS_DARWIN = platform-tools-latest-darwin.zip | ||
PLATFORMTOOLS_LINUX = platform-tools-latest-linux.zip | ||
PLATFORMTOOLS_FOLDER = /tmp/platform-tools | ||
|
||
lint: | ||
@echo "[lint] Running linter on codebase" | ||
@golint ./... | ||
|
||
deps: | ||
@echo "[deps] Installing dependencies..." | ||
go mod download | ||
go get -u github.com/go-bindata/go-bindata/... | ||
@echo "[deps] Dependencies installed." | ||
|
||
windows: deps | ||
@mkdir -p $(BUILD_FOLDER) | ||
@mkdir -p $(ASSETS_FOLDER) | ||
|
||
@if [ ! -f /tmp/$(PLATFORMTOOLS_WINDOWS) ]; then \ | ||
echo "Downloading Windows Android Platform Tools..."; \ | ||
wget $(PLATFORMTOOLS_URL)$(PLATFORMTOOLS_WINDOWS) -O /tmp/$(PLATFORMTOOLS_WINDOWS); \ | ||
fi | ||
|
||
@rm -rf $(PLATFORMTOOLS_FOLDER) | ||
@cd /tmp && unzip -u $(PLATFORMTOOLS_WINDOWS) | ||
@cp $(PLATFORMTOOLS_FOLDER)/AdbWinApi.dll $(ASSETS_FOLDER) | ||
@cp $(PLATFORMTOOLS_FOLDER)/AdbWinUsbApi.dll $(ASSETS_FOLDER) | ||
@cp $(PLATFORMTOOLS_FOLDER)/adb.exe $(ASSETS_FOLDER) | ||
@go-bindata -pkg adb -o adb/bindata.go -prefix $(ASSETS_FOLDER) $(ASSETS_FOLDER) | ||
|
||
$(FLAGS_WINDOWS) go build --ldflags '-s -w -extldflags "-static"' -o $(BUILD_FOLDER)/snoopdroid2.exe ./cmd/ | ||
|
||
darwin: deps | ||
@mkdir -p $(BUILD_FOLDER) | ||
@mkdir -p $(ASSETS_FOLDER) | ||
|
||
@if [ ! -f /tmp/$(PLATFORMTOOLS_DARWIN) ]; then \ | ||
echo "Downloading Darwin Android Platform Tools..."; \ | ||
wget $(PLATFORMTOOLS_URL)$(PLATFORMTOOLS_DARWIN) -O /tmp/$(PLATFORMTOOLS_DARWIN); \ | ||
fi | ||
|
||
@rm -rf $(PLATFORMTOOLS_FOLDER) | ||
@cd /tmp && unzip -u $(PLATFORMTOOLS_DARWIN) | ||
@cp $(PLATFORMTOOLS_FOLDER)/adb $(ASSETS_FOLDER) | ||
@go-bindata -pkg adb -o adb/bindata.go -prefix $(ASSETS_FOLDER) $(ASSETS_FOLDER) | ||
|
||
$(FLAGS_DARWIN) go build --ldflags '-s -w' -o $(BUILD_FOLDER)/snoopdroid2-darwin ./cmd/ | ||
|
||
linux: deps | ||
@mkdir -p $(BUILD_FOLDER) | ||
@mkdir -p $(ASSETS_FOLDER) | ||
|
||
@if [ ! -f /tmp/$(PLATFORMTOOLS_LINUX) ]; then \ | ||
echo "Downloading Linux Android Platform Tools..."; \ | ||
wget $(PLATFORMTOOLS_URL)$(PLATFORMTOOLS_LINUX) -O /tmp/$(PLATFORMTOOLS_LINUX); \ | ||
fi | ||
|
||
@rm -rf $(PLATFORMTOOLS_FOLDER) | ||
@cd /tmp && unzip -u $(PLATFORMTOOLS_LINUX) | ||
@cp $(PLATFORMTOOLS_FOLDER)/adb $(ASSETS_FOLDER) | ||
@go-bindata -pkg adb -o adb/bindata.go -prefix $(ASSETS_FOLDER) $(ASSETS_FOLDER) | ||
|
||
@go build --ldflags '-s -w' -o $(BUILD_FOLDER)/snoopdroid2-linux ./cmd/ | ||
|
||
clean: | ||
rm -rf $(ASSETS_FOLDER) | ||
rm -rf $(BUILD_FOLDER) | ||
rm -f ./*/bindata.go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Snoopdroid 2 | ||
|
||
[![Go Report Card](https://goreportcard.com/badge/github.com/botherder/snoopdroid2)](https://goreportcard.com/report/github.com/botherder/snoopdroid2) | ||
|
||
Snoopdroid 2 is a portable tool to simplify the acquisition of relevant forensic data from Android devices. It is the successor of [Snoopdroid](https://github.com/botherder/snoopdroid), re-written in Go and leveraging official adb binaries. | ||
|
||
## Build | ||
|
||
In order to build Snoopdroid 2 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, depending on which platform you would like to run Snoopdroid 2 on: | ||
|
||
make linux | ||
make darwin | ||
make windows | ||
|
||
These commands will generate binaries in a *build/* folder. | ||
|
||
## Use | ||
|
||
Before launching Snoopdroid you need to have the target Android device connected to your computer via USB, and you will need to have enabled USB debugging. Please refer to the [official documentation](https://developer.android.com/studio/debug/dev-options#enable) on how to do this, but also be mindful that Android phones from different manufacturers might require different navigation steps than the defaults. | ||
|
||
Once USB debugging is enabled, you can proceed launching Snoopdroid 2. It will first attempt to connect to the device over the USB bridge, which should result in the Android phone to prompt you to manually authorize the host keys. Make sure to authorize them, ideally permanently so that the prompt wouldn't appear again. | ||
|
||
Now Snoopdroid 2 should be executing and creating an acquisition folder at the same path you have placed your Snoopdroid 2 binary. At some point in the execution, Snoopdroid 2 will prompt you some choices: these prompts will pause the acquisition until you provide a selection, so pay attention. | ||
|
||
The following data can be extracted: | ||
|
||
1. A list of all packages installed and related distribution files. | ||
2. (Optional) Copy of all installed APKs or of only those not safelisted by Snoopdroid 2. | ||
3. The output of the `dumpsys` shell command, providing diagnostic information about the device. | ||
4. The output of the `getprop` shell command, providing build information and configuration parameters. | ||
5. The output of the `ps` shell command, providing a list of all running processes. | ||
6. (Optional) A backup of SMS and MMS messages. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Snoopdroid 2 | ||
// 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/ | ||
|
||
package acquisition | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"time" | ||
|
||
"github.com/botherder/snoopdroid2/adb" | ||
"github.com/satori/go.uuid" | ||
) | ||
|
||
type Acquisition struct { | ||
UUID string | ||
ADB *adb.ADB | ||
BasePath string | ||
APKSPath string | ||
Datetime time.Time | ||
} | ||
|
||
// New returns a new Acquisition instance. | ||
func New() (*Acquisition, error) { | ||
acq := Acquisition{} | ||
uuidBytes := uuid.NewV4() | ||
acq.UUID = uuidBytes.String() | ||
acq.Datetime = time.Now().UTC() | ||
|
||
err := acq.initADB() | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to initialize adb: %s", err) | ||
} | ||
|
||
err = acq.createFolder() | ||
if err != nil { | ||
return nil, fmt.Errorf("Failed to create acquisition folder: %s", err) | ||
} | ||
|
||
return &acq, nil | ||
} | ||
|
||
func (a *Acquisition) initADB() error { | ||
var err error | ||
a.ADB, err = adb.New() | ||
if err != nil { | ||
return fmt.Errorf("Failed to initialize adb: %s", err) | ||
} | ||
|
||
_, err = a.ADB.GetState() | ||
if err != nil { | ||
return fmt.Errorf("Unable to get adb state, are you sure a device is connected?") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a *Acquisition) createFolder() error { | ||
cwd, err := os.Getwd() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
a.BasePath = filepath.Join(cwd, a.UUID) | ||
err = os.Mkdir(a.BasePath, 0755) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
a.APKSPath = filepath.Join(a.BasePath, "apks") | ||
err = os.Mkdir(a.APKSPath, 0755) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Snoopdroid 2 | ||
// 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/ | ||
|
||
package acquisition | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/botherder/go-savetime/hashes" | ||
"github.com/botherder/go-savetime/slice" | ||
"github.com/i582/cfmt" | ||
"github.com/manifoldco/promptui" | ||
) | ||
|
||
const ( | ||
apkAll = "All" | ||
apkNotKnown = "Only not known" | ||
) | ||
|
||
type File struct { | ||
Path string `json:"path"` | ||
LocalName string `json:"local_name"` | ||
SHA256 string `json:"sha256"` | ||
} | ||
|
||
func (a *Acquisition) getPathToLocalCopy(packageName, filePath string) string { | ||
fileName := "" | ||
if strings.Contains(filePath, "==/") { | ||
fileName = fmt.Sprintf("_%s", strings.Replace(strings.Split(filePath, "==/")[1], ".apk", "", 1)) | ||
} | ||
|
||
localPath := filepath.Join(a.APKSPath, fmt.Sprintf("%s%s.apk", packageName, fileName)) | ||
counter := 0 | ||
for true { | ||
if _, err := os.Stat(localPath); os.IsNotExist(err) { | ||
break | ||
} | ||
|
||
counter++ | ||
localPath = filepath.Join(a.APKSPath, fmt.Sprintf("%s%s_%s.apk", packageName, fileName, counter)) | ||
} | ||
|
||
return localPath | ||
} | ||
|
||
func (a *Acquisition) DownloadAPKs() error { | ||
fmt.Println("Downloading copies of installed apps...") | ||
|
||
packages, err := a.ADB.GetPackages() | ||
if err != nil { | ||
return fmt.Errorf("Unable to retrieve list of installed packages: %s", err) | ||
} | ||
|
||
cfmt.Printf("Found a total of {{%d}}::cyan|bold installed packages\n", | ||
len(packages)) | ||
|
||
fmt.Println("Would you like to download all APKs or only those not known?") | ||
promptAll := promptui.Select{ | ||
Label: "Download", | ||
Items: []string{apkAll, apkNotKnown}, | ||
} | ||
_, downloadOption, err := promptAll.Run() | ||
if err != nil { | ||
return fmt.Errorf("Failed to make selection for download option") | ||
} | ||
|
||
for i, p := range packages { | ||
if downloadOption != apkAll && slice.Contains(packageFilter, p.Name) { | ||
continue | ||
} | ||
|
||
cfmt.Printf("Found Android package: {{%s}}::cyan|bold\n", p.Name) | ||
|
||
pFilePaths, err := a.ADB.GetPackagePaths(p.Name) | ||
if err == nil { | ||
for _, pFilePath := range pFilePaths { | ||
localPath := a.getPathToLocalCopy(p.Name, pFilePath) | ||
|
||
out, err := a.ADB.Pull(pFilePath, localPath) | ||
if err != nil { | ||
cfmt.Printf("{{ERROR:}}::red|bold Failed to download {{%s}}::cyan|underline: {{%s}}::italic\n", | ||
pFilePath, out) | ||
|
||
continue | ||
} | ||
|
||
cfmt.Printf("Downloaded {{%s}}::cyan|underline to {{%s}}::magenta|underline\n", | ||
pFilePath, localPath) | ||
|
||
sha256, _ := hashes.FileSHA256(localPath) | ||
file := File{ | ||
Path: pFilePath, | ||
LocalName: filepath.Base(localPath), | ||
SHA256: sha256, | ||
} | ||
|
||
packages[i].Files = append(packages[i].Files, file) | ||
} | ||
} | ||
} | ||
|
||
packagesJSONPath := filepath.Join(a.BasePath, "packages.json") | ||
packagesJSON, err := os.Create(packagesJSONPath) | ||
if err != nil { | ||
return fmt.Errorf("Unable to save list of installed packages to file: %s", err) | ||
} | ||
defer packagesJSON.Close() | ||
|
||
buf, _ := json.MarshalIndent(packages, "", " ") | ||
|
||
packagesJSON.WriteString(string(buf[:])) | ||
packagesJSON.Sync() | ||
|
||
return nil | ||
} |
Oops, something went wrong.