C++ for Cyber Security

Build high-performance security tools with C++ - from network scanners to malware analyzers. Combines C's power with modern OOP and safety features.

Why C++ for Security

C++ combines C's low-level access with object-oriented programming, making it ideal for building professional-grade security tools. Many commercial security products, antivirus engines, and network scanners are written in C++.

  • Performance - Near-C speed for real-time packet processing and analysis.
  • OOP - Clean architecture for complex security tools with classes and inheritance.
  • STL - Standard Template Library provides containers, algorithms, and iterators.
  • Memory control - Smart pointers for safe memory management.
  • Cross-platform - Build tools for Linux, Windows, and embedded systems.

C++ Basics

cpp
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

struct ScanResult {
    int port;
    bool open;
    std::string service;
};

int main() {
    // Vector for dynamic arrays
    std::vector<ScanResult> results;

    // Map for service lookup
    std::map<int, std::string> services = {
        {22, "SSH"}, {80, "HTTP"}, {443, "HTTPS"}
    };

    // Range-based for loop
    for (const auto& [port, name] : services) {
        results.push_back({port, true, name});
        std::cout << "[+] Port " << port << ": " << name << std::endl;
    }

    // Lambda for filtering
    auto https_results = std::find_if(results.begin(), results.end(),
        [](const ScanResult& r) { return r.service == "HTTPS"; });

    if (https_results != results.end()) {
        std::cout << "Found HTTPS on port " << https_results->port << std::endl;
    }

    return 0;
}

OOP for Security Tools

cpp - SecurityScanner.h
#include <iostream>
#include <string>
#include <vector>
#include <functional>

// Abstract base class for security scanners
class Scanner {
protected:
    std::string target;
    int timeout;

public:
    Scanner(const std::string& t, int tm = 3)
        : target(t), timeout(tm) {}

    virtual ~Scanner() = default;

    // Pure virtual - must be implemented
    virtual void scan() = 0;
    virtual std::string name() const = 0;
};

// Concrete port scanner
class PortScanner : public Scanner {
private:
    int start_port, end_port;

public:
    PortScanner(const std::string& t, int s, int e)
        : Scanner(t), start_port(s), end_port(e) {}

    void scan() override {
        std::cout << "Scanning ports " << start_port
                  << "-" << end_port << " on " << target << std::endl;
    }

    std::string name() const override { return "PortScanner"; }
};

// Concrete web scanner
class WebScanner : public Scanner {
private:
    std::vector<std::string> paths;

public:
    WebScanner(const std::string& t)
        : Scanner(t), paths({"/admin", "/backup", "/.env"}) {}

    void scan() override {
        for (const auto& path : paths) {
            std::cout << "Checking " << target << path << std::endl;
        }
    }

    std::string name() const override { return "WebScanner"; }
};

Memory Management

cpp
#include <memory>
#include <iostream>

// Raw pointer - DANGEROUS (C-style)
void dangerous() {
    int* ptr = new int(42);
    // If exception thrown here, ptr leaks!
    delete ptr;  // Easy to forget
}

// Smart pointers - SAFE (modern C++)
void safe() {
    // unique_ptr - exclusive ownership
    auto uptr = std::make_unique<int>(42);

    // shared_ptr - reference counted
    auto sptr = std::make_shared<std::string>("secret");
    auto sptr2 = sptr;  // Both point to same data

    // Automatically freed when scope ends - no leaks!
}

// RAII for security resources
class Socket {
private:
    int fd;
public:
    Socket(int domain, int type)
        : fd(socket(domain, type, 0)) {}

    ~Socket() {
        if (fd >= 0) close(fd);  // Auto-cleanup!
    }

    int get_fd() const { return fd; }
    bool is_valid() const { return fd >= 0; }
};

Network Programming

cpp - port_scanner.cpp
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <atomic>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

std::mutex cout_mutex;
std::atomic<int> open_count(0);

void scan_port(const std::string& ip, int port) {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) return;

    struct sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    inet_pton(AF_INET, ip.c_str(), &addr.sin_addr);

    // Set timeout
    struct timeval tv{.tv_sec = 1};
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
        std::lock_guard<std::mutex> lock(cout_mutex);
        std::cout << "[+] Port " << port << " OPEN" << std::endl;
        open_count++;
    }
    close(sock);
}

int main(int argc, char** argv) {
    std::string target = (argc > 1) ? argv[1] : "127.0.0.1";
    std::vector<std::thread> threads;

    for (int port = 1; port <= 1024; port++) {
        threads.emplace_back(scan_port, target, port);
        if (threads.size() >= 100) {
            for (auto& t : threads) t.join();
            threads.clear();
        }
    }
    for (auto& t : threads) t.join();

    std::cout << "\nFound " << open_count << " open ports" << std::endl;
    return 0;
}

Building Security Tools

cpp - network_tool.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <thread>
#include <mutex>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

class ServiceDetector {
private:
    std::map<int, std::string> common_services = {
        {21, "FTP"}, {22, "SSH"}, {25, "SMTP"},
        {80, "HTTP"}, {443, "HTTPS"}, {3306, "MySQL"},
        {3389, "RDP"}, {5432, "PostgreSQL"}, {8080, "HTTP-Alt"}
    };
    std::string host;
    std::mutex result_mutex;
    std::vector<std::pair<int, std::string>> open_services;

public:
    ServiceDetector(const std::string& h) : host(h) {}

    void detect(int port) {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) return;

        struct sockaddr_in addr{};
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        inet_pton(AF_INET, host.c_str(), &addr.sin_addr);

        struct timeval tv{.tv_sec = 2};
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));

        if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
            std::string service = common_services.count(port) ?
                common_services[port] : "Unknown";
            std::lock_guard<std::mutex> lock(result_mutex);
            open_services.emplace_back(port, service);
        }
        close(sock);
    }

    void run(int start = 1, int end = 1024) {
        std::vector<std::thread> threads;
        for (int p = start; p <= end; p++) {
            threads.emplace_back(&ServiceDetector::detect, this, p);
            if (threads.size() >= 100) {
                for (auto& t : threads) t.join();
                threads.clear();
            }
        }
        for (auto& t : threads) t.join();

        std::sort(open_services.begin(), open_services.end());
        for (const auto& [port, svc] : open_services) {
            std::cout << "[+] Port " << port << ": " << svc << std::endl;
        }
    }
};

int main(int argc, char** argv) {
    std::string target = (argc > 1) ? argv[1] : "127.0.0.1";
    ServiceDetector scanner(target);
    std::cout << "[*] Scanning " << target << std::endl;
    scanner.run();
    return 0;
}
Practice

Extend this tool by adding SSL/TLS certificate checking, HTTP response analysis, and vulnerability signature matching.

Resources

  • C++ Reference: cplusplus.com
  • Effective C++: Scott Meyers
  • Network Security Tools: Building custom tools with C++ sockets
  • Rootkits and Botnets: Understanding at the system level