GTFOBins.github.io/_includes/bin_table.html

138 lines
4.3 KiB
HTML
Raw Normal View History

<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 }}">{{ function.label }}</a></li>
{% endfor %}
</ul>
<input id="bin-search" type="text" placeholder="Search among {{ site.gtfobins | size }} binaries: <binary> +<function> ..."/>
</div>
2018-05-21 21:14:41 +02:00
<div id="bin-table-wrapper">
2018-05-29 21:52:10 +02:00
<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>
2018-05-21 21:14:41 +02:00
</div>
<script>
function filter(query) {
2018-09-15 16:06:56 +02:00
var queryArray = query.toLowerCase().trim().split(/ *\+/);
var binPattern = queryArray[0];
var functionPatterns = queryArray.splice(1);
// filter rows
var noResults = true;
2018-05-21 21:14:41 +02:00
document.querySelectorAll('#bin-table tbody tr').forEach(function (row) {
2018-09-15 18:20:39 +02:00
var show = true;
2018-05-23 16:00:31 +02:00
var binName = row.children[0].firstElementChild.innerText.toLowerCase();
2018-09-15 18:20:39 +02:00
if (binName.indexOf(binPattern) === -1) {
show = false;
}
2018-09-15 16:06:56 +02:00
2018-09-15 18:20:39 +02:00
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().indexOf(pattern) !== -1) {
item.className = 'match';
noMatches = false;
}
});
// no function satisfies the pattern
if (noMatches) {
show = false;
}
});
}
2018-05-23 16:00:31 +02:00
2018-09-15 16:06:56 +02:00
if (show) {
2018-05-21 21:14:41 +02:00
row.style.display = '';
noResults = false;
} else {
row.style.display = 'none';
}
});
// update the search message visibility
var searchMessage = document.getElementById('search-message');
2018-05-29 21:39:49 +02:00
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;
searchBox.focus();
}
}
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 () {
2018-09-15 16:06:56 +02:00
var query = searchBox.value;
location.hash = query;
});
2018-05-29 12:10:30 +02:00
// handle shortcuts
addEventListener('keydown', function (event) {
2018-05-29 12:10:30 +02:00
// focus search box on valid keydown
2018-09-15 16:06:56 +02:00
if (event.key.toLowerCase().match(/^[+a-z]$/) &&
!(event.ctrlKey || event.altKey || event.metaKey)) {
searchBox.focus();
searchBox.parentElement.scrollIntoView();
}
2018-05-29 12:10:30 +02:00
// clear filter on escape
else if (event.key === 'Escape') {
location.hash = searchBox.value = '';
2018-05-29 12:10:30 +02:00
searchBox.focus();
searchBox.parentElement.scrollIntoView();
2018-05-29 12:10:30 +02:00
}
});
2018-05-21 21:14:41 +02:00
// handle URL changes
window.onhashchange = applyFilter;
// trigger filter on page load
applyFilter();
}
setup();
2018-05-21 21:14:41 +02:00
</script>