Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 93a5ce069d | |||
| 85f315dafe | |||
| e05b54fb29 | |||
| 7a6ae01254 | |||
| 02ef2f78fb | |||
| 473bdbff0b |
@@ -1 +1,2 @@
|
|||||||
.idea/*
|
.idea/*
|
||||||
|
build/*
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
txt
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 966 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -0,0 +1,53 @@
|
|||||||
|
# Makefile for Dehasher
|
||||||
|
|
||||||
|
# Go command
|
||||||
|
GO=go
|
||||||
|
|
||||||
|
# Binary name
|
||||||
|
BINARY_NAME=dehasher
|
||||||
|
|
||||||
|
# Build directory
|
||||||
|
BUILD_DIR=build/bin
|
||||||
|
|
||||||
|
# Platforms to build for
|
||||||
|
PLATFORMS=linux darwin windows
|
||||||
|
|
||||||
|
# Architecture to build for
|
||||||
|
ARCHS=amd64 arm64
|
||||||
|
|
||||||
|
# Version info from git tag or default
|
||||||
|
VERSION=$(shell git describe --tags 2>/dev/null || echo "v1.0.1")
|
||||||
|
|
||||||
|
.PHONY: all clean build build-all
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all: clean build-all
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
|
mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
# Build for current platform
|
||||||
|
build:
|
||||||
|
$(GO) build -o $(BUILD_DIR)/$(BINARY_NAME) -ldflags "-X main.version=$(VERSION)" dehasher.go
|
||||||
|
|
||||||
|
# Build for all platforms
|
||||||
|
build-all: clean
|
||||||
|
@for platform in $(PLATFORMS); do \
|
||||||
|
for arch in $(ARCHS); do \
|
||||||
|
echo "Building for $$platform/$$arch..."; \
|
||||||
|
GOOS=$$platform GOARCH=$$arch $(GO) build -o $(BUILD_DIR)/$(BINARY_NAME)-$$platform-$$arch -ldflags "-X main.version=$(VERSION)" dehasher.go; \
|
||||||
|
if [ "$$platform" = "windows" ]; then \
|
||||||
|
mv $(BUILD_DIR)/$(BINARY_NAME)-$$platform-$$arch $(BUILD_DIR)/$(BINARY_NAME)-$$platform-$$arch.exe; \
|
||||||
|
fi; \
|
||||||
|
done; \
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install locally
|
||||||
|
install: build
|
||||||
|
cp $(BUILD_DIR)/$(BINARY_NAME) /usr/local/bin/
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
test:
|
||||||
|
$(GO) test ./...
|
||||||
@@ -1,69 +1,36 @@
|
|||||||
# Dehasher
|
# 🚀 Dehasher
|
||||||
## A cli tool built for interaction with the Dehash API
|
### A CLI tool for seamless interaction with the Dehashed API
|
||||||
|
|
||||||
<div align="center">
|
---
|
||||||
<img src="https://img.wanman.io/fUSu0/SaCUyEMe87.png/raw" style="width: 350px; height: auto" alt="Ar1ste1a" title="Ar1ste1a Offensive Security">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
# Features
|
## 🌟 Features
|
||||||
- Output Format Control
|
- **Output Format Control**: JSON, YAML, XML, and TEXT support.
|
||||||
- Request Limiting
|
- **Regex & Wildcard Matching**: Flexible query options.
|
||||||
- Record Limiting
|
- **Local Database Storage**: Default or custom paths.
|
||||||
- Regular Expression Handling
|
- **Database Querying**: Raw SQL and filtered queries.
|
||||||
- Exact Match Handling
|
- **Enhanced Logging**: Easy log parsing and rotation.
|
||||||
- Error Handling
|
- **Error Handling**: Intelligent API error management.
|
||||||
- Credential Dumping
|
- **WhoIs Lookups**: Domain, IP, MX, NS, and more.
|
||||||
- Intelligent Token Usage
|
- **Subdomain Scanning**: Identify subdomains.
|
||||||
- Database Path Configuration
|
- **Robust Logging**: Detailed logs for debugging.
|
||||||
# Options
|
- **API Key Management**: Securely store and manage API keys.
|
||||||
|
- **Formatted Output**: Easy to read and understand.
|
||||||
|
- **Intuitive Database Querying**: Query for specific information.
|
||||||
|
|
||||||
```bash-session
|
---
|
||||||
usage: Dehasher [-h --help] {-k --key} {-a --authorized-email} [-h --help] [-m --max-records] [-r --max-requests] [-B --print-balance] [-X --exact-match] [-R --regex-match] [-t --list-tokens] [-o --output-file-name] [-T --output-txt] [-J --output-json] [-Y --output-yaml] [-x --output-xml] [-U --username-query] [-E --email-query] [-I --ip-address-query] [-P --password-query] [-Q --hashed-password-query] [-N --name-query] [-C --creds-only]
|
|
||||||
|
|
||||||
Dehashed Tool
|
## 📦 Installation
|
||||||
|
|
||||||
options:
|
Clone the repository and build the tool:
|
||||||
-h --help show this help message and exit
|
```bash
|
||||||
-m --max-records Maximum amount of records to return
|
git clone https://github.com/Ar1ste1a/Dehasher.git
|
||||||
-r --max-requests Maximum number of requests to make
|
cd Dehasher
|
||||||
-B --print-balance Print remaining balance after requests
|
go build dehasher.go
|
||||||
-X --exact-match Use Exact Matching on fields
|
|
||||||
-R --regex-match Use Regex Matching on fields
|
|
||||||
-t --list-tokens List the number of tokens remaining
|
|
||||||
-o --output-file-name File to output results to
|
|
||||||
-T --output-txt Output to text file
|
|
||||||
-J --output-json Output to JSON file
|
|
||||||
-Y --output-yaml Output to YAML file
|
|
||||||
-x --output-xml Output to XML file
|
|
||||||
-U --username-query Username Query
|
|
||||||
-E --email-query Email Query
|
|
||||||
-I --ip-address-query IP Address Query
|
|
||||||
-P --password-query Password Query
|
|
||||||
-Q --hashed-password-query Hashed Password Query
|
|
||||||
-N --name-query Name Query
|
|
||||||
-C --creds-only Return Credentials Only
|
|
||||||
-k --key API Key
|
|
||||||
-a --authorized-email Email to pair with key for authentication
|
|
||||||
--local-db Use local database in current directory
|
|
||||||
|
|
||||||
|
|
||||||
v1.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
# Sample Run
|
<hr></hr>
|
||||||
```bash-session
|
|
||||||
-k ddq<redacted> -a ar1ste1a@<redacted> -E @example.com -C -o example_creds
|
|
||||||
Making 3 Requests for 10000 Records (30000 Total)
|
|
||||||
[*] Performing Request...
|
|
||||||
[*] Retrieved 60 Records
|
|
||||||
[-] Not Enough Entries, ending queries
|
|
||||||
[+] Discovered 60 Records
|
|
||||||
[*] Writing entries file: example_creds.json
|
|
||||||
[*] Success
|
|
||||||
|
|
||||||
```
|
## 🔰 Getting Started
|
||||||
|
|
||||||
# Getting Started
|
|
||||||
|
|
||||||
To begin, clone the repository
|
To begin, clone the repository
|
||||||
``` bash-session
|
``` bash-session
|
||||||
@@ -72,13 +39,26 @@ cd Dehasher
|
|||||||
go build dehasher.go
|
go build dehasher.go
|
||||||
```
|
```
|
||||||
|
|
||||||
# Database Configuration
|
<hr></hr>
|
||||||
|
|
||||||
|
## 🛠️ Initial Setup
|
||||||
|
|
||||||
|
Dehasher requires an API key from Dehashed. Set it up with:
|
||||||
|
```bash
|
||||||
|
ar1ste1a@kali:~$ dehasher set-key <redacted>
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr></hr>
|
||||||
|
|
||||||
|
## 🗄️ Database Configuration
|
||||||
|
|
||||||
Dehasher supports two database storage options:
|
Dehasher supports two database storage options:
|
||||||
|
|
||||||
1. **Default Path** (default): Stores the database at `~/.local/share/Dehasher/db/dehashed.sqlite`
|
1. **Default Path** (default): Stores the database at `~/.local/share/Dehasher/db/dehashed.sqlite`
|
||||||
2. **Local Path**: Stores the database in the current directory as `./dehasher.sqlite`
|
2. **Local Path**: Stores the database in the current directory as `./dehasher.sqlite`
|
||||||
|
|
||||||
|
The **Local Path** option allows for separate databases for different projects or engagements.
|
||||||
|
|
||||||
To configure the database location:
|
To configure the database location:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -89,61 +69,207 @@ To configure the database location:
|
|||||||
./dehasher set-local-db false
|
./dehasher set-local-db false
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also specify the database location when running commands:
|
<hr></hr>
|
||||||
|
|
||||||
```bash
|
## 🔍 Crafting Queries
|
||||||
# Use local database for this command only
|
|
||||||
./dehasher -k YOUR_API_KEY -a YOUR_EMAIL -E @example.com --local-db
|
|
||||||
```
|
|
||||||
|
|
||||||
# Crafting a query
|
### Simple Query
|
||||||
|
Dehasher can be used simply for example to query for credentials matching a given email domain.
|
||||||
## Simple Query
|
|
||||||
``` go
|
``` go
|
||||||
# Provide credentials for emails matching @target.com
|
# Provide credentials for emails matching @target.com
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -E @target.com
|
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -E @target.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Simple Credentials Query
|
### Simple Credentials Query
|
||||||
|
Dehasher can also be used to return only credentials for a given query.
|
||||||
``` go
|
``` go
|
||||||
# Provide credentials for emails matching @target.com
|
# Provide credentials for emails matching @target.com
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -E @target.com -C
|
dehasher -E @target.com -C
|
||||||
```
|
```
|
||||||
|
|
||||||
## Simple Query Returning Balance
|
### Multiple Match Query
|
||||||
|
Dehasher is capable of handling multiple queries for the same field.
|
||||||
|
This is useful for when you want to search for multiple domains, or multiple usernames.
|
||||||
``` go
|
``` go
|
||||||
# Provide credentials for emails matching @target.com
|
# Provide credentials for emails matching @target.com and @target2.com
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -E @target.com -C -B
|
dehasher -E @target.com,@target2.com -C
|
||||||
```
|
```
|
||||||
|
|
||||||
## Regex Query
|
### Wildcard Query
|
||||||
|
Dehasher is capable of handling wildcard queries.
|
||||||
|
A wildcard query cannot begin with a wildcard.
|
||||||
|
This is a limitation of the Dehashed API.
|
||||||
|
An asterisk can be used to denote multiple characters, and a question mark can be used to denote a single character.
|
||||||
|
``` go
|
||||||
|
# Provide credentials for emails matching @target.com and @target2.com
|
||||||
|
dehasher -E @target?.com -C -W
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Regex Query
|
||||||
|
Dehasher is capable of handling regex queries.
|
||||||
|
Simply denote regex queries with the `-R` flag.
|
||||||
|
Place all regex queries in quotes with the corresponding query flag in single quotes.
|
||||||
``` go
|
``` go
|
||||||
# Return matches for emails matching this given regex query
|
# Return matches for emails matching this given regex query
|
||||||
# -R e: Specify the '-E' field as a regex entry
|
dehasher -R -e '[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)?@target.com'
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -E '[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)?@target.com' -C -B -R e
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Exact Match Query
|
### Output Text (default JSON)
|
||||||
``` go
|
Dehasher is capable of handling output formats.
|
||||||
# Return matches for usernames exactly matching "admin"
|
The default output format is JSON.
|
||||||
# -X u: Specify the '-U' field as an exact match entry
|
To change the output format, use the `-f` flag.
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -C -B -U admin -X u
|
Dehasher currently supports JSON, YAML, XML, and TEXT output formats.
|
||||||
```
|
|
||||||
|
|
||||||
## Output Text (default JSON)
|
|
||||||
``` go
|
``` go
|
||||||
# Return matches for usernames exactly matching "admin" and write to text file 'admins_file.txt'
|
# Return matches for usernames exactly matching "admin" and write to text file 'admins_file.txt'
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -C -B -U admin -X u -T -o admins_file
|
dehasher -U admin -o admins_file -f txt
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output YAML
|
<hr></hr>
|
||||||
``` go
|
|
||||||
# Return matches for usernames exactly matching "admin" and write to yaml file 'admins_file.yaml'
|
## 🌐 WhoIs Lookups
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -C -B -U admin -X u -Y -o admins_file
|
Dehasher supports WHOIS lookups, history searches, reverse WHOIS searches, IP lookups, MX lookups, NS lookups, and subdomain scans.
|
||||||
|
The WhoIs Lookups require a separate API Credit from the Dehashed API.
|
||||||
|
|
||||||
|
### Domain Lookup
|
||||||
|
```bash
|
||||||
|
# Perform a WHOIS lookup for example.com
|
||||||
|
dehasher whois -d example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output XML
|
### History Lookup
|
||||||
``` go
|
History Lookups require 25 credits.
|
||||||
# Return matches for usernames exactly matching "admin" and write to xml file 'admins_file.xml'
|
This is a Dehashed API limitation.
|
||||||
dehasher -k ddq<redacted> -a ar1ste1a@domain.tld -C -B -U admin -X u -x -o admins_file
|
```bash
|
||||||
|
# Perform a WHOIS history search for example.com
|
||||||
|
dehasher whois -d example.com -H
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Reverse WHOIS Lookup
|
||||||
|
```bash
|
||||||
|
# Perform a reverse WHOIS lookup for example.com
|
||||||
|
dehasher whois -I example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### IP Lookup
|
||||||
|
```bash
|
||||||
|
# Perform a reverse IP lookup for 8.8.8.8
|
||||||
|
dehasher whois -i 8.8.8.8
|
||||||
|
```
|
||||||
|
|
||||||
|
### MX Lookup
|
||||||
|
```bash
|
||||||
|
# Perform a reverse MX lookup for google.com
|
||||||
|
dehasher whois -m google.com
|
||||||
|
```
|
||||||
|
### NS Lookup
|
||||||
|
```bash
|
||||||
|
# Perform a reverse NS lookup for google.com
|
||||||
|
dehasher whois -n google.com
|
||||||
|
```
|
||||||
|
### Subdomain Scan
|
||||||
|
```bash
|
||||||
|
# Perform a WHOIS subdomain scan for google.com
|
||||||
|
dehasher whois -d google.com -s
|
||||||
|
```
|
||||||
|
|
||||||
|
<hr></hr>
|
||||||
|
|
||||||
|
## 📊 Database Querying
|
||||||
|
Dehasher stores query results in a local database.
|
||||||
|
This database can be queried for previous results.
|
||||||
|
This database also includes WhoIs Information and Subdomain Scan results, but does **not** include historical lookups.
|
||||||
|
|
||||||
|
## Simple Query
|
||||||
|

|
||||||
|
|
||||||
|
Dehasher supports querying the database for previous results.
|
||||||
|
This is useful for when you want to query for specific information.
|
||||||
|
```bash
|
||||||
|
# Query the database for all results containing the word 'admin' in the username
|
||||||
|
dehasher query -t results -q "username LIKE '%admin%'"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Raw SQL Queries
|
||||||
|

|
||||||
|
|
||||||
|
Dehasher also supports raw SQL queries. This is useful for when you want to query for specific information.
|
||||||
|
```bash
|
||||||
|
# Query the database for all results containing the word 'admin' in the username
|
||||||
|
dehasher query -r "SELECT * FROM results WHERE username LIKE '%admin%'"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query Options
|
||||||
|
Dehasher supports a number of query options. These options can be used to filter the results of a query.
|
||||||
|
```bash
|
||||||
|
# Query the database for all results containing the word 'admin' in the username
|
||||||
|
dehasher query -t results -q "username LIKE '%admin%'" -n username,email,password
|
||||||
|
```
|
||||||
|
|
||||||
|
## Listing Tables and Columns
|
||||||
|
Dehasher supports listing all available tables and columns.
|
||||||
|
This is useful for when you want to query for specific information.
|
||||||
|
```bash
|
||||||
|
# List all available tables and columns
|
||||||
|
dehasher query -a
|
||||||
|
```
|
||||||
|
|
||||||
|
The current tables available for query are:
|
||||||
|
- results
|
||||||
|
- creds
|
||||||
|
- whois
|
||||||
|
- subdomains
|
||||||
|
- history
|
||||||
|
- runs
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Exporting Results
|
||||||
|
Dehasher supports exporting results to a file.
|
||||||
|
This is useful for when you want to requery for specific information without touching the Dehashed API.
|
||||||
|
The export subcommand supports all the same options as the query subcommand.
|
||||||
|
The export subcommand also supports file naming and output format control.
|
||||||
|
```bash
|
||||||
|
# Export all results containing the word 'admin' in the username to a text file
|
||||||
|
dehasher export -t results -q "username LIKE '%admin%'" -o admins_file -f txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 Debugging
|
||||||
|
|
||||||
|
Dehasher uses the `zap` logging library for logging. The logs are stored in `~/.local/share/Dehasher/logs`.
|
||||||
|
The logs can be easily queried from the Dehasher CLI.
|
||||||
|
```bash
|
||||||
|
# Show the last 10 logs
|
||||||
|
dehasher logs -l 10
|
||||||
|
|
||||||
|
# Show logs from the last 24 hours
|
||||||
|
dehasher logs -s "24 hours ago"
|
||||||
|
|
||||||
|
# Show logs from the last 24 hours with a severity of error or fatal
|
||||||
|
dehasher logs -s "24 hours ago" -v error,fatal
|
||||||
|
```
|
||||||
|
## 🎉 Sample Run
|
||||||
|
```bash
|
||||||
|
ar1ste1a@kali:~$ dehasher api -D <redacted>.com -o <redacted> -f json
|
||||||
|
Making 3 Requests for 10000 Records (30000 Total)
|
||||||
|
[*] Querying Dehashed API...
|
||||||
|
[*] Performing Request...
|
||||||
|
[+] Retrieved 2740 Records
|
||||||
|
[-] Not Enough Entries, ending queries
|
||||||
|
[+] Discovered 10 Credentials
|
||||||
|
[*] Writing entries to file: <redacted>.json
|
||||||
|
[*] Success
|
||||||
|
[*] Completing Process
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
Contributions are welcome! Submit a pull request to help improve Dehasher.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="https://img.wanman.io/fUSu0/jUtovIFE52.png/raw" style="width: 350px; height: auto" alt="Ar1ste1a" title="Ar1ste1a Offensive Security">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## **Release The Kraken**
|
||||||
|
|||||||
+70
-4
@@ -16,8 +16,8 @@ func init() {
|
|||||||
|
|
||||||
// Add flags specific to export command
|
// Add flags specific to export command
|
||||||
exportCmd.Flags().IntVarP(&exportLimitRows, "limit", "l", 100, "Limit number of results")
|
exportCmd.Flags().IntVarP(&exportLimitRows, "limit", "l", 100, "Limit number of results")
|
||||||
exportCmd.Flags().BoolVarP(&exportListAll, "list-all", "a", false, "List all columns")
|
exportCmd.Flags().BoolVarP(&exportListAll, "list-all", "a", false, "List all tables and their columns")
|
||||||
exportCmd.Flags().StringVarP(&exportTableName, "table", "t", "", "Table to export")
|
exportCmd.Flags().StringVarP(&exportTableName, "table", "t", "", "Table to export (results, creds, whois, subdomains, history, runs)")
|
||||||
exportCmd.Flags().StringVarP(&exportNotNull, "not-null", "n", "", "Filter for non-null values (comma-separated list, e.g., 'password,email')")
|
exportCmd.Flags().StringVarP(&exportNotNull, "not-null", "n", "", "Filter for non-null values (comma-separated list, e.g., 'password,email')")
|
||||||
exportCmd.Flags().StringVarP(&exportColumns, "columns", "c", "", "Columns to display in output (comma-separated list, e.g., 'username,email,password')")
|
exportCmd.Flags().StringVarP(&exportColumns, "columns", "c", "", "Columns to display in output (comma-separated list, e.g., 'username,email,password')")
|
||||||
exportCmd.Flags().StringVarP(&exportUserQuery, "user-query", "q", "", "User query to execute")
|
exportCmd.Flags().StringVarP(&exportUserQuery, "user-query", "q", "", "User query to execute")
|
||||||
@@ -50,6 +50,12 @@ var (
|
|||||||
Use: "export",
|
Use: "export",
|
||||||
Short: "Export database to file",
|
Short: "Export database to file",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// If list-all flag is set, list all tables and columns
|
||||||
|
if exportListAll {
|
||||||
|
listAvailableTables()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("[*] Exporting database...")
|
fmt.Println("[*] Exporting database...")
|
||||||
|
|
||||||
// If Raw Query is set, execute it and export
|
// If Raw Query is set, execute it and export
|
||||||
@@ -59,11 +65,65 @@ var (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate table name
|
||||||
|
if exportTableName == "" {
|
||||||
|
fmt.Println("[!] Error: Table name is required. Use -t or --table to specify a table.")
|
||||||
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isValidTable(exportTableName) {
|
||||||
|
fmt.Printf("[!] Error: Unknown table '%s'.\n", exportTableName)
|
||||||
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate columns if specified
|
||||||
|
if exportColumns != "" {
|
||||||
|
columns := strings.Split(exportColumns, ",")
|
||||||
|
invalidColumns := validateColumns(exportTableName, columns)
|
||||||
|
if len(invalidColumns) > 0 {
|
||||||
|
fmt.Printf("[!] Error: Invalid column(s) for table '%s': %s\n",
|
||||||
|
exportTableName, strings.Join(invalidColumns, ", "))
|
||||||
|
fmt.Println("[*] Available columns for this table:")
|
||||||
|
for i := 0; i < len(availableTables[exportTableName]); i += 5 {
|
||||||
|
end := i + 5
|
||||||
|
if end > len(availableTables[exportTableName]) {
|
||||||
|
end = len(availableTables[exportTableName])
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", strings.Join(availableTables[exportTableName][i:end], ", "))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate not-null fields if specified
|
||||||
|
if exportNotNull != "" {
|
||||||
|
notNullFields := strings.Split(exportNotNull, ",")
|
||||||
|
invalidFields := validateColumns(exportTableName, notNullFields)
|
||||||
|
if len(invalidFields) > 0 {
|
||||||
|
fmt.Printf("[!] Error: Invalid not-null field(s) for table '%s': %s\n",
|
||||||
|
exportTableName, strings.Join(invalidFields, ", "))
|
||||||
|
fmt.Println("[*] Available columns for this table:")
|
||||||
|
for i := 0; i < len(availableTables[exportTableName]); i += 5 {
|
||||||
|
end := i + 5
|
||||||
|
if end > len(availableTables[exportTableName]) {
|
||||||
|
end = len(availableTables[exportTableName])
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", strings.Join(availableTables[exportTableName][i:end], ", "))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determine which table to query based on the tableTypeDBQuery parameter
|
// Determine which table to query based on the tableTypeDBQuery parameter
|
||||||
table := sqlite.GetTable(exportTableName)
|
table := sqlite.GetTable(exportTableName)
|
||||||
if table == sqlite.UnknownTable {
|
if table == sqlite.UnknownTable {
|
||||||
fmt.Printf("Error: Unknown table type '%s'.\n", exportTableName)
|
fmt.Printf("[!] Error: Unknown table type '%s'.\n", exportTableName)
|
||||||
cmd.Help()
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +159,12 @@ func exportTableQuery(table sqlite.Table) {
|
|||||||
// Get the object for the table
|
// Get the object for the table
|
||||||
object := table.Object()
|
object := table.Object()
|
||||||
|
|
||||||
|
// Check if object is nil (invalid table)
|
||||||
|
if object == nil {
|
||||||
|
fmt.Printf("[!] Error: Table '%s' is not valid or does not exist.\n", exportTableName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Query the database
|
// Query the database
|
||||||
db := sqlite.GetDB()
|
db := sqlite.GetDB()
|
||||||
query := db.Model(object).Select(columns)
|
query := db.Model(object).Select(columns)
|
||||||
|
|||||||
+189
-7
@@ -7,28 +7,137 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Map of available tables and their columns
|
||||||
|
var availableTables = map[string][]string{
|
||||||
|
"results": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "dehashed_id", "email", "ip_address", "username",
|
||||||
|
"password", "hashed_password", "hash_type", "name", "vin", "license_plate", "url", "social",
|
||||||
|
"cryptocurrency_address", "address", "phone", "company", "database_name",
|
||||||
|
},
|
||||||
|
"creds": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "email", "username", "password",
|
||||||
|
},
|
||||||
|
"whois": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "contact_email", "created_date",
|
||||||
|
"domain_name", "domain_name_ext", "expires_date", "status", "whois_server",
|
||||||
|
},
|
||||||
|
"subdomains": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "domain", "first_seen", "last_seen",
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "domain_name", "domain_type",
|
||||||
|
"registrar_name", "whois_server", "created_date_iso8601", "updated_date_iso8601", "expires_date_iso8601",
|
||||||
|
},
|
||||||
|
"runs": {
|
||||||
|
"id", "created_at", "updated_at", "deleted_at", "max_records", "max_requests", "starting_page",
|
||||||
|
"output_format", "output_file", "regex_match", "wildcard_match", "username_query", "email_query",
|
||||||
|
"ip_query", "pass_query", "hash_query", "name_query", "domain_query", "vin_query", "license_plate_query",
|
||||||
|
"address_query", "phone_query", "social_query", "crypto_address_query", "print_balance", "creds_only",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to list available tables and their columns
|
||||||
|
func listAvailableTables() {
|
||||||
|
fmt.Println("Available tables and columns:")
|
||||||
|
|
||||||
|
// Prepare data for pretty.Table
|
||||||
|
headers := []string{"Table", "Columns"}
|
||||||
|
var tableRows [][]string
|
||||||
|
|
||||||
|
// Sort tables alphabetically for consistent output
|
||||||
|
var tableNames []string
|
||||||
|
for tableName := range availableTables {
|
||||||
|
tableNames = append(tableNames, tableName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple bubble sort for table names
|
||||||
|
for i := 0; i < len(tableNames)-1; i++ {
|
||||||
|
for j := 0; j < len(tableNames)-i-1; j++ {
|
||||||
|
if tableNames[j] > tableNames[j+1] {
|
||||||
|
tableNames[j], tableNames[j+1] = tableNames[j+1], tableNames[j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create rows for the table
|
||||||
|
for _, tableName := range tableNames {
|
||||||
|
columns := availableTables[tableName]
|
||||||
|
|
||||||
|
// Format columns with line breaks for better readability
|
||||||
|
var formattedColumns string
|
||||||
|
for i := 0; i < len(columns); i += 5 {
|
||||||
|
end := i + 5
|
||||||
|
if end > len(columns) {
|
||||||
|
end = len(columns)
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
formattedColumns += "\n"
|
||||||
|
}
|
||||||
|
formattedColumns += strings.Join(columns[i:end], ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
tableRows = append(tableRows, []string{tableName, formattedColumns})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the table
|
||||||
|
pretty.Table(headers, tableRows)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to validate table name
|
||||||
|
func isValidTable(tableName string) bool {
|
||||||
|
_, exists := availableTables[tableName]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to validate column names for a specific table
|
||||||
|
func validateColumns(tableName string, columns []string) []string {
|
||||||
|
if tableName == "" || columns == nil || len(columns) == 0 || columns[0] == "*" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tableColumns, exists := availableTables[tableName]
|
||||||
|
if !exists {
|
||||||
|
return []string{fmt.Sprintf("Table '%s' does not exist", tableName)}
|
||||||
|
}
|
||||||
|
|
||||||
|
var invalidColumns []string
|
||||||
|
for _, col := range columns {
|
||||||
|
valid := false
|
||||||
|
for _, tableCol := range tableColumns {
|
||||||
|
if col == tableCol {
|
||||||
|
valid = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
invalidColumns = append(invalidColumns, col)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return invalidColumns
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Add whois command to root command
|
// Add whois command to root command
|
||||||
rootCmd.AddCommand(queryCmd)
|
rootCmd.AddCommand(queryCmd)
|
||||||
|
|
||||||
// Add flags specific to whois command
|
// Add flags specific to whois command
|
||||||
queryCmd.Flags().StringVarP(&dbQueryTableName, "table", "t", "", "Table to query (results, creds, whois, subdomains, history, query_options)")
|
queryCmd.Flags().StringVarP(&dbQueryTableName, "table", "t", "", "Table to query (results, creds, whois, subdomains, history, runs)")
|
||||||
queryCmd.Flags().IntVarP(&dbQueryLimitRows, "limit", "l", 100, "Limit number of results")
|
queryCmd.Flags().IntVarP(&dbQueryLimitRows, "limit", "l", 100, "Limit number of results")
|
||||||
queryCmd.Flags().StringVarP(&dbQueryNotNull, "not-null", "n", "", "Filter for non-null values (comma-separated list, e.g., 'password,email')")
|
queryCmd.Flags().StringVarP(&dbQueryNotNull, "not-null", "n", "", "Filter for non-null values (comma-separated list, e.g., 'password,email')")
|
||||||
queryCmd.Flags().StringVarP(&dbQueryColumns, "columns", "c", "", "Columns to display in output (comma-separated list, e.g., 'username,email,password')")
|
queryCmd.Flags().StringVarP(&dbQueryColumns, "columns", "c", "", "Columns to display in output (comma-separated list, e.g., 'username,email,password')")
|
||||||
queryCmd.Flags().StringVarP(&dbQueryUserQuery, "user-query", "q", "", "User query to execute")
|
queryCmd.Flags().StringVarP(&dbQueryUserQuery, "user-query", "q", "", "User query to execute")
|
||||||
queryCmd.Flags().StringVarP(&dbQueryRawQuery, "raw-query", "r", "", "Raw SQL query to execute")
|
queryCmd.Flags().StringVarP(&dbQueryRawQuery, "raw-query", "r", "", "Raw SQL query to execute")
|
||||||
queryCmd.Flags().BoolVarP(&dbQueryListAll, "list-all", "a", false, "List all columns")
|
queryCmd.Flags().BoolVarP(&dbQueryListAll, "list-all", "a", false, "List all tables and their columns")
|
||||||
|
|
||||||
// Add mutually exclusive flags to query and raw-query
|
// Add mutually exclusive flags to query and raw-query
|
||||||
// Cannot use query and raw-query at the same time
|
// Cannot use query and raw-query at the same time
|
||||||
queryCmd.MarkFlagsMutuallyExclusive("user-query", "raw-query")
|
queryCmd.MarkFlagsMutuallyExclusive("user-query", "raw-query")
|
||||||
// Raw query does not require a table
|
// Raw query does not require a table
|
||||||
queryCmd.MarkFlagsMutuallyExclusive("user-query", "table")
|
queryCmd.MarkFlagsMutuallyExclusive("raw-query", "table")
|
||||||
// List all columns does not require a query or raw-query
|
// List all columns does not require a query or raw-query
|
||||||
queryCmd.MarkFlagsMutuallyExclusive("raw-query", "list-all")
|
queryCmd.MarkFlagsMutuallyExclusive("raw-query", "list-all")
|
||||||
}
|
}
|
||||||
@@ -47,20 +156,81 @@ var (
|
|||||||
Short: "Query the database",
|
Short: "Query the database",
|
||||||
Long: `Query the database for various information.`,
|
Long: `Query the database for various information.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// If list-all flag is set, list all tables and columns
|
||||||
|
if dbQueryListAll {
|
||||||
|
listAvailableTables()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If Raw Query is set, execute it and return
|
// If Raw Query is set, execute it and return
|
||||||
if dbQueryRawQuery != "" {
|
if dbQueryRawQuery != "" {
|
||||||
fmt.Println("[*] Executing Raw Query...")
|
fmt.Println("[*] Executing Raw Query...")
|
||||||
rawDBQuery()
|
rawDBQuery()
|
||||||
os.Exit(1)
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate table name
|
||||||
|
if dbQueryTableName == "" {
|
||||||
|
fmt.Println("[!] Error: Table name is required. Use -t or --table to specify a table.")
|
||||||
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isValidTable(dbQueryTableName) {
|
||||||
|
fmt.Printf("[!] Error: Unknown table '%s'.\n", dbQueryTableName)
|
||||||
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate columns if specified
|
||||||
|
if dbQueryColumns != "" {
|
||||||
|
columns := strings.Split(dbQueryColumns, ",")
|
||||||
|
invalidColumns := validateColumns(dbQueryTableName, columns)
|
||||||
|
if len(invalidColumns) > 0 {
|
||||||
|
fmt.Printf("[!] Error: Invalid column(s) for table '%s': %s\n",
|
||||||
|
dbQueryTableName, strings.Join(invalidColumns, ", "))
|
||||||
|
fmt.Println("[*] Available columns for this table:")
|
||||||
|
for i := 0; i < len(availableTables[dbQueryTableName]); i += 5 {
|
||||||
|
end := i + 5
|
||||||
|
if end > len(availableTables[dbQueryTableName]) {
|
||||||
|
end = len(availableTables[dbQueryTableName])
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", strings.Join(availableTables[dbQueryTableName][i:end], ", "))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate not-null fields if specified
|
||||||
|
if dbQueryNotNull != "" {
|
||||||
|
notNullFields := strings.Split(dbQueryNotNull, ",")
|
||||||
|
invalidFields := validateColumns(dbQueryTableName, notNullFields)
|
||||||
|
if len(invalidFields) > 0 {
|
||||||
|
fmt.Printf("[!] Error: Invalid not-null field(s) for table '%s': %s\n",
|
||||||
|
dbQueryTableName, strings.Join(invalidFields, ", "))
|
||||||
|
fmt.Println("[*] Available columns for this table:")
|
||||||
|
for i := 0; i < len(availableTables[dbQueryTableName]); i += 5 {
|
||||||
|
end := i + 5
|
||||||
|
if end > len(availableTables[dbQueryTableName]) {
|
||||||
|
end = len(availableTables[dbQueryTableName])
|
||||||
|
}
|
||||||
|
fmt.Printf(" %s\n", strings.Join(availableTables[dbQueryTableName][i:end], ", "))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine which table to query based on the tableTypeDBQuery parameter
|
// Determine which table to query based on the tableTypeDBQuery parameter
|
||||||
table := sqlite.GetTable(dbQueryTableName)
|
table := sqlite.GetTable(dbQueryTableName)
|
||||||
if table == sqlite.UnknownTable {
|
if table == sqlite.UnknownTable {
|
||||||
fmt.Printf("Error: Unknown table type '%s'.\n", dbQueryTableName)
|
fmt.Printf("[!] Error: Unknown table type '%s'.\n", dbQueryTableName)
|
||||||
cmd.Help()
|
fmt.Println("[*] Available tables: results, creds, whois, subdomains, history, runs")
|
||||||
|
fmt.Println("[*] Use --list-all to see all tables and their columns.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[*] Querying Database...")
|
fmt.Println("[*] Querying Database...")
|
||||||
tableQuery(table)
|
tableQuery(table)
|
||||||
},
|
},
|
||||||
@@ -93,6 +263,12 @@ func tableQuery(table sqlite.Table) {
|
|||||||
// Get the object for the table
|
// Get the object for the table
|
||||||
object := table.Object()
|
object := table.Object()
|
||||||
|
|
||||||
|
// Check if object is nil (invalid table)
|
||||||
|
if object == nil {
|
||||||
|
fmt.Printf("[!] Error: Table '%s' is not valid or does not exist.\n", dbQueryTableName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Query the database
|
// Query the database
|
||||||
db := sqlite.GetDB()
|
db := sqlite.GetDB()
|
||||||
query := db.Model(object).Select(columns)
|
query := db.Model(object).Select(columns)
|
||||||
@@ -114,6 +290,7 @@ func tableQuery(table sqlite.Table) {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error executing query: %v\n", err)
|
fmt.Printf("[!] Error executing query: %v\n", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
@@ -125,6 +302,7 @@ func tableQuery(table sqlite.Table) {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error getting columns from query: %v\n", err)
|
fmt.Printf("[!] Error getting columns from query: %v\n", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare data for pretty.Table
|
// Prepare data for pretty.Table
|
||||||
@@ -144,6 +322,7 @@ func tableQuery(table sqlite.Table) {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error scanning row from query: %v\n", err)
|
fmt.Printf("[!] Error scanning row from query: %v\n", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert row values to strings
|
// Convert row values to strings
|
||||||
@@ -202,6 +381,7 @@ func rawDBQuery() {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error executing raw query: %v\n", err)
|
fmt.Printf("[!] Error executing raw query: %v\n", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
@@ -212,6 +392,7 @@ func rawDBQuery() {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error getting columns from raw query: %v\n", err)
|
fmt.Printf("[!] Error getting columns from raw query: %v\n", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare data for pretty.Table
|
// Prepare data for pretty.Table
|
||||||
@@ -231,6 +412,7 @@ func rawDBQuery() {
|
|||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
fmt.Printf("[!] Error scanning row from raw query: %v\n", err)
|
fmt.Printf("[!] Error scanning row from raw query: %v\n", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert row values to strings
|
// Convert row values to strings
|
||||||
|
|||||||
@@ -85,20 +85,20 @@ func (dh *Dehasher) setQueries() {
|
|||||||
|
|
||||||
// Start starts the querying process
|
// Start starts the querying process
|
||||||
func (dh *Dehasher) Start() {
|
func (dh *Dehasher) Start() {
|
||||||
fmt.Println("[*] Querying Dehashed API...")
|
fmt.Printf("[*] Querying Dehashed API...\n")
|
||||||
for i := 0; i < dh.options.MaxRequests; i++ {
|
for i := 0; i < dh.options.MaxRequests; i++ {
|
||||||
fmt.Printf("\n\t[*] Performing Request...")
|
fmt.Printf(" [*] Performing Request...\n")
|
||||||
count, err := dh.client.Search(*dh.request)
|
count, err := dh.client.Search(*dh.request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Check if it's a DehashError
|
// Check if it's a DehashError
|
||||||
if dhErr, ok := err.(*DehashError); ok {
|
if dhErr, ok := err.(*DehashError); ok {
|
||||||
fmt.Printf("\n\t[!] Dehashed API Error: %s (Code: %d)", dhErr.Message, dhErr.Code)
|
fmt.Printf(" [!] Dehashed API Error: %s (Code: %d)\n", dhErr.Message, dhErr.Code)
|
||||||
zap.L().Error("dehashed_api_error",
|
zap.L().Error("dehashed_api_error",
|
||||||
zap.String("message", dhErr.Message),
|
zap.String("message", dhErr.Message),
|
||||||
zap.Int("code", dhErr.Code),
|
zap.Int("code", dhErr.Code),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\n\t[!] Error performing request: %v", err)
|
fmt.Printf(" [!] Error performing request: %v\n", err)
|
||||||
zap.L().Error("request_error",
|
zap.L().Error("request_error",
|
||||||
zap.String("message", "failed to perform request"),
|
zap.String("message", "failed to perform request"),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
@@ -108,11 +108,11 @@ func (dh *Dehasher) Start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if count < dh.options.MaxRecords {
|
if count < dh.options.MaxRecords {
|
||||||
fmt.Printf("\n\t\t[+] Retrieved %d Records", count)
|
fmt.Printf(" [+] Retrieved %d records\n", count)
|
||||||
fmt.Printf("\n[-] Not Enough Entries, ending queries")
|
fmt.Printf(" [-] Not enough entries, ending queries\n")
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\n\t\t[+] Retrieved %d Records", dh.options.MaxRecords)
|
fmt.Printf(" [+] Retrieved %d records\n", dh.options.MaxRecords)
|
||||||
}
|
}
|
||||||
|
|
||||||
dh.request.Page = dh.getNextPage()
|
dh.request.Page = dh.getNextPage()
|
||||||
@@ -171,7 +171,7 @@ func (dh *Dehasher) parseResults() {
|
|||||||
zap.L().Info("extracting_credentials")
|
zap.L().Info("extracting_credentials")
|
||||||
results := dh.client.GetResults()
|
results := dh.client.GetResults()
|
||||||
creds := results.ExtractCredentials()
|
creds := results.ExtractCredentials()
|
||||||
fmt.Printf("\n\t[*] Discovered %d Credentials", len(creds))
|
fmt.Printf("\n\t[+] Discovered %d Credentials", len(creds))
|
||||||
err := sqlite.StoreCreds(creds)
|
err := sqlite.StoreCreds(creds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zap.L().Error("store_creds",
|
zap.L().Error("store_creds",
|
||||||
|
|||||||
Reference in New Issue
Block a user