Skip to content

Commit

Permalink
Merge pull request #18 from glaslos/slavikm_merge
Browse files Browse the repository at this point in the history
Merging the slavikm fork back into master
  • Loading branch information
williballenthin authored Nov 26, 2016
2 parents 0c6f6bc + 21bb994 commit ce85749
Show file tree
Hide file tree
Showing 20 changed files with 479 additions and 543 deletions.
34 changes: 34 additions & 0 deletions API-CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Breaking API changes from version 1.0

1. Initialization
-----------------
Previously, initializing the client required creating the client with the relevant API key and other parameters:
```
// Create the client
c := govt.Client{Apikey: "api key"}
```

Now, the initialization is done via the New function with which checks that the client is initialized correctly:
```
// Create the client
c := govt.New(govt.SetErrorLog(log.New(os.Stderr, "VT: ", log.Lshortfile), govt.SetApikey(apikey), govt.SetUrl(apiurl))
```

You can provide multiple initialization functions of type govt.OptionFunc to help with the initialization.

| *Function* | *Description* | *Mandatory* |
|---------------|------------------------------------------------|-------------|
| SetApikey | Provide the API key to use | true |
| SetHttpClient | Provide a custom HTTP client | false |
| SetUrl | Provide a different URL from the default one | false |
| SetBasicAuth | Provide proxy credentials | false |
| SetErrorLog | Set error logger to write errors to | false |
| SetTraceLog | Set trace logger to dump requests / replies to | false |

2. Client implementation details
--------------------------------
Client implementation details such as internal fields are now private. This move was made so it will be easier to evolve and change the API without breaking compatibility with existing code.

3. File uploads
---------------
To improve memory footprint requirements, file uploads are now streaming using a goroutine.
2 changes: 1 addition & 1 deletion SampleClients/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Provides some example program that use the govt module.

In general all client programs get their VirusTotal API Key via an environment variable (VT_API_KEY).
Therefore you have to export VT_API_KEY before useing any of the provided examples.
Therefore you have to export VT_API_KEY before using any of the provided examples.

```export VT_API_KEY=<YOUR_API_KEY_GOES_HERE>```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ package main

import (
"encoding/json"
"fmt"
"github.com/williballenthin/govt"
//"github.com/scusi/govt"
"flag"
"fmt"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var md5 string

// init - initializes flag variables.
func init() {
Expand All @@ -38,8 +37,8 @@ func main() {
fmt.Println("-domain=<domainname> missing!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}

c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)
// get a domain report (passive dns info)
d, err := c.GetDomainReport(domain)
check(err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,21 @@ package main
import (
"flag"
"fmt"
"github.com/williballenthin/govt"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var rsrc string

func init() {
flag.StringVar(&apikey, "apikey", os.Getenv("VT_API_KEY"), "Set environment variable VT_API_KEY to your VT API Key or specify on prompt")
flag.StringVar(&apiurl, "apiurl", "https://www.virustotal.com/vtapi/v2/", "URL of the VirusTotal API to be used.")
flag.StringVar(&rsrc, "rsrc", "8ac31b7350a95b0b492434f9ae2f1cde", "resource of file to check VT for. Resource can be md5, sha-1 or sha-2 sum of a file.")
}

func getApiKeyFromEnv() (apikey string) {
apikey = os.Getenv("VT_API_KEY")
if len(apikey) == 0 {
panic("VT_API_KEY is not set!\n")
}
if len(apikey) < 64 {
panic("VT_API_KEY is to short!\n")
}
return apikey
}

func check(e error) {
if e != nil {
panic(e)
Expand All @@ -36,8 +27,9 @@ func check(e error) {

func main() {
flag.Parse()
apikey := getApiKeyFromEnv()
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

r, err := c.GetFileReport(rsrc)
check(err)
if r.ResponseCode == 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ package main

import (
"encoding/json"
"fmt"
"github.com/williballenthin/govt"
"flag"
//"github.com/scusi/govt"
"fmt"
"io/ioutil"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var rsrc string

// init - initializes flag variables.
Expand All @@ -41,18 +40,20 @@ func main() {
fmt.Println("-rsrc=<md5|sha-1|sha-2> not given!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// get a file report
r, err := c.GetFile(rsrc)
check(err)
//fmt.Printf("r: %s\n", r)
j, err := json.MarshalIndent(r, "", " ")
check(err)
fmt.Printf("FileReport: ")
os.Stdout.Write(j)
//fmt.Printf("%d %s \t%s \t%s \t%d/%d\n", r.Status.ResponseCode, r.Status.VerboseMsg, r.Resource, r.ScanDate, r.Positives, r.Total)

err = ioutil.WriteFile(rsrc, r.Content, 0600)
fmt.Printf("file %s has been written.\n", rsrc)
check(err)
fmt.Printf("file %s has been written.\n", rsrc)
}
81 changes: 81 additions & 0 deletions SampleClients/fileknownbysymantec/vtFileKnownBySymantec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// vtFileKnownBySymantec.go - checks via VirusTotal if a given file is detected by Symantec AV.
package main

import (
"crypto/md5"
"encoding/json"
"flag"
"fmt"
"io"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var rsrc string
var file string
var vtUpload bool

func init() {
flag.StringVar(&apikey, "apikey", os.Getenv("VT_API_KEY"), "Set environment variable VT_API_KEY to your VT API Key or specify on prompt")
flag.StringVar(&apiurl, "apiurl", "https://www.virustotal.com/vtapi/v2/", "URL of the VirusTotal API to be used.")
flag.StringVar(&rsrc, "rsrc", "8ac31b7350a95b0b492434f9ae2f1cde", "resource of file to check VT for. Resource can be md5, sha-1 or sha-2 sum of a file.")
flag.StringVar(&file, "file", "", "submit a file instead of a resource")
flag.BoolVar(&vtUpload, "upload-vt", false, "if 'true' files unknown to VT will be uploaded to VT")
}

// calculate md5 of a given file
func calcMd5(filename string) (md5sum string) {
f, err := os.Open(filename)
check(err)
defer f.Close()
md5 := md5.New()
_, err = io.Copy(md5, f)
return fmt.Sprintf("%x", md5.Sum(nil))
}

func check(e error) {
if e != nil {
panic(e)
}
}

func main() {
flag.Parse()
fileForError := ""
if file != "" {
rsrc = calcMd5(file)
fileForError = file
} else {
fileForError = "</path/to/file>"
}

c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

r, err := c.GetFileReport(rsrc)
check(err)
if r.ResponseCode == 0 {
fmt.Println(rsrc + " NOT KNOWN by VirusTotal")
if vtUpload == true && file != "" {
r, err := c.ScanFile(file)
check(err)
j, err := json.MarshalIndent(r, "", " ")
fmt.Printf("FileReport: ")
os.Stdout.Write(j)
} else {
fmt.Printf("For uploading to VT use vtFileScan -file=%s\n", fileForError)
}
} else {
sr := r.Scans["Symantec"]
if sr.Detected == true {
fmt.Printf("%s detected by Symantec Version %s as %s since update %s\n", rsrc, sr.Version, sr.Result, sr.Update)
} else {
fmt.Printf("%s NOT detected by Symantec; Detection Rate: [%d/%d]\n", rsrc, r.Positives, r.Total)
fmt.Printf("If you want to upload this file to VT use: 'vtFileScan -file=%s'\n", fileForError)
fmt.Printf("If you want to submit it to Symantec use: 'symantecUpload -file=%s'\n", fileForError)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import (
"encoding/json"
"flag"
"fmt"
"github.com/williballenthin/govt"
"io/ioutil"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var rsrc string

// init - initializes flag variables.
Expand All @@ -40,18 +40,17 @@ func main() {
fmt.Println("-rsrc=<md5|sha-1|sha-2> not given!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// get a file report
r, err := c.GetFileNetworkTraffic(rsrc)
check(err)
//fmt.Printf("r: %s\n", r)
j, err := json.MarshalIndent(r, "", " ")
fmt.Printf("File Network Traffic: ")
os.Stdout.Write(j)
//fmt.Printf("%d %s \t%s \t%s \t%d/%d\n", r.Status.ResponseCode, r.Status.VerboseMsg, r.Resource, r.ScanDate, r.Positives, r.Total)

err = ioutil.WriteFile(rsrc+".pcap", r.Content, 0600)
fmt.Printf("file %s has been written.\n", rsrc+".pcap")
check(err)
fmt.Printf("file %s has been written.\n", rsrc+".pcap")
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"encoding/json"
"flag"
"fmt"
"github.com/williballenthin/govt"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var rsrc string

// init - initializes flag variables.
Expand All @@ -36,14 +36,14 @@ func main() {
fmt.Println("-rsrc=<md5|sha-1|sha-2> not given!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// get a file report
r, err := c.GetFileReport(rsrc)
check(err)
//fmt.Printf("r: %s\n", r)
j, err := json.MarshalIndent(r, "", " ")
check(err)
fmt.Printf("FileReport: ")
os.Stdout.Write(j)
//fmt.Printf("%d %s \t%s \t%s \t%d/%d\n", r.Status.ResponseCode, r.Status.VerboseMsg, r.Resource, r.ScanDate, r.Positives, r.Total)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import (
"encoding/json"
"flag"
"fmt"
"github.com/williballenthin/govt"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var rsrc string

// init - initializes flag variables.
Expand All @@ -37,14 +37,13 @@ func main() {
fmt.Println("-rsrc=<md5|sha1|sha2> missing!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// get a file report
r, err := c.RescanFile(rsrc)
check(err)
//fmt.Printf("r: %s\n", r)
j, err := json.MarshalIndent(r, "", " ")
check(err)
fmt.Printf("FileReport: ")
os.Stdout.Write(j)

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ package main

import (
"encoding/json"
"fmt"
"github.com/williballenthin/govt"
//"github.com/scusi/govt"
"flag"
"fmt"
"os"

"github.com/williballenthin/govt"
)

var apikey string
var apiurl string
var domain string
var file string

// init - initializes flag variables.
Expand All @@ -37,14 +36,15 @@ func main() {
fmt.Println("-file=<fileToScan.ext> missing!")
os.Exit(1)
}
c := govt.Client{Apikey: apikey, Url: apiurl}
c, err := govt.New(govt.SetApikey(apikey), govt.SetUrl(apiurl))
check(err)

// get a file report
r, err := c.ScanFile(file)
check(err)
//fmt.Printf("r: %s\n", r)
j, err := json.MarshalIndent(r, "", " ")
check(err)
fmt.Printf("FileReport: ")
os.Stdout.Write(j)

}
Loading

0 comments on commit ce85749

Please sign in to comment.