【问题标题】:C++ searching through memory for a binary sequence that match a patternC++ 在内存中搜索匹配模式的二进制序列
【发布时间】:2021-02-16 07:43:43
【问题描述】:

我确信这个问题已经在某个地方提出并解决了,但实际上我并没有真正找到适合我的任何东西。

我正在尝试编写一个 DLL,它需要在应用程序的 .text 部分中查找某些内容。我想我可以设法找到包含我想要的内容的 .text 部分,所以我认为,我应该能够获得一个包含整个 .text 部分的字节数组(无符号字符 *?)(?)

现在,由于到处都有指针,我想我需要使用正则表达式来忽略某些字节,这些字节可能会根据应用程序的版本而改变。

那么找到我的模式的最佳方法是什么? 这种模式的一个例子: "48 8d ?? ?? ?? ?? ?? e8"

【问题讨论】:

  • 您可以只使用简单的find 获取48 8d 字节,然后在每场比赛中检查e8

标签: c++ arrays regex memory pattern-matching


【解决方案1】:

使用正则表达式是不必要的工作。你想要的是一种用“匹配任何东西”的标记来指定字节模式的方法。

不幸的是,您不能使用任何unsigned char 值,因为所有可用值(从0x00xff)都是可能的匹配项。一种解决方案可能是为此使用uint16_t 而不是uint8_t,并使用0xff 以上的任何值来具有特殊含义。对于您的示例,假设您为此选择0xffff

const uint16_t pattern[] = { 0x48, 0x8d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xe8 };

您现在必须逐字节进行匹配(您不能再直接使用memcmpfind 之类的东西):

#define pattern_match_anything  0xffff

// Checks if the text[start_index:text_size] region matches pattern.
bool check_at_index(const uint8_t *text, size_t text_size, size_t start_index, const uint16_t *pattern)
{
    size_t pattern_index = 0;
    
    // Some bounds checks omitted for simplicity.
    for (size_t i = start_index; i < text_size; i++)
    {
        if (pattern[pattern_index] == pattern_match_anything)
        {
            pattern_index++;
            continue;
        }
        
        if (text[i] != pattern[pattern_index]) return false;

        pattern_index++;
    }
    
    return true;
}

【讨论】:

  • 或者你可以使用std::optional&lt;unsigned char&gt;作为模式。
  • @MSalters 是的,你可以。您仍然必须独立处理每个字节,这是这种方法的主要缺点。
  • 没错,但您可以通过使用std::search 和处理std::optional&lt;unsigned char&gt; 的自定义谓词来解决这个问题。
【解决方案2】:

您当然可以为此使用正则表达式,虽然这可能不是最快的方法,但这取决于您的需要。你只是想找到职位吗?是否要提取内存区域的副本?或者只是比赛中的一些内存位置?

这是一个std::regex 选项:

char const* find_chunk(char const* const beg, char const* const end)
{
    static std::regex const re{R"(\x48\x8D....\xE8)", std::regex_constants::optimize};

    std::cmatch m;
    if(!std::regex_search(beg, end, m, re))
        return end;

    return m[0].first;
}

一种可能更快的方法是手动检查图案部分,如下所示:

char const* find_chunk(char const* const beg, char const* const end)
{
    static char const match[] = {'\x48', '\x8D'};

    auto found = std::search(beg, end, std::begin(match), std::end(match));

    if(std::distance(found, end) > 6 && found[6] == '\xE8')
        return found;

    return end;
}

正如 cmets 中提到的,另一种方法是像这样使用std::optional&lt;char&gt;

char const* find_chunk(char const* const beg, char const* const end)
{
    static std::optional<char> const m[] = {{'\x48'}, {'\x8D'}, {}, {}, {}, {}, {'\xE8'}};

    return std::search(beg, end, std::begin(m), std::end(m), [](auto a, auto b){
        if(!b.has_value())
            return true;
        return a == b.value();
    });
}

【讨论】:

  • 非常感谢先生,我实际上是在寻找比赛中的记忆位置。我想我会使用你的正则表达式选项。
猜你喜欢
  • 2013-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-05
  • 2020-12-22
  • 1970-01-01
  • 2019-10-23
  • 1970-01-01
  • 2018-10-04
相关资源
最近更新 更多