feat: merge attacks into PineAP menu; auto channel; recon fixes; richer reports
- Rail: Attacks tab removed; PineAP becomes a grouped menu (Evil WPA / Evil Open / Evil Enterprise / Impersonation / Clients / Filtering); old #/attacks* hashes redirect to their PineAP equivalents. - PineAP tabs gain Evil Enterprise; stock Open AP / Evil WPA / Enterprise pages replaced by the verified one-click launchers (status, capture, export, deauth, playbooks). - Channel selects gain an Auto option: deploy resolves the target SSID's last-seen channel from recon.db (verified unit-tested end to end). - Harness: pi.dev prompt section removed; Copy Token inline; robot icon. - Recon: compare checkboxes no longer hide the AP list (multi-select stays visible, rows highlighted, clients table no longer suppressed); Previous Scans buttons moved above the dropdown with a Delete All; encryption chips + buckets now distinguish WPA2/WPA3 PSK vs Enterprise (AKM suites decoded from recon bitfield bits 32-47); scan JSON carries GPS when a fix exists; Reports tab shows a GPS column. - fix: restore top-level EVIL_ENC definition lost in the repo (deployed build had it; repo would have thrown at init).
This commit is contained in:
@@ -29,12 +29,20 @@ const App = (() => {
|
||||
|
||||
const railItems = [
|
||||
{ key: 'dashboard', label: 'Dashboard', hash: '#/dashboard', icon: 'dashboard' },
|
||||
{ key: 'attacks', label: 'Attacks', hash: '#/attacks', icon: 'attack' },
|
||||
{ key: 'pineap', label: 'PineAP', hash: '#/pineap', icon: 'wifi' },
|
||||
{
|
||||
key: 'pineap', label: 'PineAP', hash: '#/pineap', icon: 'pineap', children: [
|
||||
{ key: 'pineap_evilwpa', label: 'Evil WPA', hash: '#/pineap/evilwpa', icon: 'attack' },
|
||||
{ key: 'pineap_open', label: 'Evil Open', hash: '#/pineap/open', icon: 'wifi' },
|
||||
{ key: 'pineap_enterprise', label: 'Evil Enterprise', hash: '#/pineap/enterprise', icon: 'record' },
|
||||
{ key: 'pineap_impersonation', label: 'Impersonation', hash: '#/pineap/impersonation', icon: 'place' },
|
||||
{ key: 'pineap_clients', label: 'Clients', hash: '#/pineap/clients', icon: 'pager' },
|
||||
{ key: 'pineap_filtering', label: 'Filtering', hash: '#/pineap/filtering', icon: 'settings' }
|
||||
]
|
||||
},
|
||||
{ key: 'recon', label: 'Recon', hash: '#/recon', icon: 'recon' },
|
||||
{ key: 'logging', label: 'Logging', hash: '#/logging', icon: 'logging' },
|
||||
{ key: 'modules', label: 'Payloads', hash: '#/modules', icon: 'modules' },
|
||||
{ key: 'harness', label: 'Harness', hash: '#/harness', icon: 'extension' },
|
||||
{ key: 'harness', label: 'Harness', hash: '#/harness', icon: 'robot' },
|
||||
{ key: 'settings', label: 'Settings', hash: '#/settings', icon: 'settings' }
|
||||
];
|
||||
const railDividers = new Set(['logging']);
|
||||
@@ -63,6 +71,13 @@ const App = (() => {
|
||||
rail.appendChild(d);
|
||||
}
|
||||
rail.appendChild(railEntry(it));
|
||||
if (it.children) {
|
||||
it.children.forEach((sub) => {
|
||||
const s = railEntry(sub);
|
||||
s.classList.add('sub');
|
||||
rail.appendChild(s);
|
||||
});
|
||||
}
|
||||
});
|
||||
const foot = document.createElement('div');
|
||||
foot.className = 'rail-footer';
|
||||
@@ -85,11 +100,22 @@ const App = (() => {
|
||||
|
||||
function route() {
|
||||
closeToolbarMenus();
|
||||
const hash = (location.hash || '#/dashboard').replace(/\/+$/, '');
|
||||
let hash = (location.hash || '#/dashboard').replace(/\/+$/, '');
|
||||
if (hash === '#/recon/survey') {
|
||||
location.hash = '#/recon';
|
||||
return;
|
||||
}
|
||||
if (hash.indexOf('#/attacks') === 0) {
|
||||
const map = {
|
||||
'#/attacks': '#/pineap',
|
||||
'#/attacks/wpa': '#/pineap/evilwpa',
|
||||
'#/attacks/open': '#/pineap/open',
|
||||
'#/attacks/enterprise': '#/pineap/enterprise'
|
||||
};
|
||||
hash = map[hash] || '#/pineap';
|
||||
location.replace(hash);
|
||||
return;
|
||||
}
|
||||
const name = routes[hash];
|
||||
if (currentView && currentView.destroy) currentView.destroy();
|
||||
els.content.innerHTML = '';
|
||||
@@ -103,9 +129,13 @@ const App = (() => {
|
||||
currentView = views[name](els.content);
|
||||
}
|
||||
const key = keyOf(hash);
|
||||
const subs = els.rail.querySelectorAll('.entry.sub');
|
||||
const subActive = Array.prototype.some.call(subs, (s) => s.getAttribute('href') === hash);
|
||||
Array.prototype.forEach.call(els.rail.querySelectorAll('.entry'), (a) => {
|
||||
const href = a.getAttribute('href');
|
||||
a.classList.toggle('active', !!href && (href === hash || keyOf(href) === key));
|
||||
const exact = !!href && href === hash;
|
||||
const groupActive = !subActive && !!href && keyOf(href) === key;
|
||||
a.classList.toggle('active', exact || groupActive);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -395,13 +425,10 @@ const App = (() => {
|
||||
|
||||
const routes = {
|
||||
'#/dashboard': 'dashboard',
|
||||
'#/attacks': 'attacks',
|
||||
'#/attacks/wpa': 'attacks_wpa',
|
||||
'#/attacks/open': 'attacks_open',
|
||||
'#/attacks/enterprise': 'attacks_enterprise',
|
||||
'#/pineap': 'pineap',
|
||||
'#/pineap/open': 'pineap_open',
|
||||
'#/pineap/evilwpa': 'pineap_evilwpa',
|
||||
'#/pineap/enterprise': 'pineap_enterprise',
|
||||
'#/pineap/open': 'pineap_open',
|
||||
'#/pineap/impersonation': 'pineap_impersonation',
|
||||
'#/pineap/clients': 'pineap_clients',
|
||||
'#/pineap/filtering': 'pineap_filtering',
|
||||
|
||||
Reference in New Issue
Block a user