首页
论坛
专栏
课程

[其他内容] [原创]一个速度不是很快但是逻辑很简单的内存特征码搜索

2019-5-27 15:47 2031

[其他内容] [原创]一个速度不是很快但是逻辑很简单的内存特征码搜索

2019-5-27 15:47
2031
逻辑非常简单
// ConsoleApplication8.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
// 很多头文件不需要,你自己看着用吧 我是复制我之前的
#include "pch.h"
#include <Windows.h>
#include <windowsx.h>
#include <process.h>
#include <direct.h>
#include <tchar.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <ctime>
#include <thread>

/// 字符转字节
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[i] == ' ')
		{
			continue;
		}
		if (str[i] == '?')
		{
			Bytes.insert(Bytes.end(), '?');
		}
		else if (str[i] == '*') {
			Bytes.insert(Bytes.end(), '*');
		}
		else {
			Bytes.insert(Bytes.end(), 0x10 * ctoh(str[i]) + ctoh(str[i + 1]));
			i++;
		}
	}
	return Bytes;
}
// 获取进程模块句柄
HMODULE GetProcessModuleHandle(DWORD ProcessId, CONST TCHAR* ModuleName)
{
	HMODULE hMods[1024];
	DWORD cbNeeded;
	TCHAR szModName[MAX_PATH];

	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[i], szModName, sizeof(szModName) / sizeof(TCHAR));
			if (_tcscmp(szModName, ModuleName)) {
				return hMods[i];
			}
		}
	}
	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[Size];
	// HANDLE ProcessHandle = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
	ReadProcessMemory(ProcessHandle, (LPCVOID)Address, Buffer, Size, NULL);
	for (size_t i = 0; i < Size; i++)
	{
		Bytes[i] = Buffer[i];
	}
	delete[]Buffer;
	// CloseHandle(ProcessHandle);
	return Bytes;
}
// 用来保存模块内存数据
static std::map<CONST TCHAR*, std::map<DWORD_PTR, std::vector<BYTE>>> g_ModuleMemorys;

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[ModuleName].insert(std::pair<DWORD_PTR, std::vector<BYTE>>(BeginAddress, ReadBytes(ProcessHandle, BeginAddress, mbi.RegionSize)));
			}

			BeginAddress += mbi.RegionSize;
		}
                CloseHandle(ProcessHandle);
	}

	Memorys = g_ModuleMemorys[ModuleName];

	it = Memorys.begin();

	SIZE_T i = 0;
	SIZE_T j = 0;
	// 这个就是匹配的逻辑了
	while (it != Memorys.end())
	{
		i = it->second.size();
		while (i--) {
			j = FeatureCode.size();
			while (j--) {
				if (j == 0)
				{
					Address = it->first + i;
					goto _exit;
				}
				else if (FeatureCode[j] != it->second[i + j] && FeatureCode[j] != '?' && FeatureCode[j] != '*') {
					break;
				}
			}
			
		}

		it++;
	}
_exit:
	return Address;
}

int main(int argc, char const *argv[])
{
	clock_t startTime, endTime;
	startTime = clock();//计时开始

	// 特征码字符串格式随意  这里是拿网易的有道词典测试的
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8030000F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 * * * F4 ??? A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 ? ? ? ? 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 03 00 00 F4 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));
	printf("Address %X\n", (DWORD32)FindFeatureCode(13332, L"YoudaoDict.exe", "E8 * * * * 01 00 00 A8 61 00 00 7F 00 00 00 0A 00 00 00 50 C3 00 00 E7 03 00 00 E8 03 00 00 50"));

	endTime = clock();//计时结束
	printf("运行时间: %f/s\n", (double)(endTime - startTime) / CLOCKS_PER_SEC);
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		//翻译消息
		TranslateMessage(&msg);
		//分发消息
		DispatchMessage(&msg);
	}
	return 0;
}



[公告]安全服务和外包项目请将项目需求发到看雪企服平台:https://qifu.kanxue.com

最后于 2019-5-28 09:22 被aas102400编辑 ,原因:
最新回复 (15)
Rookietp 2019-5-27 20:00
2
0
代码看的很舒服,先收藏一波.用得上的时候再来.
最后于 2019-5-27 20:00 被Rookietp编辑 ,原因:
黑洛 1 2019-5-27 20:38
3
0
我感觉你的代码很怪,stl库和原指针混用,说不出变扭的感觉。和逻辑、效率关系不大,单纯觉得这样写代码会对自己和别人造成一定的困扰。
pureGavin 2019-5-27 20:42
4
0
mark,楼主辛苦了
aas102400 2019-5-28 09:17
5
0
黑洛 我感觉你的代码很怪,stl库和原指针混用,说不出变扭的感觉。和逻辑、效率关系不大,单纯觉得这样写代码会对自己和别人造成一定的困扰。
我自己都是瞎学的  不懂啥子规范 
aas102400 2019-5-28 09:35
6
0
aas102400 我自己都是瞎学的 不懂啥子规范 [em_12]
我自己百度找 那种要么是不能用 要么就是又臭又长
网络游侠 2019-5-28 10:06
7
0
黑洛 我感觉你的代码很怪,stl库和原指针混用,说不出变扭的感觉。和逻辑、效率关系不大,单纯觉得这样写代码会对自己和别人造成一定的困扰。
这代码不算别扭吧,可读性还行。
aas102400 2019-5-28 10:37
8
0
网络游侠 这代码不算别扭吧,可读性还行。
取内存那个可以单独写一个函数 我懒的弄了就整一块去了
叁毛 1 2019-5-28 16:14
9
0
AC自动机,多模匹配,只需要匹配一次
黑洛 1 2019-5-28 17:07
10
0
aas102400 我自己都是瞎学的 不懂啥子规范 [em_12]
可读性没啥问题 ,就是混用不太好
aas102400 2019-6-3 17:10
12
0
黑洛 可读性没啥问题 ,就是混用不太好
为啥这样不好啊
黑洛 1 2019-6-3 17:50
13
0
aas102400 为啥这样不好啊
不是一个语言的写法混用感觉很奇怪,然后虽然你用c语言的写法写,但是最后还是会被编译为C++
aas102400 2019-6-4 17:16
14
0

语法啥的,开心就好呀
MrNv 2019-6-8 20:05
15
0
大佬这个支持64位吗
aas102400 2019-6-10 11:45
16
0
MrNv 大佬这个支持64位吗
支持
游客
登录 | 注册 方可回帖
返回