zoukankan      html  css  js  c++  java
  • C/C++ 读取文件16进制格式

    读取代码

    #include <iostream>
    #include <Windows.h>
    #include <iomanip>
    #include <fstream>
    #include<cstdlib>
    #include<string>
    
    using namespace std;
    
    char HEX[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
    void setIndex(int num, char* hexNumber)
    {
    	// 清空行下标
    	for (int i = 0; i < 8; i++){
    		hexNumber[i] = '0';
    	}
    
    	// 设置新的行下标
    	int index = 7;
    	while (num != 0 && index >= 0)
    	{
    		hexNumber[index--] = HEX[num % 16];
    		num = num / 16;
    	}
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	// 打开文件
    	string path_r = "C:\Windows\SysNative\ntoskrnl.exe";
    	ifstream in = ifstream(path_r, ios::binary);
    	if (!in.is_open()){cout << "Error: File Path is Wrong" << endl;}
    
    	// 获取文件大小、文件名
    	long long Beg = in.tellg();
    	in.seekg(0, ios::end);
    	long long End = in.tellg();
    	long long fileSize = End - Beg;
    	in.seekg(0, ios::beg);
    	cout << "File Size: " << fileSize / 1024.0 << "KB" << endl;
    
    	// 读文件(每次循环读取 1 字节)
    	int byteBeenRead = 0;
    	char hexNumber[9] = "00000000";
    	unsigned char temp;
    	while (in.read((char*)&temp, 1))
    	{
    		// 每读 16 个字节换行
    		if (byteBeenRead % 16 == 0)
    		{
    			// 设置行下标
    			cout << endl;
    			setIndex(byteBeenRead, hexNumber);
    			cout << hexNumber << ":	";
    		}
    		byteBeenRead++;
    		
    		// 读 1 字节
    		int hex = (unsigned)temp;
    		char a = HEX[hex / 16];
    		char b = HEX[hex % 16];
    		cout << a << b << " ";
    	}
    	// 关闭文件流
    	in.close();
    	cout << "Read Successfully" << endl;
    
    	getchar();
    	return 0;
    }
    

    进阶篇 - 找 PE 文件内16进制特征码,计算对应的内存地址

    比如我想要找到内存里 KiProcessExpiredTimerList+0x102 的位置:

    征码:

    int codeArr_kipetl_102[] = {
    		0xff,0x53,0x08,
    		0x41,0x3b,0xb4,0x24,0xc4,0x01,0x00,0x00,
    		0x0f,0x85,0x48,0xff,0x09,0x00,
    		0x40,0x84,0xff
    	};
    int codeCtrl_kipetl_102[] = {
    		1,1,1,
    		1,1,1,1,1,1,1,1,
    		1,1,1,1,1,1,
    		1,1,1
    };
    

    在刚才的函数上稍作修改,找到这一串特征码在文件内出现的位置:

    int get_PE_feature_rof(
    	string path_r,			// PE 文件全路径。我这里是:"C:\Windows\SysNative\ntoskrnl.exe"
    	int codeArr[],			// 上面提到的第一个数组
    	int codeCtrl[],			// 上面提到的第二个数组
    	int len					// 数组的长度
    ){
    	// 打开文件
    	ifstream in = ifstream(path_r, ios::binary);
    	if (!in.is_open()){
    		cout << "文件打开失败:" << GetLastError() << endl;
    		in.close();
    		return 0;
    	}
    
    	// 获取文件大小、文件名
    	long long Beg = in.tellg();
    	in.seekg(0, ios::end);
    	long long End = in.tellg();
    	long long fileSize = End - Beg;
    	in.seekg(0, ios::beg);
    
    	// 读文件(每次循环读取 1 字节)
    	int byteBeenRead = 0;				// 已经读取的字节数
    	unsigned char temp;					// 存放读取内容的缓冲区				
    	int rof_feature = 0;				// 特征 ROF
    	int codeArrSub = 0;					// 要对比的 codeArr[] 下标
    	BOOL isFound = FALSE;				// 是否找到特征
    	while (in.read((char*)&temp, 1) && isFound == FALSE){
    		byteBeenRead++;
    		// 读 1 字节
    		int hex = (unsigned)temp;
    		
    		// 比较特征
    		for(int i=0;i<len;i++){
    			// 需要匹配
    			if(codeCtrl[codeArrSub] == 1){
    				// 匹配到特征
    				if(hex == codeArr[codeArrSub]){
    					codeArrSub++;
    					// 匹配完成
    					if(codeArrSub == len){
    						rof_feature = byteBeenRead - len;
    						isFound = TRUE;
    						break;
    					}else{break;}
    				}else{codeArrSub=0;break;}
    			}else{codeArrSub++;break;}
    		}
    	}
    	//cout << "rof_feature = " << hex << rof_feature << endl;
    	in.close();
    	return rof_feature;
    }
    

    函数返回后成功拿到这个位置的 ROF:

    然后看一下这个 ROF(0x30F42) 属于 PE 文件的哪一个区段。因为 .text 的 ROffset 小于 0x30F42 ,且 ROffset + RSize 大于 0x30F42 ,所以可知这段代码处于 .text 区段:

    所以最终的偏移 = 我们代码的 ROF - .text区段的ROF + .text区段的VAddr = 0x30F42 - 0x600 + 0x1000 = 0x31942

    用 PCHunter 看下 ntoskrnl.exe 的内核基地址(这里不讲怎么获取了)

    试下 FFFFF8000421C000 + 0x31942 = FFFFF8000424D942

    计算出的值刚好等于 WinDbg 中的值:


    许可协议: 文章中的代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!
  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/LyShark/p/15019609.html
Copyright © 2011-2022 走看看