详解驱动开发中内核PE结构VA与FOA转换 环球微动态
摘要:本文将探索内核中解析PE文件的相关内容。
本文分享自华为云社区《驱动开发:内核PE结构VA与FOA转换》,作者: LyShark 。
本章将探索内核中解析PE文件的相关内容,PE文件中FOA与VA、RVA之间的转换也是很重要的,所谓的FOA是文件中的地址,VA则是内存装入后的虚拟地址,RVA是内存基址与当前地址的相对偏移,本章还是需要用到封装的KernelMapFile()映射函数,在映射后对其PE格式进行相应的解析,并实现转换函数。
(资料图)
首先先来演示一下内存VA地址与FOA地址互相转换的方式,通过使用WinHEX打开一个二进制文件,打开后我们只需要关注如下蓝色注释为映像建议装入基址,黄色注释为映像装入后的RVA偏移。
通过上方的截图结合PE文件结构图我们可得知0000158B为映像装入内存后的RVA偏移,紧随其后的00400000则是映像的建议装入基址,为什么是建议而不是绝对?别急后面慢来来解释。
通过上方的已知条件我们就可以计算出程序实际装入内存后的入口地址了,公式如下:
VA(实际装入地址) = ImageBase(基址) + RVA(偏移) => 00400000 + 0000158B = 0040158B
找到了程序的OEP以后,接着我们来判断一下这个0040158B属于那个节区,以.text节区为例,下图我们通过观察区段可知,第一处橙色位置00000B44 (节区尺寸),第二处紫色位置00001000 (节区RVA),第三处00000C00 (文件对齐尺寸),第四处00000400 (文件中的偏移),第五处60000020 (节区属性)。
得到了上方text节的相关数据,我们就可以判断程序的OEP到底落在了那个节区中,这里以.text节为例子,计算公式如下:
虚拟地址开始位置:节区基地址 + 节区RVA => 00400000 + 00001000 = 00401000虚拟地址结束位置:text节地址 + 节区尺寸 => 00401000 + 00000B44 = 00401B44
经过计算得知 .text 节所在区间(401000 - 401B44) 你的装入VA地址0040158B只要在区间里面就证明在本节区中,此处的VA地址是在401000 - 401B44区间内的,则说明它属于.text节。
经过上面的公式计算我们知道了程序的OEP位置是落在了.text节,此时你兴致勃勃的打开x64DBG想去验证一下公式是否计算正确不料,这地址根本不是400000开头啊,这是什么鬼?
上图中出现的这种情况就是关于随机基址的问题,在新版的VS编译器上存在一个选项是否要启用随机基址(默认启用),至于这个随机基址的作用,猜测可能是为了防止缓冲区溢出之类的烂七八糟的东西。
为了方便我们调试,我们需要手动干掉它,其对应到PE文件中的结构为 IMAGE_NT_HEADERS -> IMAGE_OPTIONAL_HEADER -> DllCharacteristics 相对于PE头的偏移为90字节,只需要修改这个标志即可,修改方式 x64:6081 改 2081 相对于 x86:4081 改 0081 以X86程序为例,修改后如下图所示。
经过上面对标志位的修改,程序再次载入就能够停在0040158B的位置,也就是程序的OEP,接下来我们将通过公式计算出该OEP对应到文件中的位置。
.text(节首地址) = ImageBase + 节区RVA => 00400000 + 00001000 = 00401000VA(虚拟地址) = ImageBase + RVA(偏移) => 00400000 + 0000158B = 0040158BRVA(相对偏移) = VA - (.text节首地址) => 0040158B - 00401000 = 58BFOA(文件偏移) = RVA + .text节对应到文件中的偏移 => 58B + 400 = 98B
经过公式的计算,我们找到了虚拟地址0040158B对应到文件中的位置是98B,通过WinHEX定位过去,即可看到OEP处的机器码指令了。
接着我们来计算一下.text节区的结束地址,通过文件的偏移加上文件对齐尺寸即可得到.text节的结束地址400+C00= 1000,那么我们主要就在文件偏移为(98B - 1000)在该区间中找空白的地方,此处我找到了在文件偏移为1000之前的位置有一段空白区域,如下图:
接着我么通过公式计算一下文件偏移为0xF43的位置,其对应到VA虚拟地址是多少,公式如下:
.text(节首地址) = ImageBase + 节区RVA => 00400000 + 00001000 = 00401000VPK(实际大小) = (text节首地址 - ImageBase) - 实际偏移 => 401000-400000-400 = C00VA(虚拟地址) = FOA(.text节) + ImageBase + VPK => F43+400000+C00 = 401B43
计算后直接X64DBG跳转过去,我们从00401B44的位置向下全部填充为90(nop),然后直接保存文件。
再次使用WinHEX查看文件偏移为0xF43的位置,会发现已经全部替换成了90指令,说明计算正确。
到此文件偏移与虚拟偏移的转换就结束了,那么这些功能该如何实现呢,接下来将以此实现这些转换细节。
FOA转换为VA:首先来实现将FOA地址转换为VA地址,这段代码实现起来很简单,如下所示,此处将dwFOA地址0x84EC00转换为对应内存的虚拟地址。
// 署名权// right to sign one"s name on a piece of work// PowerBy: LyShark// Email: me@lyshark.comNTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint("hello lyshark.com \n");NTSTATUS status = STATUS_SUCCESS;HANDLE hFile = NULL;HANDLE hSection = NULL;PVOID pBaseAddress = NULL;UNICODE_STRING FileName = { 0 };// 初始化字符串RtlInitUnicodeString(&FileName, L"\\??\\C:\\Windows\\System32\\ntoskrnl.exe");// 内存映射文件status = KernelMapFile(FileName, &hFile, &hSection, &pBaseAddress);if (!NT_SUCCESS(status)){return 0;}// 获取PE头数据集PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders);PIMAGE_FILE_HEADER pFileHeader = &pNtHeaders->FileHeader;DWORD64 dwFOA = 0x84EC00;DWORD64 ImageBase = pNtHeaders->OptionalHeader.ImageBase;DWORD NumberOfSectinsCount = pNtHeaders->FileHeader.NumberOfSections;DbgPrint("镜像基址 = %p | 节表数量 = %d \n", ImageBase, NumberOfSectinsCount);for (int each = 0; each < NumberOfSectinsCount; each++){DWORD64 PointerRawStart = pSection[each].PointerToRawData; // 文件偏移开始位置DWORD64 PointerRawEnds = pSection[each].PointerToRawData + pSection[each].SizeOfRawData; // 文件偏移结束位置// DbgPrint("文件开始偏移 = %p | 文件结束偏移 = %p \n", PointerRawStart, PointerRawEnds);if (dwFOA >= PointerRawStart && dwFOA <= PointerRawEnds){DWORD64 RVA = pSection[each].VirtualAddress + (dwFOA - pSection[each].PointerToRawData); // 计算出RVADWORD64 VA = RVA + pNtHeaders->OptionalHeader.ImageBase; // 计算出VADbgPrint("FOA偏移 [ %p ] --> 对应VA地址 [ %p ] \n", dwFOA, VA);}}ZwUnmapViewOfSection(NtCurrentProcess(), pBaseAddress);ZwClose(hSection);ZwClose(hFile);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}
运行效果如下所示,此处之所以出现两个结果是因为没有及时返回,一般我们取第一个结果就是最准确的;
VA转换为FOA:将VA内存地址转换为FOA文件偏移,代码与如上基本保持一致。
// 署名权// right to sign one"s name on a piece of work// PowerBy: LyShark// Email: me@lyshark.comNTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint("hello lyshark.com \n");NTSTATUS status = STATUS_SUCCESS;HANDLE hFile = NULL;HANDLE hSection = NULL;PVOID pBaseAddress = NULL;UNICODE_STRING FileName = { 0 };// 初始化字符串RtlInitUnicodeString(&FileName, L"\\??\\C:\\Windows\\System32\\ntoskrnl.exe");// 内存映射文件status = KernelMapFile(FileName, &hFile, &hSection, &pBaseAddress);if (!NT_SUCCESS(status)){return 0;}// 获取PE头数据集PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders);PIMAGE_FILE_HEADER pFileHeader = &pNtHeaders->FileHeader;DWORD64 dwVA = 0x00007FF6D3389200;DWORD64 ImageBase = pNtHeaders->OptionalHeader.ImageBase;DWORD NumberOfSectinsCount = pNtHeaders->FileHeader.NumberOfSections;DbgPrint("镜像基址 = %p | 节表数量 = %d \n", ImageBase, NumberOfSectinsCount);for (DWORD each = 0; each < NumberOfSectinsCount; each++){DWORD Section_Start = ImageBase + pSection[each].VirtualAddress; // 获取节的开始地址DWORD Section_Ends = ImageBase + pSection[each].VirtualAddress + pSection[each].Misc.VirtualSize; // 获取节的结束地址DbgPrint("Section开始地址 = %p | Section结束地址 = %p \n", Section_Start, Section_Ends);if (dwVA >= Section_Start && dwVA <= Section_Ends){DWORD RVA = dwVA - pNtHeaders->OptionalHeader.ImageBase; // 计算RVADWORD FOA = pSection[each].PointerToRawData + (RVA - pSection[each].VirtualAddress); // 计算FOADbgPrint("VA偏移 [ %p ] --> 对应FOA地址 [ %p ] \n", dwVA, FOA);}}ZwUnmapViewOfSection(NtCurrentProcess(), pBaseAddress);ZwClose(hSection);ZwClose(hFile);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}
运行效果如下所示,此处没有出现想要的结果是因为我们当前的VA内存地址并非实际装载地址,仅仅是PE磁盘中的地址,此处如果换成内存中的PE则可以提取出正确的结果;
RVA转换为FOA:将相对偏移地址转换为FOA文件偏移地址,此处仅仅只是多了一步pNtHeaders->OptionalHeader.ImageBase + dwRVARVA转换为VA的过程其转换结果与VA转FOA一致。
// 署名权// right to sign one"s name on a piece of work// PowerBy: LyShark// Email: me@lyshark.comNTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint("hello lyshark.com \n");NTSTATUS status = STATUS_SUCCESS;HANDLE hFile = NULL;HANDLE hSection = NULL;PVOID pBaseAddress = NULL;UNICODE_STRING FileName = { 0 };// 初始化字符串RtlInitUnicodeString(&FileName, L"\\??\\C:\\Windows\\System32\\ntoskrnl.exe");// 内存映射文件status = KernelMapFile(FileName, &hFile, &hSection, &pBaseAddress);if (!NT_SUCCESS(status)){return 0;}// 获取PE头数据集PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHeaders);PIMAGE_FILE_HEADER pFileHeader = &pNtHeaders->FileHeader;DWORD64 dwRVA = 0x89200;DWORD64 ImageBase = pNtHeaders->OptionalHeader.ImageBase;DWORD NumberOfSectinsCount = pNtHeaders->FileHeader.NumberOfSections;DbgPrint("镜像基址 = %p | 节表数量 = %d \n", ImageBase, NumberOfSectinsCount);for (DWORD each = 0; each < NumberOfSectinsCount; each++){DWORD Section_Start = pSection[each].VirtualAddress; // 计算RVA开始位置DWORD Section_Ends = pSection[each].VirtualAddress + pSection[each].Misc.VirtualSize; // 计算RVA结束位置if (dwRVA >= Section_Start && dwRVA <= Section_Ends){DWORD VA = pNtHeaders->OptionalHeader.ImageBase + dwRVA; // 得到VA地址DWORD FOA = pSection[each].PointerToRawData + (dwRVA - pSection[each].VirtualAddress); // 得到FOADbgPrint("RVA偏移 [ %p ] --> 对应FOA地址 [ %p ] \n", dwRVA, FOA);}}ZwUnmapViewOfSection(NtCurrentProcess(), pBaseAddress);ZwClose(hSection);ZwClose(hFile);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}
运行效果如下所示;
点击关注,第一时间了解华为云新鲜技术~
图片
-
详解驱动开发中内核PE结构VA
属羊女的命运不好是真的吗
流通协会:4月二手车交易146
-
全球观点:【物流618】申通6
重庆油菜喜获丰收 总产量实
焦点热门:ads是什么意思怎么
中方要美拿出诚意,减少周边
交银施罗德基金管理有限公司
世界动态:电动焦虑下的日系
-
热点评!智能表面产品和新型
安溪:让农家书屋成为乡村的
每日动态!2023高考数学开考
环球关注:世茂能源06月07日
天天新资讯:加拿大野火烟雾
每日观点:苹果手机通话记录
-
涟源市市场监督管理局:247
每日讯息!广聚能源:公司主
【新要闻】丰原药业:公司没
2个8相乘的积是多少_2个7的
23安徽债61今日发布发行公告
深圳多部门开通高考服务热线
精彩推送
- BIAME汽车制博会上惊现“吸睛王”,跨越为汽车产业高质量发展“划重点”
- 详解驱动开发中内核PE结构VA与FOA转换 环球微动态
- 天天看热讯:白酒概念板块涨0.19% 顺鑫农业涨3.34%居首
- 全球热头条丨本月底前,北京疾控中心新址完成基坑垫层施工
- 当前关注:收评:沪指午后拉升收涨0.49% 建筑装饰板块领涨
- 易实精密北交所上市首日涨39% 募1.08亿金元证券保荐|环球快看点
- 锂电池板块跌0.57% 日播时尚涨10%居首
- 生物医药板块跌1.35% 退市辅仁涨7.04%居首
- 广东自贸区固定资产投资累计超1万亿元|全球动态
- 贵州发挥金融“活水”优势支持消费恢复扩大 全球今亮点
- 全国首条长距离新能源运输试点项目落地山西临汾
- TechInsights:全球5G智能手机出货量同比增长3.9%|快讯
- 全球速读:5月份国内汽车投诉量逾1.3万宗创新高 自主品牌插电混动车型投诉量环比涨超3倍
- 智能报警记录仪亮相中国国际社会公共安全产品博览会
- 当前视点!一线城市房地产限购 应适时优化调整
- 环球热消息:艺术特色学校创建自查报告(艺术特色)
- 弘视科技黑科技亮相2023PT|全息互动 4K显示 毫秒延时
- 广发基金王瑞冬:医疗领域关注“三低长尾行业龙头”
- 李云泽:抓紧恢复和扩大有效需求关键手 持续优化和改善金融服务|每日焦点
- 全球快消息!廊坊大力发展现代商贸物流产业
- 多地下调首套房贷利率至4%以下
- 李海涛离任蜂巢添盈纯债
- 世界实时:八仙过海是神话故事吗
- 属羊女的命运不好是真的吗 1967年属羊女命运婚姻|世界关注
- 全国“三夏”麦收进度过半 已收冬小麦达1.64亿亩_环球播报
- vivo手机电池不耐用怎么办教你一招(vivo手机电池不耐用怎么办)
- 微读圣经官方网站_圣经电脑版官方|天天快看
- 美丽的神话歌词完整版_美丽的神话歌词_世界热头条
- 流通协会:4月二手车交易146万辆,市场呈下沉趋势 每日视讯
- 食道癌扩散快吗能治好吗_食道癌扩散快吗
- 短讯!护航逐梦,海底捞开展爱心助考行动
- 天天动态:江铃E400电池包屡修屡坏无法解决 厂家称未达到换新条件
- 国旗旗杆标准尺寸是多少_关于国旗旗杆标准尺寸介绍
- 全球观点:【物流618】申通618第一波单日揽收6000万件
- 焦点短讯!锡林郭勒盟发放内蒙古自治区首笔“带押过户”住房公积金贷款
- 每日快看:广东新丰:厚植生态底色 提升绿色颜值
- 每日速看!创新经营方式 促进农民增收——山西省开展农业生产托管服务纪略
- 【热闻】四川:今年前5月完成投资1447.5亿元
- 洲际、万达布局环球影城,强IP主题乐园如何做好酒店产品?_世界快看点
- 推动文旅赋能乡村振兴,湖南发布最新措施
- 浙江苍南构建自然保护地新体系
- 午评:三大指数早间低位震荡 猪肉板块涨幅居前
- 广汽本田最新公益短片《美在流溪——为生态保护注入源头活水》上线 天天热头条
- 环球今日讯!国家林草局发布黄河上中游天然林保护修复效益监测国家报告
- 榆林治沙带来生态空间颜色之变
- 空调使用旺季来临,教你找到正规的大金空调官方售后维修中心
- 底部放量下跌意味着什么?底部放量下跌是好还是坏?
- 人民币兑美元中间价报7.1280 调贬84个基点
- 底部放量滞涨说明什么?底部放量注意建仓什么意思?
- 环球新动态:福建华通银行被罚97万 未按规定报送可疑交易报告等
- 标准普尔500指数实时行情介绍?标准普尔500指数和道琼斯指数区别在哪?
- 标准普尔500指数是什么意思?标准普尔500指数计算方法为多少?
- 转增股本是什么意思?已发行股本是什么意思非上市公司?
- 重庆油菜喜获丰收 总产量实现连续16年增长|天天最资讯
- 股本是什么意思?股本和实收资本的区别是什么?
- 万达集团回应“19亿股权被冻结”:正通过法律途径申诉
- 天天看点:桂阳:“六月杨梅满枝头 “采梅止渴”正当时
- 交通银行:林骅刘建军王文进高管任职资格获核准
- 我爱我家:预计今年二手房市场交易量将迎来稳健复苏
- 环球观速讯丨请注意!多家银行今起下调存款利率,5年期存款利率2.5%
- 观天下!武汉7宗地块集中拍卖时间推迟至6月26日 起拍总价42.26亿元
- 未来锂供给结构的三大发展方向
- 5月地产销售继续分化 优质房企增长好于平均值
- 环球简讯:新增化学测试指标 根据婴童头围设计尺寸、重量 婴童运动头盔将有标可依
- 拍领导牵手的摄影师立功还是担责?公司领导拍员工照片可以吗?
- 除息日买入股票划算吗?除权除息日应该买入还是卖出?
- 石油与化工指数涨跌互现
- 环球关注:江苏出台14条措施推动外贸稳规模优结构
- 除息日股票为什么会跌?除息日是什么意思?除息日特点介绍
- 纳指纳斯达克指数开盘时间介绍?纳指基金卖出净值怎么算?
- 纳指100实时行情一览 纳指和etf哪个好一点
- 纳指期货和纳斯达克有关系吗?纳指是什么意思?
- 纳指ETF是指什么?纳指etf交易规则及费用是什么?
- 焦点热门:ads是什么意思怎么理解ads是什么意思
- 股票交易系统投票怎么操作?股票交易系统投票有什么用?
- 佳能60d配什么镜头最实用(佳能60d能配70-200吗?)-世界速看料
- 首超日本,我国成世界第一大汽车出口国!_聚看点
- 集资诈骗的定罪标准是什么?集资诈骗案退赔程序怎么走?
- etf期权和股指期权区别是什么?上证etf期权开户条件有哪些?
- 每日热讯!今日上市:双元科技、易实精密
- 50etf期权持仓量多少说明什么?etf期权交易规则及费用详解
- 中方要美拿出诚意,减少周边驻军,你们的舰机,离我们领土太近了|全球报资讯
- 他们用“超级天平”给原子核称“体重”
- 轧空行情是上涨还是下跌?轧空的反义词是什么?
- 轧空什么意思?轧空怎么造句?游戏驿站轧空事件是咋回事?
- 全国“三夏”麦收进度过半 当前头条
- 中国人寿财产保险是国企吗?中国人寿财产保险和中国人保区别在哪?
- 环球视点!别总想着“培育”消费者
- 全国首个百度文心千帆大模型赋能中心基地落地无锡梁溪
- 为什么说带血的流量该好好管管?夺命直播乱象是什么意思?
- 金帝股份过会:今年IPO过关第136家 国信证券过2单
- 存款利率向下 大额存单热销 环球报道
- 电视剧坐庄讲了什么?坐庄赌博构成什么犯罪?
- 李显扬现在哪里任职?李显扬学的什么专业?新加坡李显扬个人简介
- 光伏逆变器发展面临三大挑战 即时看
- 2023年即将倒闭的银行有哪些?国家不允许倒闭的银行有哪几个?
- 天天观速讯丨做好“加减法” 增粮有实招——部分粮食主产区一线扫描
- 工信部:前瞻布局下一代互联网 全面推进6G技术研发 世界热门
- 环球热点评!林业上“云” 生态保护有“数”——数字技术守护绿水青山一线见闻
- 万亿美元发债潮将至 美国金融体系或酝酿流动性风险