吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 669|回复: 13
收起左侧

[C&C++ 原创] hex_search 多文件搜索文本和二进制,开源命令行工具

  [复制链接]
yes2 发表于 2024-12-21 13:57
本帖最后由 yes2 于 2024-12-21 20:05 编辑

https://gitee.com/yes2/hex_search
可能我需求比较怪,一直没找到趁手的工具,所以自己写了一个。这个是在windows下使用的,因为linux下有grep功能更强大速度更快。
用法:
hex_search target_folder "text" [codepage_number]
hex_search target_folder "binary_data" -b
功能一:搜索文本,不区分大小写,命令行末尾可以手动加上代码页参数。
比如 hex_search "c:\some_app" "验证失败" 65001 或者 hex_search "c:\some_app" "验证失败" 1200
如果是 hex_search "c:\some_app" "验证失败" 不带代码页参数的话就使用系统默认代码页
功能二:搜索二进制数据,末尾加-b参数表示搜索二进制而不是文本。
比如 hex_search "c:\some_app" "4b 6d" -b 二进制数据中间可以有空格也可以不加空格。


特性:
尽量追求性能。
1.使用多线程任务队列方式,排队取任务进行搜索;
2.使用内存映射技术,避免频繁read;
3.使用kmp搜索技术,kmp是抄的开源代码,做了一点小修改支持忽略大小写;


todo:
1.大文件可以考虑分块给任务队列领取任务,避免其他线程都干完活了只剩下一个线程在搜索最后一个大文件;
2.文本搜索的时候也许可以提供一个区分大小写的选项,理论上应该能提高一点性能;
3.单次访问的页面范围可以考虑更大,减少内存映射和kmp搜索的次数;
4.搜索结果目前只输出匹配结果的文件名和第一个匹配到的偏移,后面可能会考虑输出更多信息,以及单个文件内多个匹配到的结果


欢迎review代码和fork,欢迎批评和建议,互相探讨,共同进步。
附上大文件操作的类代码:
LargeFile.h
[C++] 纯文本查看 复制代码
#pragma once

#define ALIGN_DOWN_BY(length, alignment) \
    ((ULONG_PTR)(length) & ~(alignment - 1))

#define ALIGN_UP_BY(length, alignment) \
    (ALIGN_DOWN_BY(((ULONG_PTR)(length) + alignment - 1), alignment))

#define ALIGN_DOWN_POINTER_BY(address, alignment) \
    ((PVOID)((ULONG_PTR)(address) & ~((ULONG_PTR)alignment - 1)))

#define ALIGN_UP_POINTER_BY(address, alignment) \
    (ALIGN_DOWN_POINTER_BY(((ULONG_PTR)(address) + alignment - 1), alignment))

#define ALIGN_DOWN(length, type) \
    ALIGN_DOWN_BY(length, sizeof(type))

#define ALIGN_UP(length, type) \
    ALIGN_UP_BY(length, sizeof(type))

#define ALIGN_DOWN_POINTER(address, type) \
    ALIGN_DOWN_POINTER_BY(address, sizeof(type))

#define ALIGN_UP_POINTER(address, type) \
    ALIGN_UP_POINTER_BY(address, sizeof(type))

class CLargeFile
{
public:
	CLargeFile();
	~CLargeFile();

	/************************************************************************/
	/* open file, return TRUE if success; if FALSE, use GetLastError to get error code
	/* error may occur at CreateFile or CreateFileMapping
	/************************************************************************/
	BOOL OpenFile(LPCTSTR pFilePathName, UINT nPageCount = 3);

	/************************************************************************/
	/* check if i have opened a file.
	/************************************************************************/
	BOOL IsOpenFile();

	/************************************************************************/
	/* get file path name.
	/************************************************************************/
	LPCTSTR GetFilePathName();

	/************************************************************************/
	/* just close file, NOTHING saved.
	/* if you want to save, call SaveFile() before CloseFile().
	/************************************************************************/
	void CloseFile();

	/************************************************************************/
	/* get file size.
	/************************************************************************/
	DWORD GetFileSizeLow();
	DWORD GetFileSizeHigh();
	void GetFileSizeEx(LARGE_INTEGER* puFileSize);

	/************************************************************************/
	/* visit file position. return a pointer point to the data at the position.
	/* dwAvalibleSize received the avalible size of the data that you can use, 
	/* if out of the size, you should call VisitFilePosition() 
	/* with the new position to get a new pointer and new avalible size.
	/************************************************************************/
	void* VisitFilePosition(DWORD nVisitLow, DWORD nVisitHigh = 0, DWORD* pdwAvalibleSize = 0);
	void* VisitFilePosition(LARGE_INTEGER nVisit, DWORD* pdwAvalibleSize = 0);

protected:
	virtual void OnUnmapViewOfFile();
	virtual BYTE* OnMapViewOfFile(LARGE_INTEGER nViewStart, DWORD dwMapSize);
	LARGE_INTEGER m_nViewStart;
	DWORD m_dwMapSize;
	DWORD m_dwPageSize;
	DWORD m_dwPageCount;
	BYTE* m_pView;
private:
	void init();
	TCHAR m_szFilePathName[MAX_PATH];
	HANDLE m_hFile;
	HANDLE m_hMap;

	LARGE_INTEGER m_nFileSize;
};



LargeFile.cpp
[C++] 纯文本查看 复制代码
#include "stdafx.h"
#include <windows.h>
#include "LargeFile.h"


CLargeFile::CLargeFile()
{
	SYSTEM_INFO si;
	GetSystemInfo(&si);
	m_dwPageSize = si.dwAllocationGranularity;
	m_dwPageCount = 3;
	init();
}


CLargeFile::~CLargeFile()
{
    CloseFile();
}

BOOL CLargeFile::OpenFile(LPCTSTR pFilePathName, UINT nPageCount /*= 3*/)
{
	CloseFile();

	m_hFile = CreateFile(pFilePathName,
		GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL, 0);
	if (m_hFile == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}
	::GetFileSizeEx(m_hFile, &m_nFileSize);
	
	if (!m_nFileSize.QuadPart)
	{
		CloseHandle(m_hFile);
		m_hFile = INVALID_HANDLE_VALUE;
		SetLastError(ERROR_EMPTY);
		return FALSE;
	}
	m_hMap = CreateFileMapping(m_hFile, 0, PAGE_WRITECOPY, 0, 0, 0);
	if (!m_hMap)
	{
		CloseHandle(m_hFile);
		m_hFile = INVALID_HANDLE_VALUE;
		return FALSE;
	}
	lstrcpy(m_szFilePathName, pFilePathName);
	m_pView = 0;
	m_nViewStart.QuadPart = 0;
	m_dwPageCount = nPageCount;
	return TRUE;
}

BOOL CLargeFile::IsOpenFile()
{
	return (m_hFile != INVALID_HANDLE_VALUE) && (m_hMap != NULL);
}

LPCTSTR CLargeFile::GetFilePathName()
{
	return m_szFilePathName;
}

void CLargeFile::CloseFile()
{
	if (m_pView)
	{
        OnUnmapViewOfFile();
	}
	if (m_hMap)
	{
		CloseHandle(m_hMap);
	}
	if (m_hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(m_hFile);
	}
	init();
}

DWORD CLargeFile::GetFileSizeLow()
{
	return m_nFileSize.LowPart;
}

DWORD CLargeFile::GetFileSizeHigh()
{
	return m_nFileSize.HighPart;
}

void CLargeFile::GetFileSizeEx(LARGE_INTEGER* puFileSize)
{
	if (puFileSize)
		puFileSize->QuadPart = m_nFileSize.QuadPart;
}

void* CLargeFile::VisitFilePosition(LARGE_INTEGER nVisit, DWORD* pdwAvalibleSize /*= 0*/)
{
	if (m_hFile == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	if (nVisit.QuadPart >= m_nFileSize.QuadPart)
	{
		return 0;
	}
	DWORD dwAvalibleSize = 0;
	DWORD dwVisitOffset = 0;

	if (m_pView)
	{
		if (nVisit.QuadPart >= m_nViewStart.QuadPart + m_dwPageSize &&
			nVisit.QuadPart <= m_nViewStart.QuadPart + m_dwPageSize * 2)
		{
            dwVisitOffset = (DWORD)(nVisit.QuadPart - m_nViewStart.QuadPart);
			dwAvalibleSize = m_dwPageSize * 3 - dwVisitOffset;
		}

		if (nVisit.QuadPart >= m_nViewStart.QuadPart && // m_nViewStart.QuadPart means 0
			nVisit.QuadPart < m_dwPageSize)
		{
            dwVisitOffset = (DWORD)nVisit.QuadPart;
			dwAvalibleSize = m_dwPageSize * 3 - dwVisitOffset;
		}

		if (dwAvalibleSize)
		{
			if (dwAvalibleSize > m_nFileSize.QuadPart - nVisit.QuadPart)
			{
                dwAvalibleSize = (DWORD)(m_nFileSize.QuadPart - nVisit.QuadPart);
			}
			if (pdwAvalibleSize)
			{
				*pdwAvalibleSize = dwAvalibleSize;
			}
			return m_pView + dwVisitOffset;
		}
	}

	if (m_pView)
	{
		OnUnmapViewOfFile();
	}

	if (nVisit.QuadPart < m_dwPageSize)
	{
		m_nViewStart.QuadPart = 0;
	}
	else
	{
		m_nViewStart.QuadPart = ALIGN_DOWN_BY(nVisit.QuadPart, m_dwPageSize) - m_dwPageSize;
	}

	m_dwMapSize = m_dwPageSize * m_dwPageCount;
	if (m_nViewStart.QuadPart + m_dwMapSize > m_nFileSize.QuadPart)
	{
        m_dwMapSize = (DWORD)(m_nFileSize.QuadPart - m_nViewStart.QuadPart);
	}

	m_pView = OnMapViewOfFile(m_nViewStart, m_dwMapSize);
	if (!m_pView)
	{
		return 0;
	}
    dwVisitOffset = (DWORD)(nVisit.QuadPart - m_nViewStart.QuadPart);
	dwAvalibleSize = m_dwMapSize - dwVisitOffset;
	if (pdwAvalibleSize)
	{
		*pdwAvalibleSize = dwAvalibleSize;
	}

	return m_pView + dwVisitOffset;
}

void* CLargeFile::VisitFilePosition(DWORD nVisitLow, DWORD nVisitHigh /*= 0*/, DWORD* pdwAvalibleSize /*= 0*/)
{
	LARGE_INTEGER nVisit;
	nVisit.LowPart = nVisitLow;
	nVisit.HighPart = nVisitHigh;
	return VisitFilePosition(nVisit, pdwAvalibleSize);
}

void CLargeFile::OnUnmapViewOfFile()
{
	UnmapViewOfFile(m_pView);
}

BYTE* CLargeFile::OnMapViewOfFile(LARGE_INTEGER nViewStart, DWORD dwMapSize)
{
	return (BYTE*)MapViewOfFile(m_hMap, FILE_MAP_COPY, nViewStart.HighPart,
		nViewStart.LowPart, dwMapSize);
}

void CLargeFile::init()
{
	m_hFile = INVALID_HANDLE_VALUE;
	m_hMap = 0;
	m_pView = 0;

	m_nFileSize.QuadPart = 0;
	m_nViewStart.QuadPart = 0;
	m_szFilePathName[0] = 0;
}

免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +2 收起 理由
zhczf + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

Elaineliu 发表于 2024-12-22 12:41
本帖最后由 Elaineliu 于 2024-12-22 13:00 编辑
yes2 发表于 2024-12-22 12:40
感谢指导,我研究一下。我在算法这块比较渣

https://www.52pojie.cn/thread-1962446-1-1.html
https://www.52pojie.cn/thread-1982500-1-1.html

这个也行


你也可以在百度搜  字符串模式匹配算法——BM、Horspool、Sunday、KMP、KR、AC算法一网打尽
三滑稽甲苯 发表于 2024-12-22 08:29
楼主也可以试试 ripgrep,它速度比 grep 还快,支持自动忽略隐藏文件夹、二进制文件以及 .gitignore 内指定的文件(当然也可以选择禁用这些自动规则)
苏紫方璇 发表于 2024-12-21 16:06
请在帖子内插入部分关键代码
本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能介绍【20220924强制执行】
少年持剑 发表于 2024-12-21 17:19
这个不错  16进制搜索支持通配符吗
 楼主| yes2 发表于 2024-12-21 20:07
少年持剑 发表于 2024-12-21 17:19
这个不错  16进制搜索支持通配符吗

暂时不支持。因为是自用的,目前没有需求就没去思考这个功能。
要支持可能需要对kmp改动更多,目前还没有把握。
欢迎提交MR
 楼主| yes2 发表于 2024-12-21 20:08
苏紫方璇 发表于 2024-12-21 16:06
请在帖子内插入部分关键代码
本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能 ...

功能介绍就有了,关键代码。。。感觉都挺关键的,其他代码不好拆,就贴个大文件映射的类代码吧
xiaoxion999 发表于 2024-12-21 22:43
感谢老板
董督秀 发表于 2024-12-22 06:37
yes2 发表于 2024-12-21 20:07
暂时不支持。因为是自用的,目前没有需求就没去思考这个功能。
要支持可能需要对kmp改动更多,目前还没 ...

有支持内存特征码匹配的吗?
Elaineliu 发表于 2024-12-22 12:17
sunday算法在实际场景中是远优于kmp
shift-and算法也能处理流数据单模匹配问题,并且实际中比kmp更加高效。
 楼主| yes2 发表于 2024-12-22 12:39
三滑稽甲苯 发表于 2024-12-22 08:29
楼主也可以试试 ripgrep,它速度比 grep 还快,支持自动忽略隐藏文件夹、二进制文件以及 .gitignore 内指定 ...

感谢推荐,有空试试
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-1-7 20:05

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表