it seems this pulling the offsets from data which is right but when you search it in in ida it should point to the string name in rdata which it dont it poinbts to data #include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tlhelp32.h>
#include <string>
#include <psapi.h>
#include <vector>

void log_message(FILE* log_file, const char* format, ...) {
    va_list args;
    va_start(args, format);
    vprintf(format, args); // Console output
    if (log_file != NULL) {
        vfprintf(log_file, format, args); // File output
        fflush(log_file);
    }
    va_end(args);
}

DWORD get_process_id_by_name(const char* process_name) {
    PROCESSENTRY32 pe32;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return 0;
    }
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hSnapshot, &pe32)) {
        CloseHandle(hSnapshot);
        return 0;
    }
    do {
        char exeFile[MAX_PATH];
        size_t converted_chars = 0;
        wcstombs_s(&converted_chars, exeFile, MAX_PATH, pe32.szExeFile, _TRUNCATE);
        if (_stricmp(exeFile, process_name) == 0) {
            CloseHandle(hSnapshot);
            return pe32.th32ProcessID;
        }
    } while (Process32Next(hSnapshot, &pe32));

    CloseHandle(hSnapshot);
    return 0;
}

unsigned long long get_base_address(DWORD pid) {
    MODULEENTRY32 me32;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
    if (hSnapshot == INVALID_HANDLE_VALUE) {
        return 0;
    }
    me32.dwSize = sizeof(MODULEENTRY32);
    if (!Module32First(hSnapshot, &me32)) {
        CloseHandle(hSnapshot);
        return 0;
    }
    unsigned long long base_address = (unsigned long long)me32.modBaseAddr;
    CloseHandle(hSnapshot);
    return base_address;
}

bool get_section_limits(HANDLE hProcess, unsigned long long base_addr, const char* section_name, unsigned long long& section_start, unsigned long long& section_end) {
    IMAGE_DOS_HEADER dos_header;
    if (!ReadProcessMemory(hProcess, (LPCVOID)base_addr, &dos_header, sizeof(dos_header), NULL)) {
        return false;
    }
    if (dos_header.e_magic != IMAGE_DOS_SIGNATURE) {
        return false;
    }
    IMAGE_NT_HEADERS nt_headers;
    if (!ReadProcessMemory(hProcess, (LPCVOID)(base_addr + dos_header.e_lfanew), &nt_headers, sizeof(nt_headers), NULL)) {
        return false;
    }
    if (nt_headers.Signature != IMAGE_NT_SIGNATURE) {
        return false;
    }
    IMAGE_SECTION_HEADER* section_headers = new IMAGE_SECTION_HEADER[nt_headers.FileHeader.NumberOfSections];
    if (!ReadProcessMemory(hProcess, (LPCVOID)((unsigned long long)(base_addr + dos_header.e_lfanew) + sizeof(nt_headers)), section_headers, sizeof(IMAGE_SECTION_HEADER) * nt_headers.FileHeader.NumberOfSections, NULL)) {
        delete[] section_headers;
        return false;
    }
    for (int i = 0; i < nt_headers.FileHeader.NumberOfSections; ++i) {
        if (strncmp((char*)section_headers[i].Name, section_name, IMAGE_SIZEOF_SHORT_NAME) == 0) {
            section_start = base_addr + section_headers[i].VirtualAddress;
            section_end = section_start + section_headers[i].Misc.VirtualSize;
            delete[] section_headers;
            return true;
        }
    }
    delete[] section_headers;
    return false;
}

std::vector<std::pair<std::string, unsigned long long>> find_strings_in_section(HANDLE hProcess, unsigned long long section_start, unsigned long long section_end, size_t min_length) {
    std::vector<std::pair<std::string, unsigned long long>> strings;
    unsigned long long addr = section_start;
    while (addr < section_end) {
        MEMORY_BASIC_INFORMATION mbi;
        if (!VirtualQueryEx(hProcess, (LPCVOID)addr, &mbi, sizeof(mbi))) {
            break;
        }

        if (mbi.State == MEM_COMMIT && (mbi.Protect == PAGE_READONLY || mbi.Protect == PAGE_READWRITE)) {
            char* buffer = new char[mbi.RegionSize];
            SIZE_T bytesRead;
            if (ReadProcessMemory(hProcess, (LPCVOID)addr, buffer, mbi.RegionSize, &bytesRead) && bytesRead > 0) {
                for (SIZE_T i = 0; i < bytesRead;) {
                    if (isprint(buffer[i]) && isprint(buffer[i + 1]) && isprint(buffer[i + 2])) {
                        std::string possible_string;
                        SIZE_T j = i;
                        while (j < bytesRead && isprint(buffer[j]) && buffer[j] != '\0') {
                            possible_string += buffer[j];
                            j++;
                        }
                        if (possible_string.length() >= min_length) {
                            strings.emplace_back(possible_string, addr + i);
                        }
                        i = j; // Move i to the end of the found string
                    }
                    else {
                        i++;
                    }
                }
            }
            delete[] buffer;
        }

        addr += mbi.RegionSize;
    }
    return strings;
}

unsigned long long find_reference_in_data_section(HANDLE hProcess, unsigned long long section_start, unsigned long long section_end, unsigned long long string_addr) {
    unsigned long long addr = section_start;
    while (addr < section_end) {
        MEMORY_BASIC_INFORMATION mbi;
        if (!VirtualQueryEx(hProcess, (LPCVOID)addr, &mbi, sizeof(mbi))) {
            break;
        }

        if (mbi.State == MEM_COMMIT && (mbi.Protect == PAGE_READWRITE || mbi.Protect == PAGE_EXECUTE_READWRITE || mbi.Protect == PAGE_EXECUTE_WRITECOPY || mbi.Protect == PAGE_WRITECOPY)) {
            char* buffer = new char[mbi.RegionSize];
            SIZE_T bytesRead;
            if (ReadProcessMemory(hProcess, (LPCVOID)addr, buffer, mbi.RegionSize, &bytesRead) && bytesRead > 0) {
                for (SIZE_T i = 0; i < bytesRead - sizeof(unsigned long long); ++i) {
                    unsigned long long* potential_ptr = (unsigned long long*)(buffer + i);
                    if (*potential_ptr == string_addr) {
                        unsigned long long reference_addr = addr + i;
                        delete[] buffer;
                        return reference_addr;
                    }
                }
            }
            delete[] buffer;
        }

        addr += mbi.RegionSize;
    }
    return 0;
}

int main() {
    const char* process_name = "Fallout76.exe";
    const size_t minStringLength = 5; // Define the minimum string length you consider a valid string

    FILE* log_file;
    if (fopen_s(&log_file, "memscan.log", "w") != 0) {
        printf("Could not open log file for writing\n");
        return 1;
    }

    DWORD pid = get_process_id_by_name(process_name);
    if (pid == 0) {
        log_message(log_file, "Could not find process ID for \"%s\"\n", process_name);
        fclose(log_file);
        return 1;
    }

    unsigned long long base_addr = get_base_address(pid);
    log_message(log_file, "Base Address: 0x%llx\n", base_addr);

    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
    if (hProcess == NULL) {
        log_message(log_file, "Could not open process \"%s\"\n", process_name);
        fclose(log_file);
        return 1;
    }

    unsigned long long rdata_section_start, rdata_section_end;
    if (!get_section_limits(hProcess, base_addr, ".rdata", rdata_section_start, rdata_section_end)) {
        log_message(log_file, "Failed to get limits for .rdata section\n");
        CloseHandle(hProcess);
        fclose(log_file);
        return 1;
    }

    unsigned long long data_section_start, data_section_end;
    if (!get_section_limits(hProcess, base_addr, ".data", data_section_start, data_section_end)) {
        log_message(log_file, "Failed to get limits for .data section\n");
        CloseHandle(hProcess);
        fclose(log_file);
        return 1;
    }

    log_message(log_file, "$strings_with_offsets = [\n");

    auto rdata_strings = find_strings_in_section(hProcess, rdata_section_start, rdata_section_end, minStringLength);
    for (const auto& item : rdata_strings) {
        unsigned long long string_addr = item.second;
        unsigned long long reference_addr = find_reference_in_data_section(hProcess, data_section_start, data_section_end, string_addr);

        if (reference_addr != 0) {
            // Subtract 0x10 from reference address if needed depending on structure analysis
            unsigned long long function_pointer = reference_addr - 0x10;
            unsigned long long offset = function_pointer - base_addr;

            // Log detailed addresses for debugging
            log_message(log_file, "String: \"%s\"\n", item.first.c_str());
            log_message(log_file, "String Address: 0x%llx\n", string_addr);
            log_message(log_file, "Reference Address: 0x%llx\n", reference_addr);
            log_message(log_file, "Function Pointer (Adjusted): 0x%llx\n", function_pointer);
            log_message(log_file, "Offset from Base: 0x%llx\n", offset);

            if (offset >= 0) {
                log_message(log_file, "    \"%s\" at offset: 0x%llx\n", item.first.c_str(), offset);
            }
            else {
                log_message(log_file, "Error: Calculated offset is negative or out of bounds.\n");
            }
        }
    }

    log_message(log_file, "];\n");

    CloseHandle(hProcess);
    fclose(log_file);

    return 0;
}