jtwc 发表于 2022-4-20 12:02

各位老师,C++代码输出出现如下错误提示,是啥原因呢??

各位老师,C++代码输出出现如下错误提示,是啥原因呢?谢谢了

wuai习 发表于 2022-4-20 12:07

提示已经指明了:vector subscript out of range,超出存储范围,越界。

xfmjn 发表于 2022-4-20 12:13

嗯,越界访问。

seawaycao 发表于 2022-4-20 12:16

越界了。是不是定义的空间不够。

jtwc 发表于 2022-4-20 12:33

wuai习 发表于 2022-4-20 12:07
提示已经指明了:vector subscript out of range,超出存储范围,越界。

谢谢老师,源码如下,如何修改呢?谢谢了#include <Windows.h>

#include <tchar.h>

#include <stdio.h>

#include <Psapi.h>

#include <iostream>

#include <vector>

#include <string>

#include <map>

#include <ctime>



using namespace std;


/// 字符转字节

int ctoh(char hex)

{

        if (hex >= '0' && hex <= '9') return hex - '0';

        if (hex >= 'A' && hex <= 'F') return hex - 'A' + 10;

        if (hex >= 'a' && hex <= 'f') return hex - 'a' + 10;

        return 0;

}



/// 十六进制字符串转字节数组

std::vector<BYTE> HexStringToBytes(std::string str)

{

        std::vector<BYTE> Bytes;

        for (SIZE_T i = 0; i < str.size(); i++)

        {

                if (str == ' ')

                {

                        continue;

                }

                if (str == '?')

                {

                        Bytes.insert(Bytes.end(), '?');

                        // 兼容OD模式的特征码

                        if (str == '?')

                                i++;

                }

                else if (str == '*') {

                        Bytes.insert(Bytes.end(), '*');

                }

                else {

                        Bytes.insert(Bytes.end(), 0x10 * ctoh(str) + ctoh(str));

                        i++;

                }

        }

        return Bytes;

}

// 获取进程模块句柄

HMODULE GetProcessModuleHandle(DWORD ProcessId, CONST TCHAR* ModuleName)

{

        HMODULE hMods;

        DWORD cbNeeded;

        TCHAR szModName;
       

        HANDLE ProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
       

        if (EnumProcessModulesEx(ProcessHandle, hMods, sizeof(hMods), &cbNeeded, 0x1))

        {

                for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)

                {
                       
                        GetModuleFileNameEx(ProcessHandle, hMods, szModName, sizeof(szModName) / sizeof(TCHAR));

                        if (_tcscmp(szModName, ModuleName)) {

                                return hMods;

                        }

                }

        }

        CloseHandle(ProcessHandle);

        return NULL;

}



// 读字节数组

std::vector<BYTE> ReadBytes(HANDLE ProcessHandle, DWORD_PTR Address, SIZE_T Size)

{

        std::vector<BYTE> Bytes = {};

        Bytes.resize(Size);

        BYTE* Buffer = new BYTE;

        // HANDLE ProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);

        ReadProcessMemory(ProcessHandle, (LPCVOID)Address, Buffer, Size, NULL);

        for (size_t i = 0; i < Size; i++)

        {

                Bytes = Buffer;

        }

        delete[]Buffer;

        // CloseHandle(ProcessHandle);

        return Bytes;

}

// 用来保存模块内存数据

static std::map<CONST TCHAR*, std::map<DWORD_PTR, std::vector<BYTE>>> g_ModuleMemorys;


//256 表示 0x00~0xff 特征码长度不要超过 256

static int maxByteSize = 256;

static int shift = { 0 };

long Sunday(std::vector<byte> T, std::vector<byte> P)

{

        int n = T.size();

        int m = P.size();
       
        // 默认值,移动m+1位 256 表示 0x00~0xff

        for (int i = 0; i < maxByteSize; i++) {

                shift = m + 1;

        }

        // 模式串P中每个字母出现的最后的下标

        // 所对应的主串参与匹配的最末位字符的下一位字符移动到该位,所需要的移动位数

        for (int i = 0; i < m; i++) {

                shift] = m - i;

        }

        // 模式串开始位置在主串的哪里

        int s = 0;

        // 模式串已经匹配到的位置

        int j;

        while (s <= n - m) {

                j = 0;

                while (P == '*' || P == '?' || T == P) {

                        j++;

                        // 匹配成功

                        if (j >= m) {

                                return s;

                        }

                }

                // 找到主串中当前跟模式串匹配的最末字符的下一个字符

                // 在模式串中出现最后的位置

                // 所需要从(模式串末尾+1)移动到该位置的步数

                s += shift];

        }

        return -1;

}



DWORD_PTR FindFeatureCode(DWORD ProcessId, CONST TCHAR* ModuleName, std::string FeatureCodeString)

{

        DWORD_PTR Address = 0;

        DWORD_PTR BeginAddress = 0;

        DWORD_PTR EndAddress = 0;

        HANDLE ProcessHandle = NULL;

        MODULEINFO ModuleInfo;

        MEMORY_BASIC_INFORMATION mbi;

        std::map<DWORD_PTR, std::vector<BYTE>> Memorys;

        std::map<DWORD_PTR, std::vector<BYTE>>::iterator it;
       
        std::vector<BYTE> FeatureCode = HexStringToBytes(FeatureCodeString);
       
        // 这里获取模块内存信息

        if (g_ModuleMemorys.find(ModuleName) == g_ModuleMemorys.end())

        {

                //printf("%s\n", "123456");

                ProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);



                GetModuleInformation(ProcessHandle, GetProcessModuleHandle(ProcessId, ModuleName), &ModuleInfo, sizeof(ModuleInfo));



                BeginAddress = (DWORD_PTR)ModuleInfo.lpBaseOfDll;

                EndAddress = (DWORD_PTR)ModuleInfo.lpBaseOfDll + ModuleInfo.SizeOfImage;



                while (BeginAddress <= EndAddress)

                {

                        ::VirtualQueryEx(ProcessHandle, (LPCVOID)BeginAddress, &mbi, sizeof(mbi));



                        if (mbi.Protect != 1 && mbi.Protect != 16 && mbi.Protect != 512 && mbi.RegionSize > 1)

                        {



                                g_ModuleMemorys.insert(std::pair<DWORD_PTR, std::vector<BYTE>>(BeginAddress, ReadBytes(ProcessHandle, BeginAddress, mbi.RegionSize)));

                        }



                        BeginAddress += mbi.RegionSize;

                }

                CloseHandle(ProcessHandle);

        }



        Memorys = g_ModuleMemorys;



        it = Memorys.begin();



        while (it != Memorys.end())

        {

                long offset = Sunday(it->second, FeatureCode);

                if (offset >= 0)

                {

                        Address = it->first + offset;

                        goto _exit;

                }

                it++;

        }
       
_exit:

        return Address;

}



int main(int argc, char const* argv[])

{

        clock_t startTime, endTime;

        startTime = clock();//计时开始
       
        // 特征码字符串格式随意这里是拿网易的有道词典测试的

        ULONG address = 0;//2332, "PlantsVsZombies.exe", " AF 00 00 00 14 00 00 00 C5 15 "
       
        address = FindFeatureCode(2332, "PlantsVsZombies.exe", "3E A0 ?? ?? ?? ?? 3E AC 3E B0 ?? B4 ?? B8 ?? ?? ?? ?? 3E C4 3E C8 3E CC ?? D0 3E D4 ?? D8 3E DC 3E E0 ?? E4 ?? E8 ?? ?? ?? ??");
       
        printf("address %x\n", address);
       
        endTime = clock();//计时结束

        printf("运行时间: %f/s\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);

        system("pause");

        return 0;
}


tony666 发表于 2022-4-20 14:25

直接调试运行,报错时候看堆栈,定位到自己的代码,就看出来为什么了
图里这个报错是vector越界

wuai习 发表于 2022-4-20 14:44

jtwc 发表于 2022-4-20 12:33
谢谢老师,源码如下,如何修改呢?谢谢了#include

#include


std::vector<BYTE> ReadBytes(HANDLE ProcessHandle, DWORD_PTR Address, SIZE_T Size)

{

    std::vector<BYTE> Bytes = {};

    Bytes.resize(Size);

    BYTE* Buffer = new BYTE;



DWORD_PTR FindFeatureCode(DWORD ProcessId, CONST TCHAR* ModuleName, std::string FeatureCodeString)

{

while (BeginAddress <= EndAddress)

      {

            ::VirtualQueryEx(ProcessHandle, (LPCVOID)BeginAddress, &mbi, sizeof(mbi));



            if (mbi.Protect != 1 && mbi.Protect != 16 && mbi.Protect != 512 && mbi.RegionSize > 1)

            {


                g_ModuleMemorys.insert(std::pair<DWORD_PTR, std::vector<BYTE>>(BeginAddress, ReadBytes(ProcessHandle, BeginAddress, mbi.RegionSize)));

            }

我这边看到的是,你这个mbi.RegionSize的大小是int类型的最大值,ReadBytes函数传入了这个参数作为size,可能是这一块儿导致的,具体原因你自己在调试分析一下。

jtwc 发表于 2022-4-20 15:14

wuai习 发表于 2022-4-20 14:44
std::vector ReadBytes(HANDLE ProcessHandle, DWORD_PTR Address, SIZE_T Size)
...

谢谢了,老师,好像是下图红线部分报错,如何改呢?

wuai习 发表于 2022-4-20 15:55

我查了一下你这个源代码是CSDN上的吧,这个大体思路是对的。
但是由于MEMORY_BASIC_INFORMATION的大小实在是太大了,用readbyte这个函数,这里的size超出了设定。
你可以参考一下这篇文章https://www.cnblogs.com/LyShark/p/15019490.html
采用分割内存的方式进行读取。

hl_ke 发表于 2022-4-20 16:07

没有那么复杂,仔细看下面两行代码
for (SIZE_T i = 0; i < str.size(); i++)

Bytes.insert(Bytes.end(), 0x10 * ctoh(str) + ctoh(str));

str下标已经变成了 str,很明显的越界访问。
页: [1] 2
查看完整版本: 各位老师,C++代码输出出现如下错误提示,是啥原因呢??