File size: 7,229 Bytes
1efb991
e6e7538
1efb991
e6e7538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1efb991
e6e7538
 
 
1efb991
e6e7538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1efb991
e6e7538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1efb991
e6e7538
 
 
1efb991
e6e7538
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1efb991
 
e6e7538
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import gradio as gr
import orjson
import requests
import time
from pathlib import Path
from typing import Dict, List, Optional
from loguru import logger
from registry import Registry
from config import DATA_DIR, HF_TOKEN, SHODAN_API_KEY, ZOOMEYE_API_KEY, ENABLE_EXECUTE, RATE_LIMIT_PER_MIN, OWNER_PIN, LLM_MODE, ALLOWED_MODELS, THEME, COUNTRIES

DATA_DIR.mkdir(exist_ok=True)
logger.add(DATA_DIR / "app.log", rotation="1 MB", retention="7 days")
registry = Registry()
session_counts: Dict[str, List[float]] = {}

def rate_limit(session_id: str) -> bool:
    now = time.time()
    if session_id not in session_counts:
        session_counts[session_id] = []
    session_counts[session_id] = [t for t in session_counts[session_id] if now - t < 60]
    if len(session_counts[session_id]) >= RATE_LIMIT_PER_MIN:
        return False
    session_counts[session_id].append(now)
    return True

def build_query(query: str, platform: str, session_id: str) -> str:
    if not rate_limit(session_id):
        return "Rate limit exceeded. Please try again later."
    parsed = registry.parse_query(query)
    intent = parsed["intents"][0] if parsed["intents"] else None
    service = parsed["services"][0] if parsed["services"] else None
    base_query = []
    if intent and intent in registry.store.intents:
        templates = registry.store.intents[intent].platform_templates.get(platform, [])
        defaults = registry.store.intents[intent].defaults
        for template in templates:
            formatted = template.format(**defaults)
            base_query.append(formatted)
    elif service:
        for s in registry.store.services:
            if s["name"] == service:
                base_query.append(f'port:{s["port"]}' if s.get("port") else f'product:"{s["name"]}"')
    for key, value in parsed["filters"].items():
        if key in registry.store.operators:
            base_query.append(f'{key}:"{value}"')
    sanitized_query = registry.sanitize_operators(" ".join(base_query + parsed["operators"]))
    logger.info(f"Built {platform} query: {sanitized_query}")
    return sanitized_query

def exec_shodan(query: str, session_id: str) -> str:
    if not ENABLE_EXECUTE or not SHODAN_API_KEY:
        return "Shodan execution is disabled or API key is missing."
    if not rate_limit(session_id):
        return "Rate limit exceeded. Please try again later."
    try:
        response = requests.get(
            f"https://api.shodan.io/shodan/host/search?key={SHODAN_API_KEY}&query={query}",
            timeout=10
        )
        response.raise_for_status()
        data = response.json()
        logger.info(f"Shodan query executed: {query}")
        return orjson.dumps(data, option=orjson.OPT_INDENT_2).decode()
    except Exception as e:
        logger.error(f"Shodan query failed: {e}")
        return f"Error: {e}"

def exec_zoomeye(query: str, session_id: str) -> str:
    if not ENABLE_EXECUTE or not ZOOMEYE_API_KEY:
        return "ZoomEye execution is disabled or API key is missing."
    if not rate_limit(session_id):
        return "Rate limit exceeded. Please try again later."
    try:
        response = requests.get(
            f"https://api.zoomeye.org/host/search?query={query}&key={ZOOMEYE_API_KEY}",
            timeout=10
        )
        response.raise_for_status()
        data = response.json()
        logger.info(f"ZoomEye query executed: {query}")
        return orjson.dumps(data, option=orjson.OPT_INDENT_2).decode()
    except Exception as e:
        logger.error(f"ZoomEye query failed: {e}")
        return f"Error: {e}"

def query_llm(query: str, model: str) -> str:
    if model == "No LLM" or not HF_TOKEN:
        return "LLM is disabled or HF token is missing."
    try:
        response = requests.post(
            f"https://api-inference.huggingface.co/models/{model}",
            headers={"Authorization": f"Bearer {HF_TOKEN}"},
            json={"inputs": query},
            timeout=10
        )
        response.raise_for_status()
        data = response.json()
        logger.info(f"LLM query executed: {query} with model {model}")
        return data[0]["generated_text"] if isinstance(data, list) else str(data)
    except Exception as e:
        logger.error(f"LLM query failed: {e}")
        return f"Error: {e}"

def process_batch(queries: str, platform: str, session_id: str) -> List[Dict[str, str]]:
    results = []
    for query in queries.split("\n"):
        query = query.strip()
        if query:
            built_query = build_query(query, platform, session_id)
            results.append({"query": query, "built_query": built_query})
    return results

def ingest_data(url: str, pin: str) -> str:
    if pin != OWNER_PIN:
        return "Invalid owner PIN."
    registry.ingest_from_url(url)
    return f"Data ingested from {url}"

with gr.Blocks(theme=THEME, css=".gradio-container { background-color: black; color: crimson; }") as app:
    gr.Markdown("# DorkForge v3.2")
    with gr.Row():
        with gr.Column():
            query_input = gr.Textbox(label="Enter Query", placeholder="e.g., Grafana in Germany port:3000")
            platform = gr.Dropdown(choices=["google", "shodan", "zoomeye"], label="Platform", value="google")
            build_btn = gr.Button("Build Query")
            execute_btn = gr.Button("Execute Query")
            query_output = gr.Textbox(label="Built Query", interactive=False)
            result_output = gr.JSON(label="Query Result")
        with gr.Column():
            batch_input = gr.Textbox(label="Batch Queries (one per line)", lines=5)
            batch_platform = gr.Dropdown(choices=["google", "shodan", "zoomeye"], label="Batch Platform", value="google")
            batch_btn = gr.Button("Process Batch")
            batch_output = gr.Dataframe(label="Batch Results")
    with gr.Row():
        with gr.Column():
            llm_model = gr.Dropdown(choices=ALLOWED_MODELS, label="LLM Model", value=LLM_MODE)
            llm_btn = gr.Button("Query LLM")
            llm_output = gr.Textbox(label="LLM Response", interactive=False)
    with gr.Row():
        with gr.Accordion("Owner Controls", open=False):
            ingest_url = gr.Textbox(label="Ingest URL", placeholder="e.g., https://example.com/data.json")
            owner_pin = gr.Textbox(label="Owner PIN", type="password")
            ingest_btn = gr.Button("Ingest Data")
            ingest_output = gr.Textbox(label="Ingest Result", interactive=False)
    
    build_btn.click(
        fn=build_query,
        inputs=[query_input, platform, gr.State(value="session_id")],
        outputs=query_output
    )
    execute_btn.click(
        fn=lambda q, p, s: exec_shodan(q, s) if p == "shodan" else exec_zoomeye(q, s),
        inputs=[query_output, platform, gr.State(value="session_id")],
        outputs=result_output
    )
    batch_btn.click(
        fn=process_batch,
        inputs=[batch_input, batch_platform, gr.State(value="session_id")],
        outputs=batch_output
    )
    llm_btn.click(
        fn=query_llm,
        inputs=[query_input, llm_model],
        outputs=llm_output
    )
    ingest_btn.click(
        fn=ingest_data,
        inputs=[ingest_url, owner_pin],
        outputs=ingest_output
    )

app.launch()