lossen the regex ensure all strings come from the rdata section then get there offsets from the datta section #include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <regex>
#include <memory>

// Struct for safely closing handles.
struct HandleCloser {
    void operator()(HANDLE handle) const {
        if (handle && handle != INVALID_HANDLE_VALUE) {
            CloseHandle(handle);
        }
    }
};

// Unique pointer type for Windows HANDLE
using UniqueHandle = std::unique_ptr<std::remove_pointer<HANDLE>::type, HandleCloser>;

// Section structure for storing section info
struct Section {
    std::string name;
    uintptr_t start;
    uintptr_t end;

    Section(const std::string& n = "", uintptr_t s = 0, uintptr_t e = 0) : name(n), start(s), end(e) {}
};

// Function for logging messages to a file
void log_message(std::ofstream& log_file, const char* format, ...) {
    va_list args;
    va_start(args, format);
    char buffer[2048];
    vsnprintf(buffer, sizeof(buffer), format, args);
    va_end(args);

    log_file << buffer << std::endl;
    log_file.flush();
}

// Convert wide string to multibyte string for process and module names
std::string ws2s(const std::wstring& wstr) {
    int bufferSize = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string str(bufferSize - 1, 0);
    WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], bufferSize, nullptr, nullptr);
    return str;
}

// Retrieve a process ID by its process name.
DWORD get_process_id_by_name(const std::string& process_name, std::ofstream& log_file) {
    UniqueHandle hSnapshot(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
    if (!hSnapshot || hSnapshot.get() == INVALID_HANDLE_VALUE) {
        log_message(log_file, "CreateToolhelp32Snapshot failed with error: %lu", GetLastError());
        return 0;
    }

    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    if (!Process32First(hSnapshot.get(), &pe32)) {
        log_message(log_file, "Process32First failed with error: %lu", GetLastError());
        return 0;
    }

    do {
        if (_stricmp(ws2s(pe32.szExeFile).c_str(), process_name.c_str()) == 0) {
            return pe32.th32ProcessID;
        }
    } while (Process32Next(hSnapshot.get(), &pe32));

    return 0;
}

// Get base address of the main module for a given PID.
uintptr_t get_base_address(DWORD pid, const std::string& process_name, std::ofstream& log_file) {
    UniqueHandle hSnapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid));
    if (!hSnapshot || hSnapshot.get() == INVALID_HANDLE_VALUE) {
        log_message(log_file, "CreateToolhelp32Snapshot for modules failed with error: %lu", GetLastError());
        return 0;
    }

    MODULEENTRY32 me32;
    me32.dwSize = sizeof(me32);
    if (!Module32First(hSnapshot.get(), &me32)) {
        log_message(log_file, "Module32First failed with error: %lu", GetLastError());
        return 0;
    }

    do {
        if (_stricmp(ws2s(me32.szModule).c_str(), process_name.c_str()) == 0) {
            log_message(log_file, "Main module %s found at base address 0x%llX", ws2s(me32.szModule).c_str(), reinterpret_cast<unsigned long long>(me32.modBaseAddr));
            return reinterpret_cast<uintptr_t>(me32.modBaseAddr);
        }
    } while (Module32Next(hSnapshot.get(), &me32));

    log_message(log_file, "Main module not found in the module list.");
    return 0;
}

// Extract sections from PE headers.
bool get_sections(HANDLE hProcess, uintptr_t base_addr, std::vector<Section>& sections, std::ofstream& log_file) {
    IMAGE_DOS_HEADER dosHeader;
    SIZE_T bytesRead;
    if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(base_addr), &dosHeader, sizeof(dosHeader), &bytesRead) || bytesRead != sizeof(dosHeader)) {
        log_message(log_file, "Failed to read DOS header. Error: %lu", GetLastError());
        return false;
    }

    if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
        log_message(log_file, "Invalid DOS signature.");
        return false;
    }

    uintptr_t ntHeaderAddr = base_addr + dosHeader.e_lfanew;
    DWORD signature;
    if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(ntHeaderAddr), &signature, sizeof(signature), &bytesRead) || bytesRead != sizeof(signature)) {
        log_message(log_file, "Failed to read NT headers signature. Error: %lu", GetLastError());
        return false;
    }

    if (signature != IMAGE_NT_SIGNATURE) {
        log_message(log_file, "Invalid NT signature.");
        return false;
    }

    IMAGE_FILE_HEADER fileHeader;
    if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(ntHeaderAddr + sizeof(DWORD)), &fileHeader, sizeof(fileHeader), &bytesRead) || bytesRead != sizeof(fileHeader)) {
        log_message(log_file, "Failed to read IMAGE_FILE_HEADER. Error: %lu", GetLastError());
        return false;
    }

    WORD sizeOfOptionalHeader = fileHeader.SizeOfOptionalHeader;
    uintptr_t optionalHeaderAddr = ntHeaderAddr + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER);

    WORD magic;
    if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(optionalHeaderAddr), &magic, sizeof(magic), &bytesRead) || bytesRead != sizeof(magic)) {
        log_message(log_file, "Failed to read Optional Header Magic. Error: %lu", GetLastError());
        return false;
    }

    uintptr_t sectionHeaderAddr = optionalHeaderAddr + sizeOfOptionalHeader;
    for (int i = 0; i < fileHeader.NumberOfSections; ++i) {
        IMAGE_SECTION_HEADER sectionHeader;
        if (!ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(sectionHeaderAddr + i * sizeof(IMAGE_SECTION_HEADER)), &sectionHeader, sizeof(sectionHeader), &bytesRead) || bytesRead != sizeof(sectionHeader)) {
            log_message(log_file, "Failed to read IMAGE_SECTION_HEADER for section %d. Error: %lu", i + 1, GetLastError());
            return false;
        }

        std::string secName(reinterpret_cast<char*>(sectionHeader.Name), 8);
        uintptr_t sectionStart = base_addr + sectionHeader.VirtualAddress;
        uintptr_t sectionEnd = sectionStart + sectionHeader.Misc.VirtualSize;

        sections.emplace_back(secName, sectionStart, sectionEnd);
        log_message(log_file, "Section %s: Start=0x%llX, End=0x%llX (Relative: Start=0x%llX, End=0x%llX)", secName.c_str(), static_cast<unsigned long long>(sectionStart), static_cast<unsigned long long>(sectionEnd), static_cast<unsigned long long>(sectionStart - base_addr), static_cast<unsigned long long>(sectionEnd - base_addr));
    }

    return true;
}

// Function to identify and collect strings based on expected naming conventions
std::vector<std::pair<std::string, uintptr_t>> extract_dynamic_strings(HANDLE hProcess, uintptr_t section_start, uintptr_t section_end, std::ofstream& log_file) {
    std::vector<std::pair<std::string, uintptr_t>> found_strings;
    uintptr_t addr = section_start;
    const size_t MIN_STRING_LENGTH = 12;  // Minimum length for variable-style strings
    const std::regex pattern(R"([fbpiu][A-Z][a-zA-Z0-9]+)");  // Example regex for variable-style strings

    while (addr < section_end) {
        MEMORY_BASIC_INFORMATION mbi;
        if (!VirtualQueryEx(hProcess, reinterpret_cast<LPCVOID>(addr), &mbi, sizeof(mbi))) {
            log_message(log_file, "VirtualQueryEx failed at address 0x%llX with error: %lu",
                static_cast<unsigned long long>(addr), GetLastError());
            break;
        }

        if (mbi.State == MEM_COMMIT &&
            (mbi.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | PAGE_READONLY | PAGE_EXECUTE_READ))) {

            SIZE_T regionSize = mbi.RegionSize;
            if (addr + regionSize > section_end) {
                regionSize = section_end - addr;
            }

            std::vector<char> buffer(regionSize);
            SIZE_T bytesReadMem;
            if (ReadProcessMemory(hProcess, reinterpret_cast<LPCVOID>(addr), buffer.data(), regionSize, &bytesReadMem) && bytesReadMem > 0) {
                for (SIZE_T i = 0; i < bytesReadMem; ) {
                    if (isprint(buffer[i]) || buffer[i] == '\0') {
                        size_t j = i;
                        while (j < bytesReadMem && (isprint(buffer[j]) || buffer[j] == '\0')) {
                            ++j;
                        }
                        if (j - i >= MIN_STRING_LENGTH) {
                            std::string found_str(buffer.data() + i, j - i);

                            // Apply regex pattern for dynamic filtering
                            if (std::regex_match(found_str, pattern)) {
                                uintptr_t found_addr = addr + i;
                                found_strings.push_back({ found_str, found_addr });
                                log_message(log_file, "Found candidate string \"%s\" at absolute address: 0x%llX", found_str.c_str(), static_cast<unsigned long long>(found_addr));
                            }
                            i = j;
                        }
                        else {
                            ++i;
                        }
                    }
                    else {
                        ++i;
                    }
                }
            }

            addr += regionSize;
        }
        else {
            addr += mbi.RegionSize;
        }
    }

    return found_strings;
}

int main() {
    std::string process_name;
    std::cout << "Enter the process name (e.g., notepad.exe): ";
    std::getline(std::cin, process_name);

    std::ofstream log_file("memscan_detailed.log", std::ios::out);
    if (!log_file.is_open()) {
        std::cerr << "Could not open log file for writing\n";
        return 1;
    }

    DWORD pid = get_process_id_by_name(process_name, log_file);
    if (pid == 0) {
        log_message(log_file, "Process %s not found.", process_name.c_str());
        std::cerr << "Process not found. Check the process name and ensure it's running.\n";
        return 1;
    }
    log_message(log_file, "Found process %s with PID: %u", process_name.c_str(), pid);
    std::cout << "Found process " << process_name << " with PID: " << pid << "\n";

    uintptr_t base_addr = get_base_address(pid, process_name, log_file);
    if (base_addr == 0) {
        log_message(log_file, "Failed to get base address for process ID %u.", pid);
        std::cerr << "Failed to get base address.\n";
        return 1;
    }
    log_message(log_file, "Base address of %s: 0x%llX", process_name.c_str(), static_cast<unsigned long long>(base_addr));
    std::cout << "Base address of " << process_name << ": 0x" << std::hex << base_addr << std::dec << "\n";

    UniqueHandle hProcess(OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid));
    if (!hProcess) {
        log_message(log_file, "Failed to open process with PID %u. Error: %lu", pid, GetLastError());
        std::cerr << "Failed to open process. Ensure you have the necessary permissions.\n";
        return 1;
    }
    log_message(log_file, "Successfully opened process handle.\n");

    std::vector<Section> all_sections;
    if (!get_sections(hProcess.get(), base_addr, all_sections, log_file)) {
        log_message(log_file, "Failed to retrieve sections.");
        std::cerr << "Failed to retrieve sections.\n";
        return 1;
    }

    // Filter for .data and .rdata sections to analyze
    std::vector<Section> data_sections;
    for (const auto& section : all_sections) {
        if (section.name == ".data" || section.name == ".rdata") {
            data_sections.push_back(section);
            log_message(log_file, "Data section for processing: %s", section.name.c_str());
        }
    }

    // Extract dynamic strings from the .data and .rdata sections
    std::vector<std::pair<std::string, uintptr_t>> all_strings;
    for (const auto& section : data_sections) {
        auto strings = extract_dynamic_strings(hProcess.get(), section.start, section.end, log_file);
        all_strings.insert(all_strings.end(), strings.begin(), strings.end());
    }

    log_message(log_file, "\nExtracted Strings:\n");
    for (const auto& str_pair : all_strings) {
        uintptr_t relative_offset = str_pair.second - base_addr;
        log_message(log_file, "String: \"%s\" at 0x%llX (relative offset 0x%llX)", str_pair.first.c_str(),
            static_cast<unsigned long long>(str_pair.second), static_cast<unsigned long long>(relative_offset));
    }

    std::cout << "String extraction complete. Check log for details.\n";
    std::cout << "Press Enter to exit...";
    std::cin.get();

    return 0;
}