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 中的值:


    许可协议: 文章中的代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!
  • 相关阅读:
    Spring 注解@Component,@Service,@Controller,@Repository
    HttpServlet service方法
    Intellij Idea生成serialVersionUID的方法
    创建数据库池实战
    代理模式
    基于SOA架构的TDD测试驱动开发模式
    服务治理要先于SOA
    简述我的SOA服务治理
    SOA服务类项目开发模式
    oracle容器化docker解决方案
  • 原文地址:https://www.cnblogs.com/LyShark/p/15019609.html
Copyright © 2011-2022 走看看