mirror of
https://github.com/GTFOBins/GTFOBins.github.io
synced 2024-12-27 07:18:48 +01:00
138 lines
4.4 KiB
HTML
138 lines
4.4 KiB
HTML
<div id="bin-search-wrapper">
|
|
<ul id="bin-search-filters" class="function-list">
|
|
{% for function_pair in site.data.functions %}
|
|
{% assign function_id = function_pair[0] %}
|
|
{% assign function = function_pair[1] %}
|
|
<li><a href="#+{{ function.label | downcase }}" data-title="{{ function.description | replace: '\n', ' ' }}">{{ function.label }}</a></li>
|
|
{% endfor %}
|
|
</ul>
|
|
|
|
<input id="bin-search" type="text" placeholder="Search among {{ site.gtfobins | size }} binaries: <binary> +<function> ..."/>
|
|
</div>
|
|
|
|
<div id="bin-table-wrapper">
|
|
<table id="bin-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Binary</th>
|
|
<th>Functions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for file in site.gtfobins %}
|
|
<tr>
|
|
<td><a href="{{ file.url }}" class="bin-name">{% include get_bin_name path=file.path %}</a></td>
|
|
<td>{% include function_list.html bin=file %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr><td id="search-message" colspan="2">No binary matches...</td></tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
|
|
<script>
|
|
function filter(query) {
|
|
var queryArray = query.toLowerCase().trim().split(/ *\+/);
|
|
var binPattern = queryArray[0];
|
|
var functionPatterns = queryArray.splice(1);
|
|
|
|
// filter rows
|
|
var noResults = true;
|
|
document.querySelectorAll('#bin-table tbody tr').forEach(function (row) {
|
|
var show = true;
|
|
|
|
var binName = row.children[0].firstElementChild.innerText.toLowerCase();
|
|
if (binName.indexOf(binPattern) === -1) {
|
|
show = false;
|
|
}
|
|
|
|
if (show) {
|
|
var functionElems = Array.from(row.children[1].firstElementChild.children);
|
|
functionElems.forEach((item) => {
|
|
item.className = '';
|
|
});
|
|
functionPatterns.forEach((pattern) => {
|
|
// skip empty filters
|
|
if (!pattern) {
|
|
return;
|
|
}
|
|
// check against the pattern
|
|
var noMatches = true;
|
|
functionElems.forEach((item) => {
|
|
if (item.innerText.toLowerCase().startsWith(pattern.toLowerCase())) {
|
|
item.className = 'match';
|
|
noMatches = false;
|
|
}
|
|
});
|
|
// no function satisfies the pattern
|
|
if (noMatches) {
|
|
show = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (show) {
|
|
row.style.display = '';
|
|
noResults = false;
|
|
} else {
|
|
row.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// update the search message visibility
|
|
var searchMessage = document.getElementById('search-message');
|
|
searchMessage.style.display = noResults ? 'table-cell' : 'none';
|
|
}
|
|
|
|
function applyFilter() {
|
|
// filter on load according to the URL
|
|
var searchBox = document.getElementById('bin-search');
|
|
var query = decodeURIComponent(location.hash.slice(1));
|
|
filter(query);
|
|
if (query) {
|
|
searchBox.value = query;
|
|
}
|
|
}
|
|
|
|
function setup() {
|
|
var searchBox = document.getElementById('bin-search');
|
|
|
|
// ensure height during filtering
|
|
var binTableWrapper = document.getElementById('bin-table-wrapper');
|
|
binTableWrapper.style.height = binTableWrapper.clientHeight + 'px';
|
|
|
|
// handle user input
|
|
searchBox.addEventListener('input', function () {
|
|
var query = searchBox.value;
|
|
history.replaceState(null, null, encodeURI('#' + query));
|
|
applyFilter();
|
|
});
|
|
|
|
// handle shortcuts
|
|
addEventListener('keydown', function (event) {
|
|
// focus search box on valid keydown
|
|
if (event.key.toLowerCase().match(/^[+a-z]$/) &&
|
|
!(event.ctrlKey || event.altKey || event.metaKey)) {
|
|
searchBox.focus();
|
|
searchBox.parentElement.scrollIntoView();
|
|
}
|
|
// clear filter on escape
|
|
else if (event.key === 'Escape') {
|
|
location.hash = searchBox.value = '';
|
|
searchBox.focus();
|
|
searchBox.parentElement.scrollIntoView();
|
|
}
|
|
});
|
|
|
|
// handle URL changes
|
|
window.onhashchange = applyFilter;
|
|
|
|
// trigger filter on page load
|
|
applyFilter();
|
|
}
|
|
|
|
setup();
|
|
</script>
|