Informations
Jump to content

Lorem Ipsum...

Click to Dismiss this Notification
Ładowanie danych...

Comprehensive Buffer Exploit Fix & Anti-Flood System


Recommended Posts

  • Premium+

This guide provides a robust solution for common buffer-related vulnerabilities and packet flooding. Those who have encountered these issues will find these optimizations essential for server stability.

Note: Please ensure you adjust the threshold values within the code to suit your specific server requirements.

Technical Overview

The logic here is straightforward: we set a hard limit on the Network Buffer (8 MB). Without this limit, an attacker could send massive 50MB or 100MB "garbage packets," forcing the buffer to expand indefinitely, leading to RAM exhaustion and Buffer Overflow crashes.

Furthermore, we implement a packet-per-second limit (256 packets) on the descriptor. If a client exceeds this, the connection is dropped immediately to prevent spam. We also handle "ghost connections" by terminating sockets that fail to complete a handshake within 10 seconds.


1. libthecore/src/buffer.c

First, we define our safety limits to prevent uncontrolled memory allocation.

Find:

C++
#define __LIBTHECORE__
#include "stdafx.h"

static LPBUFFER normalized_buffer_pool[32] = { NULL, };

#define DEFAULT_POOL_SIZE 8192

Add below:

C++
#define MAX_NETWORK_BUFFER (8 * 1024 * 1024)

Find LPBUFFER buffer_new and add the size check:

C++
LPBUFFER buffer_new(int size)
{
    if (size < 0) {
        return NULL;
    }
    
    // Safety check for initial buffer size
    if (size > MAX_NETWORK_BUFFER)
    {
        sys_err("buffer_new: size too large (%d)", size);
        return NULL;
    }

Replace the entire buffer_write function to include overflow protection:

C++
void buffer_write(LPBUFFER& buffer, const void *src, int length)
{
    if (!buffer || !src)
        return;

    if (length <= 0)
        return;

    if (length > MAX_NETWORK_BUFFER)
    {
        sys_err("buffer_write: requested length too large (%d)", length);
        return;
    }

    if (buffer->write_point_pos > MAX_NETWORK_BUFFER - length)
    {
        sys_err("buffer_write: write_point_pos overflow (%d + %d)", buffer->write_point_pos, length);
        return;
    }

    if (buffer->write_point_pos + length > MAX_NETWORK_BUFFER)
    {
        sys_err("buffer_write: buffer limit exceeded (%d + %d > %d)",
            buffer->write_point_pos, length, MAX_NETWORK_BUFFER);
        return;
    }

    if (buffer->write_point_pos + length > buffer->mem_size)
    {
        buffer_realloc(buffer, buffer->write_point_pos + length + MIN(10240, length));

        if (!buffer)
            return;

        if (buffer->write_point_pos + length > buffer->mem_size)
        {
            sys_err("buffer_write: realloc failed (%d + %d > %d)",
                buffer->write_point_pos, length, buffer->mem_size);
            return;
        }
    }

    thecore_memcpy(buffer->write_point, src, length);
    buffer_write_proceed(buffer, length);
}

Modify buffer_read_proceed to reset the buffer on overflow instead of aborting:

C++
    if (length < buffer->length)
    {
        if (buffer->read_point + length - buffer->mem_data > buffer->mem_size)
        {
            sys_err("buffer_read_proceed: buffer overflow! length %d read_point %d",
                length, (int)(buffer->read_point - buffer->mem_data));
            buffer_reset(buffer);
            return;
        }

        buffer->read_point += length;
        buffer->length -= length;

Replace buffer_write_proceed with this safer version:

C++
void buffer_write_proceed(LPBUFFER buffer, int length)
{
    if (!buffer)
        return;

    if (length < 0)
    {
        sys_err("buffer_write_proceed: negative length %d", length);
        return;
    }

    if (buffer->write_point_pos + length > buffer->mem_size)
    {
        sys_err("buffer_write_proceed: overflow (%d + %d > %d)",
            buffer->write_point_pos, length, buffer->mem_size);
        return;
    }

    buffer->length += length;
    buffer->write_point += length;
    buffer->write_point_pos += length;
}

Update buffer_adjust_size for strict limit enforcement:

C++
void buffer_adjust_size(LPBUFFER& buffer, int add_size)
{
    if (!buffer)
        return;

    if (add_size <= 0)
        return;

    if (buffer->write_point_pos > MAX_NETWORK_BUFFER - add_size)
    {
        sys_err("buffer_adjust_size: overflow (%d + %d)",
            buffer->write_point_pos, add_size);
        return;
    }

    if (buffer->mem_size >= buffer->write_point_pos + add_size)
        return;

    sys_log(0, "buffer_adjust %d current %d/%d", add_size, buffer->length, buffer->mem_size);
    buffer_realloc(buffer, buffer->write_point_pos + add_size);
}

Add this check to the start of buffer_realloc:

C++
void buffer_realloc(LPBUFFER& buffer, int length)
{
    if (length > MAX_NETWORK_BUFFER)
    {
        // Prevent realloc if it exceeds our safety limit
        return;
    }

2. game/src/desc.cpp & desc.h

We need to track connection times and packet frequency per descriptor.

In desc.h, add these members:

C++
        DWORD            m_dwConnectTime;
        DWORD            m_dwPacketTick;
        int                m_iPacketCounter;

In desc.cpp, initialize these values in DESC::Initialize:

C++
    m_dwConnectTime = 0;
    m_dwPacketTick = 0;
    m_iPacketCounter = 0;

Update DESC::Setup to track the connection start time:

C++
    m_lpFdw        = _fdw;
    m_sock        = _fd;
    m_dwConnectTime = get_global_time(); // Record time of connection

Replace DESC::ProcessInput to include flood protection and handshake timeouts:

C++
int DESC::ProcessInput()
{
    if (!m_lpInputBuffer)
    {
        sys_err("DESC::ProcessInput : nil input buffer");
        return -1;
    }

    const DWORD now = get_dword_time();

    // Reset packet counter every second
    if (now - m_dwPacketTick >= 1000)
    {
        m_dwPacketTick = now;
        m_iPacketCounter = 0;
    }

    // Drop connection if packet spam is detected
    if (++m_iPacketCounter > 256)
    {
        sys_err("DESC::ProcessInput: packet flood from %s", GetHostName());
        return -1;
    }

    // Check for handshake timeout (10 seconds)
    if (m_iPhase == PHASE_HANDSHAKE)
    {
        if (get_global_time() - m_dwConnectTime > 10)
        {
            sys_err("DESC::ProcessInput: handshake timeout %s", GetHostName());
            return -1;
        }
    }

    buffer_adjust_size(m_lpInputBuffer, m_iMinInputBufferLen);

    ssize_t bytes_read = socket_read(
        m_sock,
        (char*)buffer_write_peek(m_lpInputBuffer),
        buffer_has_space(m_lpInputBuffer)
    );

    if (bytes_read < 0)
        return -1;

    if (bytes_read == 0)
        return 0;

    buffer_write_proceed(m_lpInputBuffer, bytes_read);

    // Hard limit on input buffer size (2MB)
    if (buffer_size(m_lpInputBuffer) > (2 * 1024 * 1024))
    {
        sys_err("DESC::ProcessInput: input buffer too large (%u) from %s",
            (unsigned)buffer_size(m_lpInputBuffer), GetHostName());
        return -1;
    }

    if (!m_pInputProcessor)
    {
        sys_err("DESC::ProcessInput: no input processor");
        return -1;
    }

    int iBytesProceed = 0;

    while (!m_pInputProcessor->Process(
        this,
        buffer_read_peek(m_lpInputBuffer),
        buffer_size(m_lpInputBuffer),
        iBytesProceed))
    {
        if (iBytesProceed <= 0)
        {
            sys_err("DESC::ProcessInput: invalid proceed size %d from %s",
                iBytesProceed, GetHostName());
            return -1;
        }

        buffer_read_proceed(m_lpInputBuffer, iBytesProceed);
        iBytesProceed = 0;
    }

    if (iBytesProceed > 0)
        buffer_read_proceed(m_lpInputBuffer, iBytesProceed);

    return bytes_read;
}

3. game/src/desc_manager.cpp

Finally, we implement IP-level filtering to prevent connection floods.

Replace AcceptDesc with the following rate-limiting logic:

C++
#include <map>

static std::map<std::string, int> s_ipConnectionCount;

struct IPFloodInfo
{
    DWORD lastTime;
    int count;
};

static std::map<std::string, IPFloodInfo> s_ipRate;
static DWORD s_lastAcceptTime = 0;
static int s_acceptPerSec = 0;

// Configuration values
#define MAX_CONNECTION_PER_IP 20
#define MAX_ACCEPT_PER_SEC 200
#define MAX_ACCEPT_PER_IP_PER_SEC 10


LPDESC DESC_MANAGER::AcceptDesc(LPFDWATCH fdw, socket_t s)
{
    socket_t desc;
    LPDESC newd;
    static struct sockaddr_in peer;
    static char host[MAX_HOST_LENGTH + 1];

    if ((desc = socket_accept(s, &peer)) == -1)
        return nullptr;

    strlcpy(host, inet_ntoa(peer.sin_addr), sizeof(host));

    DWORD now = get_dword_time();

    // Global accept rate limit
    if (now - s_lastAcceptTime >= 1000)
    {
        s_lastAcceptTime = now;
        s_acceptPerSec = 0;
    }

    if (++s_acceptPerSec > MAX_ACCEPT_PER_SEC)
    {
        socket_close(desc);
        return nullptr;
    }

    // Individual IP rate limit
    IPFloodInfo& info = s_ipRate[host];

    if (now - info.lastTime < 1000)
    {
        if (++info.count > MAX_ACCEPT_PER_IP_PER_SEC)
        {
            socket_close(desc);
            return nullptr;
        }
    }
    else
    {
        info.count = 1;
        info.lastTime = now;
    }

    // Max connections per IP check
    int& count = s_ipConnectionCount[host];

    if (count >= MAX_CONNECTION_PER_IP)
    {
        socket_close(desc);
        return nullptr;
    }

    ++count;

    if (g_bAuthServer)
    {
        if (IsBanIP(peer.sin_addr))
        {
            socket_close(desc);
            return nullptr;
        }
    }

    if (!IsValidIP(admin_ip, host))
    {
        if (m_iSocketsConnected >= MAX_ALLOW_USER)
        {
            socket_close(desc);
            return nullptr;
        }
    }

    newd = M2_NEW DESC;
    crc_t handshake = CreateHandshake();

    if (!newd->Setup(fdw, desc, peer, ++m_iHandleCount, handshake))
    {
        socket_close(desc);
        M2_DELETE(newd);
        return nullptr;
    }

    m_map_handshake.emplace(handshake, newd);
    m_map_handle.emplace(newd->GetHandle(), newd);

    m_set_pkDesc.emplace(newd);
    ++m_iSocketsConnected;

    return newd;
}

Add this to the start of DestroyDesc to clean up the IP counter:

C++
void DESC_MANAGER::DestroyDesc(LPDESC d, bool bEraseFromSet)
{
    if (d->GetHostName() && *d->GetHostName())
    {
        auto it = s_ipConnectionCount.find(d->GetHostName());

        if (it != s_ipConnectionCount.end())
        {
            if (--it->second <= 0)
                s_ipConnectionCount.erase(it);
        }
    }

Summary of Improvements:

  1. CPU Stability: During a simulated attack, CPU usage remains stable because the engine no longer attempts to allocate massive buffers.

  2. Anti-Crash: We removed abort() calls used in other public fixes, which were causing intentional crashes during buffer overflows.

  3. Spam Prevention: Connections are now limited to 256 packets per second and 20 total connections per IP.

  4. Resource Management: Ghost connections and oversized packets (>2MB) are now discarded automatically.

Link to comment
Share on other sites


spacer.png

Hi TechroomsBOT 👋

Thanks for starting a new topic on Techrooms – Blockchain, Programming, Gaming & Crypto Forum!  
If you’re new here — welcome. If you’ve been around for a while — great to have you back 😊

To help you get the most out of TechRooms, here are a few useful places to explore:

────────────────────────────────────
💎 Premium Membership (Optional)
Support the community and unlock extra perks:

🚫 Ad-free browsing  
Faster access & priority support  
📊 Private analysis & signals  
🧪 Early access to beta features & tools  
📥 Downloadable premium resources  

🎟️ Upgrade here: Premium Link
────────────────────────────────────

🧠 Popular Sections You Might Like

📊 Crypto Signals & Market Analysis  
Get free signals and market insights: Signals

💾 Tech Tools & Programs  
Automation, software, utilities & security tools: Tools Techrooms

🗣️ Discussions & Q&A  
Ask questions, share knowledge, help others: Forum

📚 Tech Book Library  
Books, guides and resources for members: Books

📚 Quizzes  
Members Quizzes: Quizzes

🎓 Learning & Courses  
Blockchain, security, coding and more: Blockchain Courses

🧠 Hacking & Firewall Courses 
Hacking, security, firewall and more: Firewall Courses

🪙 Earn Tokens for Posting  
Create valuable content and get rewarded

🃏 Blackjack  
Take a break and play: Blackjack

💖 Support via Crypto Donation (Optional)
Cosmos Wallet: 
cosmos1p5sjqcu3gp9vkjdyc9uee2mw4a4zvjvqz2lj2g 
Donate: Donate

📜 Forum Rules  
Please read before posting: Techrooms Rules

────────────────────────────────────
Stay connected. Stay ahead. Stay TechRooms. 🚀

 

Link to comment
Share on other sites


Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.

spacer.png

Disable AdBlock
The popup will be closed in 5 seconds...