Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
NSEcho committed Sep 13, 2023
0 parents commit 786bfc6
Show file tree
Hide file tree
Showing 16 changed files with 972 additions and 0 deletions.
27 changes: 27 additions & 0 deletions .github/actions/install-frida-devkit/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Install Frida Devkit
description: Install Frida Devkit
inputs:
arch:
required: true
path: the architecture of the devkit
os:
required: true
path: the target operating system of the devkit
version:
required: true
path: the version of the devkit
outdir:
required: true
path: where to save header and dylib
runs:
using: composite
steps:
- run: |
mkdir /tmp/frida-core-devkit && cd /tmp/frida-core-devkit
wget https://github.com/frida/frida/releases/download/${{ inputs.version }}/frida-core-devkit-${{ inputs.version }}-${{ inputs.os }}-${{ inputs.arch }}.tar.xz -O - | tar --extract --xz
mkdir -p ${{ inputs.outdir }}/include
mkdir -p ${{ inputs.outdir }}/lib
cp frida-core.h ${{ inputs.outdir }}/include
cp libfrida-core.* ${{ inputs.outdir }}/lib
rm -rf /tmp/frida-core-devkit
shell: bash
49 changes: 49 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Release
on:
push:
tags:
- v*.*.*

jobs:
release:
strategy:
matrix:
frida_version: ["16.1.3"]
runs-on: macos-latest
steps:
-
name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
-
name: Set up Go
uses: actions/setup-go@v4
-
name: Fetch all tags
run: git fetch --force --tags
-
name: Download Frida macOS_amd64
uses: ./.github/actions/install-frida-devkit
with:
arch: x86_64
os: macos
version: ${{ matrix.frida_version }}
outdir: /tmp/data/macos_amd64
-
name: Download Frida macOS_arm64
uses: ./.github/actions/install-frida-devkit
with:
arch: arm64
os: macos
version: ${{ matrix.frida_version }}
outdir: /tmp/data/macos_arm64
-
name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
34 changes: 34 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
before:
hooks:
- go mod tidy
builds:
- id: macos_amd64
binary: furlzz
env:
- CGO_ENABLED=1
- CGO_LDFLAGS=-L/tmp/data/macos_amd64/lib
- CGO_CFLAGS=-I/tmp/data/macos_amd64/include
goos:
- darwin
goarch:
- amd64
flags:
- -trimpath
ldflags: -s -w
- id: macos_arm64
binary: furlzz
env:
- CGO_ENABLED=1
- CGO_LDFLAGS=-L/tmp/data/macos_arm64/lib
- CGO_CFLAGS=-I/tmp/data/macos_arm64/include
goos:
- darwin
goarch:
- arm64
flags:
- -trimpath
ldflags: -s -w
checksum:
name_template: 'checksums.txt'
changelog:
sort: asc
87 changes: 87 additions & 0 deletions cmd/crash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package cmd

import (
"errors"
"github.com/frida/frida-go/frida"
"github.com/spf13/cobra"
"io"
"os"
"time"
)

var crashCmd = &cobra.Command{
Use: "crash",
Short: "Run the application with crash",
RunE: func(cmd *cobra.Command, args []string) error {
sfile, err := cmd.Flags().GetString("session")
if err != nil {
return err
}

l.Infof("Reading session file %s", sfile)
s, err := NewSession(sfile)
if err != nil {
return err
}

crash, err := cmd.Flags().GetString("crash")
if err != nil {
return err
}

inpf, err := os.Open(crash)
if err != nil {
return err
}
defer inpf.Close()

input, _ := io.ReadAll(inpf)

l.Infof("Read %s from crash file", string(input))

dev := frida.USBDevice()
if dev == nil {
return errors.New("no USB device detected")
}
defer dev.Clean()

sess, err := dev.Attach(s.App, nil)
if err != nil {
return err
}
defer sess.Clean()

l.Infof("Attached to %s", s.App)

script, err := sess.CreateScript(scriptContent)
if err != nil {
return err
}

script.On("message", func(message string) {
l.Infof("script output: %s", message)
})

if err := script.Load(); err != nil {
return err
}
defer script.Clean()

l.Infof("Loaded script")

l.Infof("Sleeping for two seconds and triggering crash")

time.Sleep(2 * time.Second)

_ = script.ExportsCall("fuzz", s.Method, string(input))

return nil
},
}

func init() {
crashCmd.Flags().StringP("session", "s", "", "session path")
crashCmd.Flags().StringP("crash", "c", "", "crash file")

rootCmd.AddCommand(crashCmd)
}
177 changes: 177 additions & 0 deletions cmd/fuzz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package cmd

import (
"errors"
"github.com/fatih/color"
"github.com/frida/frida-go/frida"
"github.com/nsecho/furlzz/mutator"
"github.com/spf13/cobra"
"os"
"strings"
"time"
)

var fuzzCmd = &cobra.Command{
Use: "fuzz",
Short: "Fuzz URL scheme",
RunE: func(cmd *cobra.Command, args []string) error {
var validInputs []string
var err error

base, err := cmd.Flags().GetString("base")
if err != nil {
return err
}
if base == "" {
return errors.New("base URL cannot be empty")
}

input, err := cmd.Flags().GetString("input")
if err != nil {
return err
}

if input == "" && strings.Contains(base, "FUZZ") {
return errors.New("input directory cannot be empty when using FUZZ keyword")
}

if strings.Contains(base, "FUZZ") {
validInputs, err = readInputs(input)
if err != nil {
return err
}
}

runs, err := cmd.Flags().GetUint("runs")
if err != nil {
return err
}

fn, err := cmd.Flags().GetString("function")
if err != nil {
return err
}

timeout, err := cmd.Flags().GetUint("timeout")
if err != nil {
return err
}

method, err := cmd.Flags().GetString("method")
if err != nil {
return err
}

l.Infof("Fuzzing base URL \"%s\"", base)
if strings.Contains(base, "FUZZ") {
l.Infof("Read %d inputs from %s directory",
len(validInputs), input)
} else {
l.Infof("Fuzzing base URL")
}

if runs == 0 {
l.Infof("Fuzzing indefinitely")
} else {
l.Infof("Fuzzing with %d mutated inputs", runs)
}

if timeout != 0 {
l.Infof("Sleeping %d seconds between each fuzz case", timeout)
}

app, err := cmd.Flags().GetString("app")
if err != nil {
return err
}

if app == "" {
return errors.New("error: app cannot be empty")
}

dev := frida.USBDevice()
if dev == nil {
return errors.New("no USB device detected")
}
defer dev.Clean()

sess, err := dev.Attach(app, nil)
if err != nil {
return err
}

l.Infof("Attached to %s", app)

var lastInput string

sess.On("detached", func(reason frida.SessionDetachReason, crash *frida.Crash) {
l.Infof("Session detached; reason=%s", reason.String())
out := crashSHA256(lastInput)
err := func() error {
f, err := os.Create(out)
if err != nil {
return err
}
f.WriteString(lastInput)
return nil
}()
if err != nil {
l.Errorf("Error writing crash file: %v", err)
} else {
l.Infof("Written crash to: %s", out)
}
s := Session{
App: app,
Base: base,
Function: fn,
Method: method,
}
if err := s.WriteToFile(); err != nil {
l.Errorf("Error writing session file: %v", err)
} else {
l.Infof("Written session file")
}
os.Exit(1)
})

script, err := sess.CreateScript(scriptContent)
if err != nil {
return err
}

script.On("message", func(message string) {
l.Infof("script output: %s", message)
})

if err := script.Load(); err != nil {
return err
}

l.Infof("Loaded script")

m := mutator.NewMutator(base, runs, fn, validInputs...)
ch := m.Mutate()

for mutated := range ch {
lastInput = mutated.Input
l.Infof("[%s] %s\n", color.New(color.FgCyan).Sprintf("%s", mutated.Mutation), mutated.Input)
_ = script.ExportsCall("fuzz", method, mutated.Input)
if timeout > 0 {
time.Sleep(time.Duration(timeout) * time.Second)
}
}
return nil
},
}

func init() {
fuzzCmd.Flags().StringP("app", "a", "Gadget", "Application name to attach to")
fuzzCmd.Flags().StringP("base", "b", "", "base URL to fuzz")
fuzzCmd.Flags().StringP("input", "i", "", "path to input directory")
fuzzCmd.Flags().StringP("function", "f", "", "apply the function to mutated input (url, base64)")
fuzzCmd.Flags().StringP("method", "m", "delegate", "method of opening url (delegate, app)")
fuzzCmd.Flags().UintP("runs", "r", 0, "number of runs")
fuzzCmd.Flags().UintP("timeout", "t", 1, "sleep X seconds between each case")

rootCmd.AddCommand(fuzzCmd)
}
Loading

0 comments on commit 786bfc6

Please sign in to comment.