C/C++ 内存遍历与KMP特征搜索

内存遍历,枚举数据,实现特征码扫描。

内存遍历: 每次读入4096字节,然后每16个字符换一次行,遍历内存 0x00401000 - 0x7FFFFFFF。

#include <stdio.h>  
#include <stdlib.h>  
#include <windows.h>  

VOID ScanAddress(HANDLE process)
{
    const DWORD beginAddr = 0x00401000;
    const DWORD endAddr = 0x7FFFFFFF;
    const DWORD pageSize = 4096;

    BOOL _break = FALSE;
    BYTE page[pageSize];
    DWORD tmpAddr = beginAddr;
    while (tmpAddr <= endAddr)
    {
        ::ReadProcessMemory(process, (LPCVOID)tmpAddr, &page, pageSize, 0);

        for (int x = 0; x < 4096; x++)
        {

            if (x % 16 != 0)
            {
                DWORD ch = page[x];

                if (ch >= 0 && ch <= 15)
                {
                    printf("0%x ", ch);
                }
                else
                {
                    printf("%x ", ch);
                }
            }
            else
                printf(" | %x n", tmpAddr);
        }
        tmpAddr += pageSize;
    }
}

int main(int argc, char* argv[])
{
    HANDLE process = ::OpenProcess(PROCESS_ALL_ACCESS, false, 4748);
    ScanAddress(process);
    ::CloseHandle(process);

    system("pause");
    return 0;
}

C/C++ 内存遍历与KMP特征搜索

过程:

#include <stdio.h>  
#include <stdlib.h>  
#include <windows.h>  

VOID ScanAddress(HANDLE Process)
{
    const DWORD beginAddr = 0x00401000;
    const DWORD endAddr = 0x7FFFFFFF;

    unsigned char shell[5] = {0x55,0x8b,0xec,0x6a,0xff};
    unsigned char *read = new unsigned char[5];


    for (int x = 0; x < beginAddr; x++)
    {
        DWORD addr = beginAddr + x;
        ReadProcessMemory(Process, (LPVOID)addr, read, 5, 0);
        printf("%x :", addr);
        for (int y = 0; y < 5; y++)
            printf("%02x ",read[y]);
        printf("n");
    }
}

int main(int argc, char* argv[])
{
    HANDLE process = ::OpenProcess(PROCESS_ALL_ACCESS, false, 1772);
    ScanAddress(process);
    /*
    unsigned char set[] = { 4,41,55 };
    unsigned char aa[] = { 4, 41, 55 };
    int ret = memcmp(set, aa, 3);
    printf("%d n", ret);
    */
    //ScanAddress(process);
    //::CloseHandle(process);
    system("pause");
    return 0;
}

C/C++ 内存遍历与KMP特征搜索

寻找开始

#include <stdio.h>  
#include <stdlib.h>  
#include <windows.h>  

VOID ScanAddress(HANDLE Process)
{
    const DWORD beginAddr = 0x00401000;
    const DWORD endAddr = 0x7FFFFFFF;

    unsigned char shell[6] = {0xff,0x75,0x10,0xff,0x75,0x0c};

    unsigned char *read = new unsigned char[6];

    for (int x = 0; x < 684032; x++)
    {
        DWORD addr = beginAddr + x;
        ReadProcessMemory(Process, (LPVOID)addr, read, 6, 0);
        int a = memcmp(read, shell, 6);

        if (a == 0)
        {
            printf("%x :", addr);

            for (int y = 0; y < 6; y++)
            {
                printf("%02x ", read[y]);
            }

            printf(" n");
        }
    }
}
int main(int argc, char* argv[])
{
    HANDLE process = ::OpenProcess(PROCESS_ALL_ACCESS, false, 1772);
    ScanAddress(process);
    system("pause");
    return 0;
}

C/C++ 内存遍历与KMP特征搜索

KMP算法搜索特征码: KMP算法每次在4096字节中寻找特征,成功返回位置,失败返回-1

#include <iostream>
#include <string>

using namespace std;

/* P 为模式串,下标从 0 开始 */
void GetNextval(string SubString, int nextval[])
{
    int SubStringLen = SubString.size();
    int i = 0;
    int j = -1;
    nextval[0] = -1;

    while (i < SubStringLen)
    {
        if (j == -1 || SubString[i] == SubString[j])
        {
            i++; j++;
            if (SubString[i] != SubString[j])
                nextval[i] = j;
            else
                nextval[i] = nextval[j];
        }
        else
        {
            j = nextval[j];
        }
    }
}

/* 在 MainString 中找到 SubString 第一次出现的位置 下标从0开始*/
int KMPSearchString(string MainString, string SubString, int next[])
{
    GetNextval(SubString, next);

    int MainStringIndex = 0;                 // 存储主字符串下标
    int SubStringIndex = 0;                  // 存储子字符串下标
    int MainStringLen = MainString.size();   // 主字符串大小
    int SubStringLen = SubString.size();     // 子字符串大小

    // 循环遍历字符串,因为末尾 '' 的存在,所以不会越界
    while (MainStringIndex < MainStringLen && SubStringIndex < SubStringLen)
    {
        // MainString 的第一个字符不匹配或 MainString[] == SubString[]
        if (SubStringIndex == -1 || MainString[MainStringIndex] == SubString[SubStringIndex])
        {
            MainStringIndex++; SubStringIndex++;
        }
        else   // 当字符串匹配失败则跳转
        {
            SubStringIndex = next[SubStringIndex];
        }
    }
    // 最后匹配成功直接返回位置
    if (SubStringIndex == SubStringLen)
        return MainStringIndex - SubStringIndex;
    return -1;
}

int main(int argc, char *argv[])
{
    int next[100] = { 0 };

    char *Str = "e5 8d 64 24 fc ba ff ff ff ff 92 f0 0f c1";
    char *Search = "ba ff ff ff ff 92 f0";

    // 在Str字符串中找Search子串,找到后返回位置
    int ret = KMPSearchString(Str, Search,next);

    printf("%d n", ret);


    system("pause");
    return 0;
}

C/C++ 内存遍历与KMP特征搜索

将上方代码整合,可实现根据特征码动态打补丁:

int main(int argc, char* argv[])
{
    HANDLE Process = OpenProcess(PROCESS_ALL_ACCESS, false, 2876);

    // 搜索指定特征码的地址数据.
    unsigned char FindCode[6] = { 0xff, 0x75, 0x10, 0xff, 0x75, 0x0c };
    DWORD ret = ScanAddress(Process, FindCode, 6);
    printf("特征地址: %x n", ret);

    // 给指定位置动态打补丁
    unsigned char Pack[6] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 };
    WriteProcessMemory(Process, (LPVOID)ret, Pack, 6, 0);

    system("pause");
    return 0;
}

原文链接: https://www.cnblogs.com/LyShark/p/13067306.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C/C++ 内存遍历与KMP特征搜索

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/353695

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午8:12
下一篇 2023年3月2日 上午8:12

相关推荐