• 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;
    }
    

    过程:

    #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;
    }
    

    寻找开始

    #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;
    }
    

    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();     // 子字符串大小
    
    	// 循环遍历字符串,因为末尾 '\0' 的存在,所以不会越界
    	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;
    }
    

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

    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;
    }
    
  • 相关阅读:
    Linux 环境下搭建单机版 Redis
    为什么要同时重写equals和hashcode方法
    使用ThreadPoolExecutor 创建线程池,完成并行操作
    一个简单的通过newFixedThreadPool实现多线程案例
    Java 获取对象的所有属性及其对应的值
    分布式id生成方案总结
    使用idea和gradle编译spring5源码
    Pandas中常用的函数使用
    单链表的反转 python实现实例
    kaggle注册中的坑---2018,12.3试过有效
  • 原文地址:https://www.cnblogs.com/LyShark/p/13067306.html
Copyright © 2020-2023  润新知