daemon-sec-lotl

DÆMONBins: GTFOBins × LOLBAS × WADComs × LOOBins in one filterable catalog
git clone https://git.daemon-sec.xyz/daemon-sec-lotl.git
Log | Files | Refs | Submodules | README | LICENSE

[tool].astro (11161B)


      1 ---
      2 import Base from '../../layouts/Base.astro';
      3 import SlantTitle from '../../components/SlantTitle.astro';
      4 import allTechniques from '../../data/techniques.json';
      5 import allTools from '../../data/tools.json';
      6 import { toolSlug, routeSourceOf } from '../../lib/techniques';
      7 import type { Technique, Tool } from '../../lib/techniques';
      8 import { SOURCE_ROUTE, SOURCE_META, PLATFORM_META, CAPABILITY_META } from '../../lib/taxonomy';
      9 import { highlightCommand } from '../../lib/highlight';
     10 import { url } from '../../lib/url';
     11 import { techArticle, breadcrumbs } from '../../lib/jsonld';
     12 import '../../styles/catalog.css';
     13 
     14 export async function getStaticPaths() {
     15   const tools = allTools as unknown as Tool[];
     16   const techs = allTechniques as unknown as Technique[];
     17   const byTool = new Map<string, Technique[]>();
     18   for (const t of techs) {
     19     if (!byTool.has(t.toolId)) byTool.set(t.toolId, []);
     20     byTool.get(t.toolId)!.push(t);
     21   }
     22   const seen = new Set<string>();
     23   const paths = [];
     24   for (const tool of tools) {
     25     const deck = SOURCE_ROUTE[routeSourceOf(tool.id)];
     26     const route = `${deck}/${toolSlug(tool.id)}`;
     27     if (seen.has(route)) continue; // guard against slug collisions
     28     seen.add(route);
     29     paths.push({
     30       params: { source: deck, tool: toolSlug(tool.id) },
     31       props: { tool, techniques: byTool.get(tool.id) || [] },
     32     });
     33   }
     34   return paths;
     35 }
     36 
     37 interface Props { tool: Tool; techniques: Technique[] }
     38 const { tool, techniques } = Astro.props;
     39 // Display deck comes from the toolId namespace, so a daemon-authored WADComs
     40 // addition (wadcoms:Certipy) reads under the WADComs deck; per-technique NEW
     41 // badges convey which rows are daemon-authored.
     42 const src = SOURCE_META[routeSourceOf(tool.id)];
     43 const upstream = tool.references?.find((r) => /gtfobins|lolbas|wadcoms|loobins/i.test(r)) || src.homepage;
     44 const deck = SOURCE_ROUTE[routeSourceOf(tool.id)];
     45 const path = `/${deck}/${toolSlug(tool.id)}`;
     46 const jsonLd = [
     47   techArticle(Astro.site, path, tool, techniques, routeSourceOf(tool.id)),
     48   breadcrumbs(Astro.site, [
     49     { name: 'Catalog', path: '/catalog' },
     50     { name: src.label, path: `/${deck}` },
     51     { name: tool.name, path },
     52   ]),
     53 ];
     54 ---
     55 <Base
     56   title={`${tool.name} — ${src.label} — DÆMONBins`}
     57   description={`${tool.name}: ${techniques.length} living-off-the-land technique${techniques.length === 1 ? '' : 's'} from ${src.label}. Commands, MITRE ATT&CK mapping, detection and references.`}
     58   jsonLd={jsonLd}
     59 >
     60   <div class="wrap tool" style="padding-top:1.5rem;" data-pagefind-body>
     61     <span class="sr-only" data-pagefind-meta={`source:${src.label}`}></span>
     62     <p class="tool__crumb">
     63       <a href={url('catalog')}>Catalog</a>
     64       <span aria-hidden="true">/</span>
     65       <a href={url(SOURCE_ROUTE[routeSourceOf(tool.id)])}>{src.label}</a>
     66     </p>
     67 
     68     <SlantTitle eyebrow={`${src.tag} · ${tool.toolType || 'Tool'}`} title={tool.name} tone={src.accent}>
     69       <Fragment slot="meta">
     70         <span>{techniques.length} technique{techniques.length === 1 ? '' : 's'}</span>
     71         {tool.platform?.length ? <span>{tool.platform.join(' · ')}</span> : null}
     72         <span>{src.label}</span>
     73         <span>GPL-3.0</span>
     74       </Fragment>
     75     </SlantTitle>
     76 
     77     <div class="tool__body">
     78       {(tool.aliases?.length || tool.fullPath?.length || tool.author || tool.contributors?.length) ? (
     79         <aside class="tool__facts slab corners">
     80           <p class="micro tool__facts-label">// {src.tag} · {tool.name}</p>
     81           <dl>
     82             {tool.aliases?.length ? (<><dt>Aliases</dt><dd>{tool.aliases.join(', ')}</dd></>) : null}
     83             {tool.fullPath?.length ? (<><dt>Full path</dt><dd class="mono">{tool.fullPath.map((p) => <div>{p}</div>)}</dd></>) : null}
     84             {tool.author ? (<><dt>Author</dt><dd>{tool.author}</dd></>) : null}
     85             {tool.created ? (<><dt>Created</dt><dd>{tool.created}</dd></>) : null}
     86             {tool.contributors?.length ? (<><dt>Credits</dt><dd>{tool.contributors.join(', ')}</dd></>) : null}
     87             <dt>Upstream</dt>
     88             <dd><a href={upstream} target="_blank" rel="noopener">{upstream.replace(/^https?:\/\//, '')}</a></dd>
     89           </dl>
     90         </aside>
     91       ) : null}
     92 
     93       <div class="tool__techs">
     94         {techniques.map((t) => (
     95           <article class="tech" id={t.id}>
     96             <header class="tech__head">
     97               <div class="tech__title">
     98                 <h2 class="tech__name">{t.name && t.name !== t.toolName ? t.name : t.capability[0]}</h2>
     99                 {t.added ? <span class="tbadge tbadge--new" style="--acc: var(--love);">DÆMON</span> : null}
    100               </div>
    101               <div class="tech__badges">
    102                 {t.capability.map((c) => (
    103                   <span class="tbadge" style={`--acc: var(--${CAPABILITY_META[c]?.accent || 'foam'});`}>{c}</span>
    104                 ))}
    105                 {t.platform.map((p) => (
    106                   <span class="tbadge tbadge--soft" style={`--acc: var(--${PLATFORM_META[p]?.accent || 'foam'});`}>{p}</span>
    107                 ))}
    108               </div>
    109             </header>
    110 
    111             {t.description ? <p class="tech__desc">{t.description}</p> : null}
    112             {t.usecase ? <p class="tech__use"><span>Use</span> {t.usecase}</p> : null}
    113 
    114             <div class="tech__cmdbar" data-cmdbar>
    115               <pre class="cmd"><code set:html={highlightCommand(t.command)} /></pre>
    116               <button class="trow__copy" type="button" data-copy aria-label="Copy command">copy</button>
    117             </div>
    118 
    119             <dl class="tech__meta">
    120               {t.verification ? (<div><dt>Evidence</dt><dd>{t.verification}{t.reviewedAt ? ` · reviewed ${t.reviewedAt}` : ''}</dd></div>) : null}
    121               {t.environment?.length ? (<div><dt>Environment</dt><dd>{t.environment.join(', ')}</dd></div>) : null}
    122               {t.compatibility ? (<div><dt>Compatibility</dt><dd>{t.compatibility}</dd></div>) : null}
    123               {t.expected ? (<div><dt>Expected result</dt><dd>{t.expected}</dd></div>) : null}
    124               {t.troubleshooting ? (<div><dt>Troubleshooting</dt><dd>{t.troubleshooting}</dd></div>) : null}
    125               {t.sideEffects ? (<div><dt>Side effects</dt><dd>{t.sideEffects}</dd></div>) : null}
    126               {t.restore ? (<div><dt>Restore</dt><dd>{t.restore}</dd></div>) : null}
    127               {t.template ? (<div><dt>Template</dt><dd><a href={url(`catalog?id=${encodeURIComponent(t.id)}`)}>Configure this command in the catalog</a></dd></div>) : null}
    128               {t.privilege ? (<div><dt>Context</dt><dd>{t.privilege}</dd></div>) : null}
    129               {t.nativeCategory?.length ? (<div><dt>Native</dt><dd>{t.nativeCategory.join(', ')}</dd></div>) : null}
    130               {t.mitre?.length ? (<div><dt>MITRE</dt><dd>{t.mitre.map((m) => <a class="tchip-link" href={`https://attack.mitre.org/techniques/${m.replace('.', '/')}/`} target="_blank" rel="noopener">{m}</a>)}</dd></div>) : null}
    131               {t.requires?.length ? (<div><dt>Requires</dt><dd>{t.requires.join(', ')}</dd></div>) : null}
    132               {t.services?.length ? (<div><dt>Services</dt><dd>{t.services.join(', ')}</dd></div>) : null}
    133               {t.detection?.length ? (<div><dt>Detection</dt><dd>{t.detection.map((d) => <div>{d.type}: {/^https?:/.test(d.value) ? <a href={d.value} target="_blank" rel="noopener">{d.value.replace(/^https?:\/\//, '')}</a> : d.value}</div>)}</dd></div>) : null}
    134               {t.verifyNote ? (<div><dt>Verified</dt><dd class="tech__note">✓ {t.verifyNote}</dd></div>) : null}
    135               {t.references?.length ? (<div><dt>Refs</dt><dd>{t.references.map((r) => <div><a href={r} target="_blank" rel="noopener">{r.replace(/^https?:\/\//, '')}</a></div>)}</dd></div>) : null}
    136             </dl>
    137           </article>
    138         ))}
    139       </div>
    140     </div>
    141   </div>
    142 
    143   <script>import '../../scripts/copy.ts';</script>
    144 </Base>
    145 
    146 <style>
    147   .tool__crumb { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); margin: 0 0 0.5rem; }
    148   .tool__crumb a { color: var(--fg-dim); text-decoration: none; }
    149   .tool__crumb a:hover { color: var(--accent); }
    150   .tool__body { margin-top: 2.5rem; display: grid; grid-template-columns: 1fr; gap: 1.5rem; }
    151   .tool__facts { padding: 1.1rem 1.3rem; }
    152   .tool__facts-label { color: var(--fg-faint); margin: 0 0 0.6rem; }
    153   .tool__facts dl { display: grid; grid-template-columns: 120px 1fr; gap: 0.35rem 1rem; margin: 0; font-size: 13px; }
    154   .tool__facts dt { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); }
    155   .tool__facts dd { margin: 0; color: var(--fg-dim); }
    156   .tool__facts dd.mono { font-family: var(--font-mono); font-size: 12px; }
    157   .tool__facts a { color: var(--accent); text-decoration: none; }
    158   .tool__techs { display: flex; flex-direction: column; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
    159   .tech { background: var(--bg); padding: 1.1rem 1.2rem; scroll-margin-top: 5.5rem; }
    160   /* The catalog's "full details" link lands here by #id — mark the row it meant. */
    161   .tech:target { box-shadow: inset 3px 0 0 var(--accent); }
    162   .tech__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 0.7rem; }
    163   .tech__title { display: flex; align-items: center; gap: 0.5rem; }
    164   /* An h2 so the techniques form a real outline under the tool's h1; styled as the label it always was. */
    165   .tech__name { margin: 0; font-family: var(--font-archivo); font-weight: 700; font-size: 16px; line-height: 1.3; letter-spacing: -0.01em; text-transform: none; color: var(--fg); }
    166   .tech__badges { display: flex; flex-wrap: wrap; gap: 0.3rem; }
    167   .tech__desc { margin: 0 0 0.7rem; font-size: 14px; line-height: 1.6; color: var(--fg-dim); max-width: 74ch; white-space: pre-wrap; }
    168   .tech__use { margin: 0 0 0.7rem; font-size: 13px; color: var(--fg-dim); }
    169   .tech__use span { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); }
    170   .tech__cmdbar { position: relative; display: flex; align-items: stretch; margin: 0 0 0.8rem; }
    171   .cmd { flex: 1; min-width: 0; margin: 0; padding: 0.6rem 0.8rem; background: var(--color-night-base, #191724); border: 1px solid color-mix(in srgb, #000 20%, var(--color-night-base, #191724)); overflow-x: auto; font-family: var(--font-mono); font-size: 12.5px; line-height: 1.6; }
    172   .cmd code { white-space: pre; color: var(--color-night-text, #e0def4); }
    173   .tech__meta { display: grid; gap: 0.35rem 1.5rem; margin: 0; }
    174   .tech__meta > div { display: grid; grid-template-columns: 90px 1fr; gap: 0.8rem; font-size: 12.5px; line-height: 1.55; }
    175   .tech__meta dt { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--fg-faint); }
    176   .tech__meta dd { margin: 0; color: var(--fg-dim); word-break: break-word; }
    177   .tech__meta a { color: var(--accent); text-decoration: none; }
    178   .tech__meta a:hover { text-decoration: underline; text-underline-offset: 2px; }
    179   .tech__note { color: var(--foam); font-family: var(--font-mono); font-size: 11.5px; }
    180 </style>