Skip to content
This repository has been archived by the owner on Jan 13, 2023. It is now read-only.

Commit

Permalink
Added c2 blacklist capability
Browse files Browse the repository at this point in the history
  • Loading branch information
alessio-perugini committed Oct 13, 2020
1 parent b95fbed commit cc9c519
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 80 deletions.
5 changes: 3 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

var (
config = stanislav.Config{
NumberOfBin: 128,
NumberOfBin: 16,
SizeBitmap: 1024,
InfluxUrl: "http://localhost",
InfluxPort: 9999,
Expand Down Expand Up @@ -45,7 +45,7 @@ func init() {
flag.IntVar(&stanislav.NTwToCompare, "nCompare", 3, "number o time windows to compare to evaluate a possible periodicity")
flag.StringVar(&stanislav.IpAddrNF, "ip", "", "ip of netflow collector")
flag.StringVar(&stanislav.PortNF, "port", "2055", "port of netflow collector")
flag.IntVar(&stanislav.Verbose, "verbose", 0, "verbosity level. (1=low,2=medium,3=high")
flag.UintVar(&config.Verbose, "verbose", 0, "verbosity level. (1=low,2=medium,3=high")

//Bitmap
flag.UintVar(&config.NumberOfBin, "bin", 16, "number of bin in your bitmap")
Expand All @@ -67,6 +67,7 @@ func init() {
flag.StringVar(&config.Ja3BlackListFile, "ja3", "", "file path of malicious ja3 fingerprints")
flag.StringVar(&config.GeoIpDb, "geoip", "", "file path of geoip db")
flag.StringVar(&config.OfflinePcap, "pcap", "", "pcap file to read")
flag.StringVar(&config.IpBlackListFile,"c2","", "file path of malicious ip")
}

func flagConfig() {
Expand Down
54 changes: 20 additions & 34 deletions inspection.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package stanislav

import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
_ "github.com/google/gopacket/layers" //Used to init internal struct
Expand All @@ -10,7 +9,6 @@ import (
"net"
"stanislav/pkg/ja3"
"stanislav/pkg/portbitmap"
"time"
)

var myIPs = make([]net.IP, 0, 2)
Expand Down Expand Up @@ -48,15 +46,22 @@ func (p *Peng) inspect(packet gopacket.Packet) {

if p.Config.Verbose == 3 {
if packetDestToMyPc {
fmt.Printf("[%s] server traffic: %s \n", time.Now().Local().String(), tcp.DstPort.String())
logger.Printf("server traffic: %s \n", tcp.DstPort.String())
} else {
fmt.Printf("[%s] client traffic: %s \n", time.Now().Local().String(), tcp.DstPort.String())
logger.Printf("client traffic: %s \n", tcp.DstPort.String())
}
}
}
}

GeoIpSearch(externalIp, p.Config.GeoIpDb)

//BLACKLISTED c2 Server
if name, ok := blackListIp[externalIp]; ok {
AddPossibleThreat(externalIp, "c2 server " + name)
logger.Printf("[%s] appears in the blocked c2 list as %s!\n", externalIp, name)
}

externalIp = ipv4.SrcIP.String() + "/" + ipv4.DstIP.String() //TODO

if len(ja3BlackList) != 0 {
Expand All @@ -66,56 +71,37 @@ func (p *Peng) inspect(packet gopacket.Packet) {

if p.Config.Verbose == 2 {
if ja3md5 != "" {
fmt.Printf("J: %s\n", ja3md5)
logger.Printf("J: %s\n", ja3md5)
}
if ja3smd5 != "" {
fmt.Printf("JS: %s\n", ja3smd5)
logger.Printf("JS: %s\n", ja3smd5)
}
}

//TODO improvmenet external IP detection, especially in offline mode! Maybe loading a filtering list
if name, ok := ja3BlackList[ja3md5]; ok {
AddPossibleThreat(externalIp, "ja3 blocklist "+name)
fmt.Printf("[%s] %s appears in the blocked Ja3 list as %s!\n", externalIp, ja3md5, name)
logger.Printf("[%s] %s appears in the blocked Ja3 list as %s!\n", externalIp, ja3md5, name)
}
if name, ok := ja3BlackList[ja3smd5]; ok {
AddPossibleThreat(externalIp, "ja3s blocklist "+name)
fmt.Printf("[%s] %s appears in the blocked Ja3 list as %s!\n", externalIp, ja3smd5, name)
logger.Printf("[%s] %s appears in the blocked Ja3 list as %s!\n", externalIp, ja3smd5, name)
}


//TODO add TLS version check
//TLS cipher security check
switch ja3.Security {
case 1:
AddPossibleThreat(externalIp, "Weak tls cipher")
fmt.Println("Weak tls cipher")
logger.Println("Weak tls cipher")
case 2:
AddPossibleThreat(externalIp, "Insecure tls cipher")
fmt.Println("Insecure tls cipher")
logger.Println("Insecure tls cipher")
}
}

//TODO add http numeric ip

// switch hello.CipherSuite {
// case 49169: fallthrough /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
// case 5: fallthrough /* TLS_RSA_WITH_RC4_128_SHA */
// case 4: Security = 2 /* TLS_RSA_WITH_RC4_128_MD5 */
// /* WEAK */
// case 157: fallthrough /* TLS_RSA_WITH_AES_256_GCM_SHA384 */
// case 61: fallthrough /* TLS_RSA_WITH_AES_256_CBC_SHA256 */
// case 53: fallthrough /* TLS_RSA_WITH_AES_256_CBC_SHA */
// case 132: fallthrough /* TLS_RSA_WITH_CAMELLIA_256_CBC_SHA */
// case 156: fallthrough /* TLS_RSA_WITH_AES_128_GCM_SHA256 */
// case 60: fallthrough /* TLS_RSA_WITH_AES_128_CBC_SHA256 */
// case 47: fallthrough /* TLS_RSA_WITH_AES_128_CBC_SHA */
// case 65: fallthrough /* TLS_RSA_WITH_CAMELLIA_128_CBC_SHA */
// case 49170: fallthrough /* TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA */
// case 22: fallthrough /* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */
// case 10: fallthrough /* TLS_RSA_WITH_3DES_EDE_CBC_SHA */
// case 150: fallthrough /* TLS_RSA_WITH_SEED_CBC_SHA */
// case 7: Security = 1 /* TLS_RSA_WITH_IDEA_CBC_SHA */
// default: Security = 0
// }
}

func GeoIpSearch(ip, dbPath string) {
Expand All @@ -128,7 +114,7 @@ func GeoIpSearch(ip, dbPath string) {
parsedIp := net.ParseIP(ip)
record, err := db.Country(parsedIp)
if err != nil {
log.Println(err)
logger.Println(err)
}

if record.Country.IsoCode != "" {
Expand All @@ -148,14 +134,14 @@ func (p *Peng) PortScanningHandler(port uint16, incomingPck bool) {
func addPortToBitmap(port uint16, pBitmap *portbitmap.PortBitmap) {
err := pBitmap.AddPort(port)
if err != nil {
log.Println(err.Error())
logger.Println(err.Error())
}
}

func getMyIp() {
addrs, err := net.InterfaceAddrs()
if err != nil {
log.Fatal(err.Error())
logger.Fatal(err.Error())
}

for _, a := range addrs {
Expand Down
10 changes: 6 additions & 4 deletions live_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,17 @@ type proto interface {
var PossibleThreat = make(map[string][]string)

func LiveMode() {
var (
wg sync.WaitGroup
signalCh = make(chan os.Signal, 1)
)
var wg sync.WaitGroup
var signalCh = make(chan os.Signal, 1)

opts = GetOptions()
runtime.GOMAXPROCS(opts.getCPU())
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGTERM)
logger = opts.Logger

//BlacklistModule
LoadBlockListedC2()

netflow9 := NewNetflowV9()
peng := New(Conf)
protos := []proto{netflow9, peng}
Expand Down
17 changes: 13 additions & 4 deletions logic.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package stanislav
import (
"encoding/json"
"fmt"
"log"
"math"
"time"
)
Expand Down Expand Up @@ -72,6 +71,16 @@ func InspectFlow(rf RawFlow) {
!ExcludeMultiAndBroadcast(rf.Ipv4SrcAddr) && !ExcludeMultiAndBroadcast(rf.Ipv4DstAddr)) {
return
}
//TODO create a function that handles C2 server blocklist
if name, ok := blackListIp[rf.Ipv4DstAddr]; ok {
AddPossibleThreat(rf.Ipv4DstAddr, "c2 server " + name)
logger.Printf("[%s] appears in the blocked c2 list as %s!\n", rf.Ipv4DstAddr, name)
}

if name, ok := blackListIp[rf.Ipv4SrcAddr]; ok {
AddPossibleThreat(rf.Ipv4SrcAddr, "c2 server " + name)
logger.Printf("[%s] appears in the blocked c2 list as %s!\n", rf.Ipv4SrcAddr, name)
}

//https://tools.ietf.org/html/rfc5102#section-5
if rf.EndReason == 2 {
Expand Down Expand Up @@ -134,10 +143,10 @@ func ChangePeriodicStatus(key string, fi *FlowInfo, v bool) {
}

if v && !fi.CurrentlyPeriodic {
AddPossibleThreat(key, fmt.Sprintf(" periodic frequency: %.2fs seen %d times.", fi.TWDuration, fi.PeriodicityCounter))
log.Printf("%s \tbecame periodic! Seen %d times. Frequency: %.2fs ", key, fi.PeriodicityCounter, fi.TWDuration)
AddPossibleThreat(key, fmt.Sprintf("periodic frequency: %.2fs seen %d times.", fi.TWDuration, fi.PeriodicityCounter))
logger.Printf("%s \tbecame periodic! Seen %d times. Frequency: %.2fs ", key, fi.PeriodicityCounter, fi.TWDuration)
} else {
log.Printf("%s \tnot periodic anymore! Seen %d times. Frequency: %.2fs ", key, fi.PeriodicityCounter, fi.TWDuration)
logger.Printf("%s \tnot periodic anymore! Seen %d times. Frequency: %.2fs ", key, fi.PeriodicityCounter, fi.TWDuration)
}

fi.CurrentlyPeriodic = v
Expand Down
2 changes: 1 addition & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var (
Conf *Config
logger *log.Logger
PercentageDeviation = 5.0
Verbose = 0
blackListIp = make(map[string]string)
)

var (
Expand Down
34 changes: 11 additions & 23 deletions peng.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/google/gopacket"
_ "github.com/google/gopacket/layers" //Used to init internal struct
"github.com/google/gopacket/pcap"
"log"
"os"
"stanislav/pkg/portbitmap"
"time"
Expand Down Expand Up @@ -36,6 +35,7 @@ type Config struct {
Ja3BlackListFile string
GeoIpDb string
OfflinePcap string
IpBlackListFile string
}

var ja3BlackList map[string]string
Expand Down Expand Up @@ -73,11 +73,10 @@ func (p *Peng) run() {
}

if err != nil {
log.Fatal(err)
logger.Fatal(err)
}
defer pHandle.Close()

//go func() {
packet := gopacket.NewPacketSource(pHandle, pHandle.LinkType())

time.AfterFunc(p.Config.TimeFrame, p.handler)
Expand All @@ -87,17 +86,6 @@ func (p *Peng) run() {
}
p.inspect(packet)
}
//}()

/*
sig := make(chan os.Signal, 1024)
signal.Notify(sig, os.Interrupt)
<-sig
log.Println("Quitting Peng, bye!")
for k, v := range topCountryVisit {
fmt.Printf("[%s] %d visit.\n", k, v)
}*/
}

func (p *Peng) shutdown() {
Expand All @@ -106,7 +94,7 @@ func (p *Peng) shutdown() {
time.Sleep(1 * time.Second)

//TODO
fmt.Println("\nTOP COUNTRY VISIT")
logger.Println("\n\nTOP COUNTRY VISIT")
threatJson, _ := json.Marshal(topCountryVisit)
fmt.Println(string(threatJson))
}
Expand All @@ -116,7 +104,7 @@ func (p *Peng) LoadBlackListJa3InMemory() {
defer file.Close()

if err != nil {
log.Println(err)
logger.Println(err)
return
}

Expand All @@ -141,29 +129,29 @@ func (p *Peng) PrintAllInfo() {
allPortTraffic := []*portbitmap.PortBitmap{p.ClientTraffic, p.ServerTraffic}
for i, v := range allPortTraffic {
if p.Config.Verbose == 3 {
fmt.Println(v) //Print all bitmap
fmt.Println("Bit set: ")
logger.Println(v) //Print all bitmap
logger.Println("Bit set: ")
for i := 0; i < len(v.InnerBitmap); i++ {
fmt.Println("bin number [", i, "] num (bit at 1): ", v.InnerBitmap[i].GetBitSets())
logger.Println("bin number [", i, "] num (bit at 1): ", v.InnerBitmap[i].GetBitSets())
}
}
if p.Config.Verbose >= 1 {
if i == 0 {
fmt.Printf("[%s] [CLIENT] ", time.Now().Local().String())
logger.Printf("[CLIENT] ")
} else {
fmt.Printf("[%s] [SERVER] ", time.Now().Local().String())
logger.Printf("[SERVER] ")
}
}
if p.Config.Verbose >= 2 {
fmt.Printf("entropy of each bin: %f\n", v.EntropyOfEachBin())
logger.Printf("entropy of each bin: %f\n", v.EntropyOfEachBin())
}

totalEntroy := v.EntropyTotal()
if totalEntroy >= 0.5 {
AddPossibleThreat("general", fmt.Sprintf("probably a port scan. Total entropy: %.2f", totalEntroy))
}
if p.Config.Verbose >= 1 {
fmt.Printf("total entropy: %f\n", totalEntroy)
logger.Printf("total entropy: %f\n", totalEntroy)
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/csv"
"fmt"
influxdb2 "github.com/influxdata/influxdb-client-go"
"log"
"os"
"time"
)
Expand Down Expand Up @@ -34,7 +33,7 @@ func (p *Peng) PushToInfluxDb() {
writeApi.Flush() // Force all unwritten data to be sent

if p.Config.Verbose == 3 {
fmt.Printf("[%s] file successfully pushed to influxdb\n", time.Now().Local().String())
logger.Printf("[%s] file successfully pushed to influxdb\n", time.Now().Local().String())
}
}

Expand All @@ -46,7 +45,7 @@ func (p *Peng) ExportToCsv() {
// 1. Open the file
file, err := os.OpenFile(p.Config.SaveFilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0777)
if err != nil {
log.Println("error opening csv file", err.Error())
logger.Println("error opening csv file", err.Error())
}

defer file.Close()
Expand All @@ -59,15 +58,15 @@ func (p *Peng) ExportToCsv() {
// 3. Write all the records
err = writer.WriteAll(csvData) // returns error
if err != nil {
log.Println("error on writing csv data ", err.Error())
logger.Println("error on writing csv data ", err.Error())
return
}
err = file.Chown(65534, 65534)
if err != nil {
fmt.Println(err.Error())
logger.Println(err.Error())
}

if p.Config.Verbose == 3 {
fmt.Printf("[%s] data successfully exported to csv\n", time.Now().Local().String())
logger.Printf("[%s] data successfully exported to csv\n", time.Now().Local().String())
}
}
Loading

0 comments on commit cc9c519

Please sign in to comment.