Skip to content

Commit

Permalink
Merge pull request #1 from moldabekov/dev
Browse files Browse the repository at this point in the history
Production release
  • Loading branch information
moldabekov authored Jan 17, 2018
2 parents c87df51 + d776813 commit 8bba630
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 8 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.idea
main
release/*
virusgotal
unstaged
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2017 Mldbk
Copyright 2017 M. Moldabekov

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
# termux-virustotal
VirusTotal wrapper for Termux. No hassle scanning URLs and files from your Android device.
# Virusgotal

`virusgotal` is a simple CLI wrapper for famous VirusTotal service. No hassle URLs and files scanning ever.

Yes, it is yet another wrapper.

However it's a crossplatform CLI tool which runs on Linux/macOS/Windows and even Android.


## Installation

The easiest way is to grab package from Github Releases page.

If you want to do it manually then you are welcome:

```go get -u github.com/moldabekov/virusgotal```

## Usage

**TBD**

## Contribution

**TBD**

## License
MIT License
59 changes: 59 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash

PACKAGE=virusgotal
DIR=./release
SRC=.
LDFLAGS="-s -w"

if [ ! -d "$DIR" ]; then
mkdir $DIR
fi

function compress {
cd $DIR
upx -9 $PACKAGE-$GOOS-$GOARCH
zip -9 -v -D $PACKAGE-$GOOS-$GOARCH.zip $PACKAGE-$GOOS-$GOARCH
cd ..
}

function compress_win {
cd $DIR
upx -9 $PACKAGE-$GOOS-$GOARCH.exe
zip -9 -v -D $PACKAGE-$GOOS-$GOARCH.zip $PACKAGE-$GOOS-$GOARCH.exe
cd ..
}

# Linux
export GOOS=linux GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=linux GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=linux GOARCH=arm && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=linux GOARCH=arm64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=linux GOARCH=mips && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=linux GOARCH=mips64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# macOS
export GOOS=darwin GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=darwin GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# Windows
export GOOS=windows GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH.exe $SRC && compress_win
export GOOS=windows GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH.exe $SRC && compress_win

# Android [!] Needs cross compiler!
# export GOOS=android GOARCH=arm && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# FreeBSD
export GOOS=freebsd GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=freebsd GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# NetBSD
export GOOS=netbsd GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=netbsd GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# OpenBSD
export GOOS=openbsd GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
export GOOS=openbsd GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress

# Plan9
# export GOOS=plan9 GOARCH=amd64 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
# export GOOS=plan9 GOARCH=386 && go build -ldflags="-s -w" -o $DIR/$PACKAGE-$GOOS-$GOARCH $SRC && compress
13 changes: 13 additions & 0 deletions check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"fmt"
"os"
)

func check(err error) {
if err != nil {
fmt.Printf("FATAL: %v\n", err)
os.Exit(1)
}
}
95 changes: 95 additions & 0 deletions filescan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"os"
"crypto/sha256"
"io"
"fmt"
"github.com/moldabekov/virusgotal/vt"
"github.com/fatih/color"
)

func sha256sum(filename string) string {
f, err := os.Open(filename)
check(err)
defer f.Close()

h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
fmt.Printf("FATAL: %v\n", err)
os.Exit(1)
}

return fmt.Sprintf("%x\n", h.Sum(nil))
}

func printFileResult(result *govt.FileReport) {
color.Set(color.FgHiYellow)
fmt.Printf("%s file scan results:\n", *filename)
if !*waitFile {
fmt.Printf("sha256 hashsum: %s\n", result.Sha256)
fmt.Printf("VirusTotal link: %s\n\n", result.Permalink)
}
color.Set(color.FgHiCyan)
fmt.Printf("Detection ratio: %v/%v\n\n", result.Positives, result.Total)
for i := range result.Scans {
if result.Scans[i].Detected {
color.Set(color.FgHiRed, color.Bold)
fmt.Printf("AV: %s\nResult: %s\n\n", i, result.Scans[i].Result)
} else {
color.Set(color.FgHiGreen, color.Bold)
fmt.Printf("AV: %s\nDetected: %t\n\n", i, result.Scans[i].Detected)
}
}
color.Unset()
os.Exit(0)
}

func scanFile(filename string) {
// Init VT
apikey := os.Getenv("VT_API_KEY")
vt, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// Check previous results
if !*forceFile {
r, err := vt.GetFileReport(sha256sum(filename))
check(err)

// If file was previously scanned print results
switch r.Status.ResponseCode {
case 1: // Results exist
fmt.Printf("%d", r.Status.ResponseCode)
printFileResult(r)
case -2: // Scan in progress
color.Set(color.FgHiRed)
fmt.Printf("You scan is still in progress\n")
color.Unset()
os.Exit(1)
}
}

// Scan file
report, err := vt.ScanFile(filename)
check(err)
color.Set(color.FgHiGreen, color.Bold)
fmt.Printf("Your file was submitted and scan was queued. Here are details:\n\n")
color.Set(color.Reset, color.FgHiCyan)
fmt.Printf("sha256 hash: %s\n", report.Sha256)
fmt.Printf("VirusTotal link: %s\n\n", report.Permalink)
color.Unset()
if *waitFile { // Wait for results if user wishes
for m := 0; m <= 600; m += 30 { // m == minutes
loader(fmt.Sprintf("waiting for results for %d seconds", m))
r, err := vt.GetFileReport(sha256sum(filename))
check(err)
if r.Status.ResponseCode == 1 {
fmt.Printf("scan took ~ %d seconds\n", m)
printFileResult(r)
}
}
color.Set(color.FgHiRed)
fmt.Printf("\nSomething went wrong with VirusTotal. Maybe their servers are overloaded.\n" +
"Please try again later\n")
}
}
37 changes: 37 additions & 0 deletions hashsearch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import (
"fmt"
"os"
"github.com/moldabekov/virusgotal/vt"
"github.com/fatih/color"
)

func searchHash(hash string) {
// Init VT
apikey := os.Getenv("VT_API_KEY")
vt, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// Check hash
r, err := vt.GetFileReport(hash)
check(err)

if r.ResponseCode == 0 {
color.Set(color.FgHiRed, color.Bold)
fmt.Printf("Given hash isn't recognized by VirusTotal\n")
color.Unset()
os.Exit(1)
} else {
if r.Positives > 0 {
color.Set(color.FgHiRed)
fmt.Printf("\nGiven hash [%d/%d] is KNOWN by VirusTotal and has positive results\n", r.Positives, r.Total)
color.Unset()
} else {
color.Set(color.FgHiGreen)
fmt.Printf("\nGiven hash is KNOWN by VirusTotal and has no positive results\n", r.Positives, r.Total)
color.Unset()
}
fmt.Printf("Direct link: %s\n\n", r.Permalink)
}
}
13 changes: 13 additions & 0 deletions loader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"time"
"github.com/moldabekov/spinner"
)

func loader(s string) {
spin := spinner.New("%s " + s)
spin.Start()
defer spin.Stop()
time.Sleep(30 * time.Second) // query every 30 seconds
}
35 changes: 32 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
package termux_virustotal
package main

import "fmt"
import (
"os"
"gopkg.in/alecthomas/kingpin.v2"
)

const apiurl = "https://www.virustotal.com/vtapi/v2/"

var (
app = kingpin.New("virusgotal", "A CLI VirusTotal client built with Go")

filescan = app.Command("file", "File scanning mode")
filename = filescan.Arg("FILE", "File to scan").Required().String()
forceFile = filescan.Flag("force", "rescan file").Bool()
waitFile = filescan.Flag("wait", "wait for results").Bool()

urlscan = app.Command("url", "URL scanning mode")
urlname = urlscan.Arg("URL", "URL to scan").Required().String()
forceUrl = urlscan.Flag("force", "rescan URL").Bool()
waitUrl = urlscan.Flag("wait", "wait for results").Bool()

hashscan = app.Command("hash", "Search files by hash")
hash = hashscan.Arg("HASH", "SHA1/SHA256/MD5 hash").Required().String()
)

func main() {
fmt.Println("123")
switch kingpin.MustParse(app.Parse(os.Args[1:])) {
case filescan.FullCommand():
scanFile(*filename)
case urlscan.FullCommand():
scanUrl(*urlname)
case hashscan.FullCommand():
searchHash(*hash)
}
}
1 change: 1 addition & 0 deletions tests/eicar
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
3 changes: 3 additions & 0 deletions tests/test_file
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test_string
and extra
and more again
79 changes: 79 additions & 0 deletions urlscan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package main

import (
"github.com/moldabekov/virusgotal/vt"
"github.com/fatih/color"
"fmt"
"os"
)

func printUrlResult(result *govt.UrlReport) {
color.Set(color.FgHiYellow)
fmt.Printf("%s scan results:\n", *urlname)
if !*waitUrl {
fmt.Printf("VirusTotal link: %s\n\n", result.Permalink)
}
color.Set(color.FgHiCyan)
fmt.Printf("Detection ratio: %v/%v\n\n", result.Positives, result.Total)
for i := range result.Scans {
if result.Scans[i].Detected {
color.Set(color.FgHiRed, color.Bold)
fmt.Printf("AV: %s\nResult: %s\n\n", i, result.Scans[i].Result)
} else {
color.Set(color.FgHiGreen, color.Bold)
fmt.Printf("AV: %s\nDetected: %t\n\n", i, result.Scans[i].Detected)
}
}
color.Unset()
os.Exit(0)
}

func scanUrl(urlname string) {
// Init VT
apikey := os.Getenv("VT_API_KEY")
vt, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// Check previous results
if !*forceUrl {
r, err := vt.GetUrlReport(urlname)
check(err)

// If file was previously scanned print results
switch r.Status.ResponseCode {
case 1: // Results exist
fmt.Printf("%d", r.Status.ResponseCode)
printUrlResult(r)
case -2: // Scan in progress
color.Set(color.FgHiRed)
fmt.Printf("You scan is still in progress\n")
color.Unset()
os.Exit(1)
}
}

// Scan URL
//if !*waitUrl {
report, err := vt.ScanUrl(urlname)
check(err)
color.Set(color.FgHiGreen, color.Bold)
fmt.Printf("Your URL was submitted and scan was queued. Here are details:\n\n")
color.Set(color.Reset, color.FgHiCyan)
fmt.Printf("Link: %s\n", report.Url)
fmt.Printf("VirusTotal link: %s\n\n", report.Permalink)
color.Unset()
if *waitUrl { // Wait for results if user wishes
for m := 0; m <= 600; m += 30 {
loader(fmt.Sprintf("waiting for results for %d seconds", m))
r, err := vt.GetUrlReport(urlname)
check(err)
if r.Status.ResponseCode == 1 {
fmt.Printf("scan took ~ %d seconds\n", m)
printUrlResult(r)
}
}
color.Set(color.FgHiRed)
fmt.Printf("\nSomething went wrong with VirusTotal. Maybe their servers are overloaded.\n" +
"Please try again later\n")
}
}
2 changes: 1 addition & 1 deletion vt/vt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ October, 2014.
File updated and patched by M. Moldabek, 2017.
*/
package vt
package govt

import (
"archive/tar"
Expand Down
Loading

0 comments on commit 8bba630

Please sign in to comment.