agent-bypass 2.16.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_ADDITIVE_CHANGELOG.md +13 -1
- package/README.md +7 -2
- package/SKILL.md +43 -118
- package/bin/install.js +28 -1
- package/dsh/persona.md +2 -2
- package/package.json +1 -1
- package/references/agent-routing.md +1 -1
- package/references/bruteforce-playbook.md +87 -0
- package/references/fake-ip-tun.md +113 -0
- package/references/tool-selection.md +9 -1
- package/scripts/doh_resolve.sh +110 -5
- package/scripts/fastrecon.py +55 -6
- package/scripts/netdns.py +192 -0
- package/scripts/origin_trace.py +369 -0
- package/scripts/portscan.py +119 -13
- package/tests/test_regressions.py +110 -0
|
@@ -250,5 +250,115 @@ class DoctorTests(unittest.TestCase):
|
|
|
250
250
|
self.assertEqual(list(Path(home).rglob("*")), [], "doctor 不应写文件")
|
|
251
251
|
|
|
252
252
|
|
|
253
|
+
class NetDnsScanOriginTests(unittest.TestCase):
|
|
254
|
+
"""fake-IP/TUN:netdns 判定 + portscan 解析守卫 + origin_trace 解析(全部离线)。"""
|
|
255
|
+
|
|
256
|
+
@classmethod
|
|
257
|
+
def setUpClass(cls):
|
|
258
|
+
sys.path.insert(0, str(SCRIPTS))
|
|
259
|
+
import netdns
|
|
260
|
+
import portscan
|
|
261
|
+
import origin_trace
|
|
262
|
+
cls.nd = netdns
|
|
263
|
+
cls.ps = portscan
|
|
264
|
+
cls.ot = origin_trace
|
|
265
|
+
|
|
266
|
+
def test_fake_ip_ranges(self):
|
|
267
|
+
for ip in ("198.18.0.5", "198.19.255.1", "240.1.2.3", "198.51.100.7", "203.0.113.9"):
|
|
268
|
+
self.assertTrue(self.nd.is_fake_ip(ip), ip)
|
|
269
|
+
for ip in ("1.1.1.1", "8.8.8.8", "192.168.1.1", "10.0.0.1"):
|
|
270
|
+
self.assertFalse(self.nd.is_fake_ip(ip), ip)
|
|
271
|
+
|
|
272
|
+
def test_parse_dns_json(self):
|
|
273
|
+
sample = ('{"Answer":[{"type":1,"data":"93.184.216.34"},'
|
|
274
|
+
'{"type":28,"data":"2606:2800::1"},{"type":1,"data":"198.18.0.1"}]}')
|
|
275
|
+
self.assertEqual(self.nd._parse_dns_json(sample, "A"), ["93.184.216.34", "198.18.0.1"])
|
|
276
|
+
self.assertEqual(self.nd._parse_dns_json(sample, "AAAA"), ["2606:2800::1"])
|
|
277
|
+
self.assertEqual(self.nd._parse_dns_json("not-json", "A"), [])
|
|
278
|
+
|
|
279
|
+
def test_portscan_split_host_fake_guard(self):
|
|
280
|
+
self.assertEqual(self.ps.split_host("https://example.com:8443/x"), ("example.com", 8443))
|
|
281
|
+
self.assertEqual(self.ps.split_host("1.2.3.4"), ("1.2.3.4", None))
|
|
282
|
+
self.assertIsNone(self.ps.split_host("bad host")[0])
|
|
283
|
+
self.assertTrue(self.ps.is_fake_ip("198.18.1.2"))
|
|
284
|
+
ip, src, fake = self.ps.resolve_target("198.18.1.2", mode="auto")
|
|
285
|
+
self.assertEqual((ip, src), ("198.18.1.2", "ip"))
|
|
286
|
+
self.assertEqual(fake, [])
|
|
287
|
+
|
|
288
|
+
def test_origin_trace_parsers(self):
|
|
289
|
+
ct = '[{"name_value":"a.example.com\\n*.example.com\\nother.test"}]'
|
|
290
|
+
self.assertEqual(self.ot.parse_crtsh(ct, "example.com"), ["a.example.com", "example.com"])
|
|
291
|
+
self.assertEqual(self.ot.extract_title("<title> Hi There </title>"), "Hi There")
|
|
292
|
+
self.assertEqual(self.ot.cdn_markers({"cf-ray": "x", "server": "nginx"}), ["cf-ray"])
|
|
293
|
+
base = {"title": "X", "server": "nginx", "status": "HTTP/1.1 200 OK", "cdn": ["cf-ray"]}
|
|
294
|
+
cand = {"title": "X", "server": "nginx", "status": "HTTP/1.1 200 OK", "cdn": [], "cert_domain_ok": True}
|
|
295
|
+
score, reasons = self.ot.score_candidate(base, cand)
|
|
296
|
+
self.assertGreaterEqual(score, 5)
|
|
297
|
+
self.assertIn("title", reasons)
|
|
298
|
+
self.assertLess(self.ot.score_candidate(base, {"cdn": ["cf-ray"]})[0], score)
|
|
299
|
+
|
|
300
|
+
def test_doh_shell_syntax(self):
|
|
301
|
+
sh = shutil.which("sh")
|
|
302
|
+
if not sh:
|
|
303
|
+
self.skipTest("no sh")
|
|
304
|
+
r = _tmp_run([sh, "-n", str(SCRIPTS / "doh_resolve.sh")])
|
|
305
|
+
self.assertEqual(r.returncode, 0, r.stderr)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
class SkillCompactTests(unittest.TestCase):
|
|
309
|
+
"""SKILL.md 体积/去重回归:防止再次膨胀。"""
|
|
310
|
+
|
|
311
|
+
def test_skill_structure_and_size(self):
|
|
312
|
+
skill = (ROOT / "SKILL.md").read_text(encoding="utf-8")
|
|
313
|
+
self.assertEqual(skill.count("<!-- module:"), 35)
|
|
314
|
+
self.assertNotIn("## 修正对照", skill, "重复的修正对照表已移除,勿再加回")
|
|
315
|
+
self.assertLess(len(skill.encode("utf-8")), 132000, "SKILL.md 体积超限(保持精简,长内容放 references/)")
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class HangProtectionTests(unittest.TestCase):
|
|
319
|
+
"""防卡死:DNS 硬超时、扫描总时限、溯源预算/同名 CDN 扣分(全部离线)。"""
|
|
320
|
+
|
|
321
|
+
@classmethod
|
|
322
|
+
def setUpClass(cls):
|
|
323
|
+
sys.path.insert(0, str(SCRIPTS))
|
|
324
|
+
import netdns, portscan, origin_trace
|
|
325
|
+
cls.nd = netdns
|
|
326
|
+
cls.ps = portscan
|
|
327
|
+
cls.ot = origin_trace
|
|
328
|
+
|
|
329
|
+
def test_system_resolve_hard_timeout(self):
|
|
330
|
+
import time as _t
|
|
331
|
+
orig = self.nd._system_resolve_impl
|
|
332
|
+
self.nd._system_resolve_impl = lambda name: (_t.sleep(3), ["1.2.3.4"])[1]
|
|
333
|
+
t0 = _t.monotonic()
|
|
334
|
+
try:
|
|
335
|
+
ips = self.nd.system_resolve("example.com", timeout=0.2)
|
|
336
|
+
finally:
|
|
337
|
+
self.nd._system_resolve_impl = orig
|
|
338
|
+
self.assertEqual(ips, [])
|
|
339
|
+
self.assertLess(_t.monotonic() - t0, 1.5, "system_resolve 必须有硬超时,不能挂住")
|
|
340
|
+
|
|
341
|
+
def test_portscan_total_deadline(self):
|
|
342
|
+
import asyncio, time as _t
|
|
343
|
+
found, timed_out = asyncio.run(
|
|
344
|
+
self.ps.scan("127.0.0.1", [9, 10], conc=1, timeout=0.05,
|
|
345
|
+
deadline=_t.monotonic() - 1))
|
|
346
|
+
self.assertEqual(found, [])
|
|
347
|
+
self.assertTrue(timed_out)
|
|
348
|
+
|
|
349
|
+
def test_origin_same_cdn_penalty(self):
|
|
350
|
+
base = {"title": "X", "server": "nginx", "status": "HTTP/1.1 200 OK", "cdn": ["cf-ray"]}
|
|
351
|
+
cand_cdn = {"title": "X", "server": "nginx", "status": "HTTP/1.1 200 OK", "cdn": ["cf-ray"]}
|
|
352
|
+
cand_origin = {"title": "X", "server": "nginx", "status": "HTTP/1.1 200 OK", "cdn": []}
|
|
353
|
+
s_cdn, r_cdn = self.ot.score_candidate(base, cand_cdn)
|
|
354
|
+
s_org, r_org = self.ot.score_candidate(base, cand_origin)
|
|
355
|
+
self.assertIn("same-cdn", r_cdn)
|
|
356
|
+
self.assertLess(s_cdn, s_org)
|
|
357
|
+
|
|
358
|
+
def test_origin_bad_flag_rejected(self):
|
|
359
|
+
r = _tmp_run([sys.executable, str(SCRIPTS / "origin_trace.py"), "--bogus"])
|
|
360
|
+
self.assertEqual(r.returncode, 2)
|
|
361
|
+
|
|
362
|
+
|
|
253
363
|
if __name__ == "__main__":
|
|
254
364
|
unittest.main()
|