Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
by2waysprojects committed Nov 26, 2024
1 parent ef56e03 commit ee28cb9
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
NEO4J_DB=neo4j://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=password
SERVER_PORT=8080
36 changes: 36 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"log"
"net/http"
"os"
"shellcode-db/controllers"
"shellcode-db/routes"
"shellcode-db/services"

"github.com/joho/godotenv"
)

func main() {
err := godotenv.Load()
if err != nil {
log.Fatalf("error loading file .env: %v", err)
}

port := os.Getenv("SERVER_PORT")
databaseURL := os.Getenv("NEO4J_DB")
user := os.Getenv("NEO4J_USER")
password := os.Getenv("NEO4J_PASSWORD")

neo4jService := services.NewNeo4jService(databaseURL, user, password)
defer neo4jService.Close()

apiService := services.NewExploitDbService()
dataLoaderService := services.NewDataLoaderService(apiService, neo4jService)
shellCodeController := controllers.NewShellCodeController(neo4jService, dataLoaderService)

router := routes.SetupRoutes(shellCodeController)

log.Println("Server running on http://localhost:" + port)
log.Fatal(http.ListenAndServe(":"+port, router))
}
49 changes: 49 additions & 0 deletions controllers/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package controllers

import (
"encoding/json"
"net/http"
"shellcode-db/services"

"github.com/gorilla/mux"
)

type ShellCodeController struct {
DBService *services.Neo4jService
DataLoaderService *services.DataLoaderService
}

func NewShellCodeController(dbService *services.Neo4jService, dataLoaderService *services.DataLoaderService) *ShellCodeController {
return &ShellCodeController{DBService: dbService, DataLoaderService: dataLoaderService}
}

func (sc *ShellCodeController) GetAllArchitectures(w http.ResponseWriter, r *http.Request) {
archiectures, err := sc.DBService.GetAllArchitectures()
if err != nil {
http.Error(w, "Failed to fetch architectures", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(archiectures)
}

func (sc *ShellCodeController) GetShellcodesByArchitectureID(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
architectureID := vars["id"]

shellcodes, err := sc.DBService.GetShellcodesByArchitectureID(architectureID)
if err != nil {
http.Error(w, "Failed to fetch shellcodes", http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(shellcodes)
}

func (sc *ShellCodeController) LoadData(w http.ResponseWriter, r *http.Request) {
err := sc.DataLoaderService.LoadData()
if err != nil {
http.Error(w, "Failed to load data", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("Data successfully loaded"))
}
13 changes: 13 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module shellcode-db

go 1.22.4

require (
github.com/gorilla/mux v1.8.1
github.com/neo4j/neo4j-go-driver/v5 v5.26.0
)

require (
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 // indirect
github.com/joho/godotenv v1.5.1 // indirect
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 h1:FWNFq4fM1wPfcK40yHE5UO3RUdSNPaBC+j3PokzA6OQ=
github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/neo4j/neo4j-go-driver/v5 v5.26.0 h1:GB3o4VtIGsvU+RmfgvF7L6nt1IpbPZaGtPMtPSOKmvc=
github.com/neo4j/neo4j-go-driver/v5 v5.26.0/go.mod h1:Vff8OwT7QpLm7L2yYr85XNWe9Rbqlbeb9asNXJTHO4k=
14 changes: 14 additions & 0 deletions model/shell_code.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package model

type Architecture struct {
ID string `json:"id"`
Name string `json:"name"`
Shellcodes []Shellcode `json:"shellcodes"`
}

type Shellcode struct {
ID string `json:"id"`
Name string `json:"name"`
DatePublished string `json:"date_published"`
Data string `json:"data"`
}
19 changes: 19 additions & 0 deletions routes/router.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package routes

import (
"shellcode-db/controllers"

"github.com/gorilla/mux"
)

func SetupRoutes(
shellCodeController *controllers.ShellCodeController,
) *mux.Router {
router := mux.NewRouter()

router.HandleFunc("/architectures", shellCodeController.GetAllArchitectures).Methods("GET")
router.HandleFunc("/architectures/{id}/shellcodes", shellCodeController.GetShellcodesByArchitectureID).Methods("GET")
router.HandleFunc("/load-data", shellCodeController.LoadData).Methods("POST")

return router
}
41 changes: 41 additions & 0 deletions services/data_loader_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package services

import (
"log"
)

type DataLoaderService struct {
APIService *APIService
Neo4jService *Neo4jService
}

func NewDataLoaderService(apiService *APIService, neo4jService *Neo4jService) *DataLoaderService {
return &DataLoaderService{
APIService: apiService,
Neo4jService: neo4jService,
}
}

func (dl *DataLoaderService) LoadData() error {
// Fetch Architectures from API
architectures, err := dl.APIService.FetchArchitectures()
if err != nil {
return err
}

// Insert Architectures into Neo4j
for _, architecture := range architectures {
err := dl.Neo4jService.CreateArchitecture(architecture)
if err != nil {
log.Printf("Failed to insert architecture %s: %v", architecture.ID, err)
continue
}

for _, shellcode := range architecture.Shellcodes {
if err := dl.Neo4jService.CreateShellcodeWithArchitecture(architecture.ID, shellcode); err != nil {
log.Printf("Failed to insert shellcode %s: %v", shellcode.ID, err)
}
}
}
return nil
}
64 changes: 64 additions & 0 deletions services/exploit_db_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package services

import (
"fmt"
"io"
"net/http"
"shellcode-db/model"
services "shellcode-db/services/model"

"github.com/gocarina/gocsv"
)

type APIService struct{}

func NewExploitDbService() *APIService {
return &APIService{}
}

func (api *APIService) FetchArchitectures() ([]model.Architecture, error) {
url := "https://gitlab.com/exploit-database/exploitdb/-/raw/main/files_shellcodes.csv"
response, err := http.Get(url)
if err != nil {
return nil, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", response.StatusCode)
}

var shellcodesExploitDB []services.Shellcode
body, _ := io.ReadAll(response.Body)

if err := gocsv.UnmarshalBytes(body, &shellcodesExploitDB); err != nil {
return nil, err
}

var shellcodes []model.Architecture
mapArchitectureShell := map[string][]model.Shellcode{}

for _, shell := range shellcodesExploitDB {
fileUrl := fmt.Sprintf("https://gitlab.com/exploit-database/exploitdb/-/raw/main/%s", shell.File)
response, err := http.Get(fileUrl)
if err != nil {
continue
}

if response.StatusCode != http.StatusOK {
continue
}

body, _ := io.ReadAll(response.Body)
response.Body.Close()

mapArchitectureShell[shell.Platform] = append(mapArchitectureShell[shell.Platform],
model.Shellcode{ID: shell.Id, Name: shell.Description, DatePublished: shell.DatePublished, Data: string(body)})
}

for key, value := range mapArchitectureShell {
shellcodes = append(shellcodes, model.Architecture{ID: key, Name: key, Shellcodes: value})
}

return shellcodes, nil
}
10 changes: 10 additions & 0 deletions services/model/shell_code_exploit_db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package services

type Shellcode struct {
Id string `csv:"id"`
Platform string `csv:"platform"`
SourceURL string `csv:"source_url"`
DatePublished string `csv:"date_published"`
Description string `csv:"description"`
File string `csv:"file"`
}
127 changes: 127 additions & 0 deletions services/neo4j_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package services

import (
"context"
"log"
"shellcode-db/model"

"github.com/neo4j/neo4j-go-driver/v5/neo4j"
)

type Neo4jService struct {
Driver neo4j.DriverWithContext
}

func NewNeo4jService(uri, username, password string) *Neo4jService {
driver, err := neo4j.NewDriverWithContext(uri, neo4j.BasicAuth(username, password, ""))
if err != nil {
log.Fatalf("Failed to create Neo4j driver: %v", err)
}
return &Neo4jService{Driver: driver}
}

func (s *Neo4jService) Close() {
s.Driver.Close(context.Background())
}

func (s *Neo4jService) GetAllArchitectures() ([]model.Architecture, error) {
ctx := context.Background()
session := s.Driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead})
defer session.Close(ctx)

architectures := []model.Architecture{}
_, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
result, err := tx.Run(ctx, "MATCH (p:Architecture) RETURN p.id AS id, p.name AS name", nil)
if err != nil {
return nil, err
}

for result.Next(ctx) {
record := result.Record()
architecture := model.Architecture{
ID: record.Values[0].(string),
Name: record.Values[1].(string),
}
architectures = append(architectures, architecture)
}
return nil, result.Err()
})

return architectures, err
}

func (s *Neo4jService) GetShellcodesByArchitectureID(architectureID string) ([]model.Shellcode, error) {
ctx := context.Background()
session := s.Driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeRead})
defer session.Close(ctx)

shellcodes := []model.Shellcode{}
_, err := session.ExecuteRead(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
query := `
MATCH (p:Architecture {id: $architectureID})-[:HAS_CHILD]->(c:Shellcode)
RETURN c.id AS id, c.name AS name, c.datePublished as datePublished, c.data as data
`
params := map[string]interface{}{"architectureID": architectureID}
result, err := tx.Run(ctx, query, params)
if err != nil {
return nil, err
}

for result.Next(ctx) {
record := result.Record()
shellcode := model.Shellcode{
ID: record.Values[0].(string),
Name: record.Values[1].(string),
DatePublished: record.Values[2].(string),
Data: record.Values[3].(string),
}
shellcodes = append(shellcodes, shellcode)
}
return nil, result.Err()
})

return shellcodes, err
}

func (s *Neo4jService) CreateArchitecture(architecture model.Architecture) error {
ctx := context.Background()
session := s.Driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
defer session.Close(ctx)

_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
query := `
MERGE (p:Architecture {id: $id})
SET p.name = $name
`
params := map[string]interface{}{"id": architecture.ID, "name": architecture.Name}
_, err := tx.Run(ctx, query, params)
return nil, err
})
return err
}

func (s *Neo4jService) CreateShellcodeWithArchitecture(architectureID string, shellcode model.Shellcode) error {
ctx := context.Background()
session := s.Driver.NewSession(ctx, neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
defer session.Close(ctx)

_, err := session.ExecuteWrite(ctx, func(tx neo4j.ManagedTransaction) (interface{}, error) {
query := `
MERGE (c:Shellcode {id: $shellcodeID})
SET c.name = $shellcodeName, c.datePublished = $datePublished, c.data = $data
WITH c
MATCH (p:Architecture {id: $architectureID})
MERGE (p)-[:HAS_CHILD]->(c)
`
params := map[string]interface{}{
"architectureID": architectureID,
"shellcodeID": shellcode.ID,
"shellcodeName": shellcode.Name,
"datePublished": shellcode.DatePublished,
"data": shellcode.Data,
}
_, err := tx.Run(ctx, query, params)
return nil, err
})
return err
}

0 comments on commit ee28cb9

Please sign in to comment.