当前位置: 首页 > news >正文

《Windows PE》5.3 导出表应用

本节我们将通过三个实验来说明导出表的应用。实验一修改导出表中的函数地址。实验二直接替换导出函数的代码。实验三导出私有函数

本节必须掌握的知识点:

        修改导出函数地址

        替换导出函数代码

        导出私有函数

5.3.1 修改导出函数地址

实验三十七:修改导出函数地址

修改winResult.dll导出结构中的函数地址。仅需要将导出函数调用的RVA地址交换位置,即可实现导出导出函数的覆盖。无需修改程序FirstWindow.exe,直接测试,发现显示窗口的动画效果发生了变化。

第一步:将winResult.dll拖入WinHex中,找到导出表,如下所示:

00001910   00 00 00 00 FF FF FF FF  00 00 00 00 60 25 00 00   ........`%..

00001920   01 00 00 00 04 00 00 00  04 00 00 00 38 25 00 00   ............8%..

00001930   48 25 00 00 58 25 00 00  F0 10 00 00 10 10 00 00   H%..X%..?......

00001940   C0 11 00 00 A0 12 00 00  6E 25 00 00 7B 25 00 00   ?..?..n%..{%..

00001950   87 25 00 00 92 25 00 00  00 00 01 00 02 00 03 00   ?..?..........

00001960   77 69 6E 52 65 73 75 6C  74 2E 64 6C 6C 00 41 6E   winResult.dll.An

00001970   69 6D 61 74 65 43 6C 6F  73 65 00 41 6E 69 6D 61   imateClose.Anima

00001980   74 65 4F 70 65 6E 00 46  61 64 65 49 6E 4F 70 65   teOpen.FadeInOpe

00001990   6E 00 46 61 64 65 4F 75  74 43 6C 6F 73 65 00 00   n.FadeOutClose..

第二步:交换导出函数AnimateOpen和FadeInOpen的RVA地址,如下所示:

00001930   48 25 00 00 58 25 00 00  F0 10 00 00 C0 11 00 00   H%..X%..?......

00001940   10 10 00 00 A0 12 00 00  6E 25 00 00 7B 25 00 00   ?..?..n%..{%..

第三步:保存后,直接运行FirstWindow.exe。

 

总结

在使用导出函数地址覆盖技术的时候,首先要保证所涉及的两个函数参数入口要一致,否则调用完成后栈不平衡,这会导致应用程序调用失败;其次,要求用户对两个函数的内部实现要有充分的了解,使得地址转向后,能够保证应用程序在功能上可以全面兼容并运行良好。

5.3.2 替换导出函数代码

实验三十八:替换导出函数代码

我们还是以winResult.dll为例。找到导出函数FadelnOpen的代码,然后将其替换为MessageBox,弹出一个对话框窗口。无需修改程序FirstWindow.exe。

第一步:将winResult.dll拖入OD调试器,打开内存映射窗口,找到winResult.dll模块,如图所示:

图5-7 内存映射窗口

       第二步:双击winResult.dll的.text节区,打开代码段,找到0x6D010000+0x000011C0地址处,即函数FadelnOpen的地址,如下所示:

6D0111C055              PUSH EBP

6D0111C1    8BEC            MOV EBP,ESP

6D0111C3    83EC 38         SUB ESP,0x38

6D0111C6    A1 0430016D     MOV EAX,DWORD PTR DS:[__security_cookie]

6D0111CB    33C5            XOR EAX,EBP

6D0111CD    8945 FC         MOV DWORD PTR SS:[EBP-0x4],EAX

6D0111D0    0F1005 BC20016D MOVUPS XMM0,DQWORD PTR DS:[??_C@_1BG@OIL>

6D0111D7    A1 CC20016D     MOV EAX,DWORD PTR DS:[0x6D0120CC]

6D0111DC    53              PUSH EBX

6D0111DD    8945 D8         MOV DWORD PTR SS:[EBP-0x28],EAX

6D0111E0    0FB705 D020016D MOVZX EAX,WORD PTR DS:[0x6D0120D0]

6D0111E7    56              PUSH ESI

6D0111E8    0F1145 C8       MOVUPS DQWORD PTR SS:[EBP-0x38],XMM0

第三步:将winResult.dll拖入WinHex窗口,点击“搜索”->“查找HEX数值”,对话框内输入硬编码“558BEC83EC38A1”。如下所示:

图5-8 搜索导出函数硬编码

       第四步:定位到函数FadelnOpen代码:

000005C0   55 8B EC 83 EC 38 A1 04  30 00 10 33 C5 89 45 FC   U嬱冹8?0..3艍E?

000005D0   0F 10 05 BC 20 00 10 A1  CC 20 00 10 53 89 45 D8   ...?..√ ..S塃?

000005E0   0F B7 05 D0 20 00 10 56  0F 11 45 C8 57 0F 10 05   .??..V..E萕...

       第五步:由内存映射窗口可知,在winResult.dll的.data节区在内存中的基址为0x6D013000,在WinHex中查到.data节区在文件中的起始地址为0x00001E00,我们在地址0x00001E20处写入字符串” HelloWorldPE”。

00001E00   B1 19 BF 44 4E E6 40 BB  FF FF FF FF 00 00 00 00   ?緿N鍬?....

00001E10   01 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00   ................

00001E20   48 65 6C 6C 6F 57 6F 72  6C 64 50 45 00 00 00 00   HelloWorldPE....

       第六步,确定当前操作系统中MessageBox函数的入口地址。在OD调试器中打开HelloWord.exe,跟踪到MessageBox函数的入口地址为0x740BFDB0

740BFDB0 >  8BFF            MOV EDI,EDI                              ; HelloWor.<ModuleEntryPoint>

740BFDB2    55              PUSH EBP

740BFDB3    8BEC            MOV EBP,ESP

740BFDB5    6A FF           PUSH -0x1

740BFDB7    6A 00           PUSH 0x0

740BFDB9    FF75 14         PUSH DWORD PTR SS:[EBP+0x14]

740BFDBC    FF75 10         PUSH DWORD PTR SS:[EBP+0x10]

740BFDBF    FF75 0C         PUSH DWORD PTR SS:[EBP+0xC]

740BFDC2    FF75 08         PUSH DWORD PTR SS:[EBP+0x8]

740BFDC5    E8 E6010000     CALL user32.MessageBoxTimeoutA

       第七步:在WinHex中覆盖FadelnOpen代码并保存,如下所示:

000005C0   55 8B EC 6A 00 6A 00 68  20 30 01 6D 6A 00 E8 08   U嬱j.j.h 0.mj.?

000005D0   00 00 00 90 90 90 90 C9  C2 04 00 FF 25 E0 11 01   .......陕..%?.

000005E0   6D EA B0 FD 0B 74 00 56  0F 11 45 C8 57 0F 10 05   m臧?t.V..E萕...

 注意

       1.保存对导出函数FadelnOpen的修改之后,我们很快会发现,程序运行失败。原因是在Win10系统中,每次加载FirstWindow.exe、winResult.dll和user32.dll的基址都会发生变化。

       解决方案:设置VS2017编译器链接选项如下:

#pragma comment(linker,"FIXED:NO")         //固定基址

#pragma comment(linker,"/DYNAMICBASE:NO"//随机基址

设置完成后,重新编译,我们会发现这两个选项不起作用。即VS编译器为了安全,默认重定位基址,不可以改变。说明直接覆盖导出函数代码的方法已经是不可取的了。

2.有兴趣的读者可以在Windows XP系统下,使用VC6.0编译器编译,然后再按照前述方法实验,会发现这种方法是有效的。

WinHex中覆盖后的数据:

00001200   55 8B EC 6A 00 6A 00 68  4C 70 00 10 6A 00 E8 08   U嬱j.j.hLp..j.?

00001210   00 00 00 90 90 90 90 C9  C2 04 00 FF 25 21 12 00   ...悙悙陕..%!..

00001220   10 EA 07 D5 77 00 00 8B  15 54 70 00 10 89 44 24   .?誻..?Tp..塂$

1000704C:”user32.dll”字符串地址。

10001221:跳转到函数FadelnOpen的入口地址。

77D507EA:MeassgeBox函数入口地址。

【注意】不同机器中上述3个地址可能各不相同,需要在OD调试器中确认。

3.还有一种方法,就是使用汇编代码编写程序,没有重定位节区,使用固定的基址,这种方法也是有效的。

5.3.3 导出私有函数

在某些场合下,DLL中的私有函数还是很有用的。也许是出于保密考虑,或者其他原因,DLL的开发者将一些比较重要的函数设置为内部私有函数,并不在导出表中声明。当程序被 二次开发时,开发者却需要这些函数,这时候就需要开发者自己将这些被定义为私有的函数 添加到导出表中。

在本章的实例中,动态链接库winResult.dll 一共导出了 4个公有导出函数;源代码中的TopXY函数被声明为私有函数,并未导出,所以在使用GetExportInfo2分析时看不到该函数。下面这个实验就以这个函数为例,介绍一下导出私有函数需要做哪些工作。

实验三十九:导出私有函数

将winResult.dll的私有函数TopXY添加到导出表中,改为公有的导出函数。

第一步:将winResult.dll拖入WinHex,数据目录项中找到导出表项,如下所示:

00000170   10 25 00 00 90 00 00 00  A0 25 00 00 64 00 00 00   .%......?..d...

00000180   00 40 00 00 F8 00 00 00  00 00 00 00 00 00 00 00   .@..?..........

00000190   00 00 00 00 00 00 00 00  00 50 00 00 7C 01 00 00   .........P..|...

000001A0   F0 20 00 00 70 00 00 00  00 00 00 00 00 00 00 00   ?..p...........

000001B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001C0   60 21 00 00 40 00 00 00  00 00 00 00 00 00 00 00   `!..@...........

000001D0   00 20 00 00 8C 00 00 00  00 00 00 00 00 00 00 00   . ..?..........

000001E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

第二步:定位导出表。导出表位于.rdata节区,定位导出表的FOA地址为:00001910。

00001910   00 00 00 00 FF FF FF FF  00 00 00 00 60 25 00 00   ........`%..

00001920   01 00 00 00 04 00 00 00  04 00 00 00 38 25 00 00   ............8%..

00001930   48 25 00 00 58 25 00 00  F0 10 00 00 10 10 00 00   H%..X%..?......

00001940   C0 11 00 00 A0 12 00 00  6E 25 00 00 7B 25 00 00   ?..?..n%..{%..

00001950   87 25 00 00 92 25 00 00  00 00 01 00 02 00 03 00   ?..?..........

00001960   77 69 6E 52 65 73 75 6C  74 2E 64 6C 6C 00 41 6E   winResult.dll.An

00001970   69 6D 61 74 65 43 6C 6F  73 65 00 41 6E 69 6D 61   imateClose.Anima

00001980   74 65 4F 70 65 6E 00 46  61 64 65 49 6E 4F 70 65   teOpen.FadeInOpe

00001990   6E 00 46 61 64 65 4F 75  74 43 6C 6F 73 65 00 00   n.FadeOutClose..

000019A0   04 26 00 00 00 00 00 00  00 00 00 00 BE 26 00 00   .&..........?..

       第三步:修改导出表。

       1.修改导出表描述符,导出函数的个数和函数名导出函数的个数改为5。

       2.函数地址表添加4个字节:添加函数TopXY的入口地址。

       确定函数TopXY的入口地址:将winResult.dll拖入OD调试器,打开内存映射窗口,点击winResult.dll的.text节区,显式winResult.dll代码内容如下所示。我们会发现,VS2017编译后的代码中,并不存在函数TopXY。

      

0FFD1000    B8 01000000     MOV EAX,0x1

0FFD1005    C2 0C00         RETN 0xC

0FFD1008    CC              INT3

0FFD1009    CC              INT3

0FFD100A    CC              INT3

0FFD100B    CC              INT3

0FFD100C    CC              INT3

0FFD100D    CC              INT3

0FFD100E    CC              INT3

0FFD100F    CC              INT3

0FFD1010 >  55              PUSH EBP

结论:如果要将私有函数导出,前提是该私有函数必须存。

我们改用VC6.0编译。同样在WinHex中定位到导出表数据如下:

00006B40   00 00 00 00 5A F3 1D 66  00 00 00 00 90 6B 00 00   ....Z?f.....k..

00006B50   01 00 00 00 04 00 00 00  04 00 00 00 68 6B 00 00   ............hk..

00006B60   78 6B 00 00 88 6B 00 00  30 11 00 00 30 10 00 00   xk..坘..0...0...

00006B70   00 12 00 00 C0 12 00 00  9E 6B 00 00 AB 6B 00 00   ....?..瀔..玨..

00006B80   B7 6B 00 00 C2 6B 00 00  00 00 01 00 02 00 03 00   穔..耴..........

00006B90   77 69 6E 52 65 73 75 6C  74 2E 64 6C 6C 00 41 6E   winResult.dll.An

00006BA0   69 6D 61 74 65 43 6C 6F  73 65 00 41 6E 69 6D 61   imateClose.Anima

00006BB0   74 65 4F 70 65 6E 00 46  61 64 65 49 6E 4F 70 65   teOpen.FadeInOpe

00006BC0   6E 00 46 61 64 65 4F 75  74 43 6C 6F 73 65 00 00   n.FadeOutClose..

       第三步:修改导出表。

       1.修改导出表描述符,导出函数的个数和函数名导出函数的个数改为5。

       2.函数地址表添加4个字节:添加函数TopXY的入口地址。

       确定函数TopXY的入口地址:将winResult.dll拖入OD调试器,打开内存映射窗口,点击winResult.dll的.text节区,显式winResult.dll代码内容如下所示。

10001000    B8 01000000     MOV EAX,0x1

10001005    C2 0C00         RETN 0xC

10001008    90              NOP

10001009    90              NOP

1000100A    90              NOP

1000100B    90              NOP

1000100C    90              NOP

1000100D    90              NOP

1000100E    90              NOP

1000100F    90              NOP

10001010    8B4424 04       MOV EAX,DWORD PTR SS:[ESP+0x4]

10001014    8B4C24 08       MOV ECX,DWORD PTR SS:[ESP+0x8]

10001018    D1E8            SHR EAX,1

1000101A    D1E9            SHR ECX,1

1000101C    2BC8            SUB ECX,EAX

1000101E    8BC1            MOV EAX,ECX

10001020    C3              RETN

函数TopXY的入口地址为:10001010,减去基址10000000,得到RVA地址为1010

00006B40   00 00 00 00 5A F3 1D 66  00 00 00 00 9A 6B 00 00   ....Z?f....歬..

00006B50   01 00 00 00 05 00 00 00  05 00 00 00 68 6B 00 00   ............hk..

00006B60   7C 6B 00 00 90 6B 00 00  30 11 00 00 30 10 00 00   |k...k..0...0...

00006B70   00 12 00 00 C0 12 00 00  10 10 00 00 A8 6B 00 00   ....?......╧..

00006B80   B5 6B 00 00 C1 6B 00 00  CC 6B 00 00 D9 6B 00 00   磌..羕..蘫..賙..

00006B90   00 00 01 00 02 00 03 00  04 00 77 69 6E 52 65 73   ..........winRes

00006BA0   75 6C 74 2E 64 6C 6C 00  41 6E 69 6D 61 74 65 43   ult.dll.AnimateC

00006BB0   6C 6F 73 65 00 41 6E 69  6D 61 74 65 4F 70 65 6E   lose.AnimateOpen

00006BC0   00 46 61 64 65 49 6E 4F  70 65 6E 00 46 61 64 65   .FadeInOpen.Fade

00006BD0   4F 75 74 43 6C 6F 73 65  00 54 6F 70 58 59 00 00   OutClose.TopXY..

3.添加6个字节函数名字符串:”TopXY\0”。

4.添加4个字节函数名RVA地址:D9 6B 00 00。

5.添加2个字节序号表:0004。

6.修改模块名RVA地址、函数名RVA地址。

7.删除16个零字节,让后面的.data节区地址保持不变。

8.数据目录项中导出表的大小可以改,也可以不改。

第四步:测试。

1.FirstWindow.exe可以正常运行。

2.调用GetExportInfo2.exe程序打印导出函数,如下所示:

序号    函数地址        函数名

0x0000  0x00001130  AnimateClose

0x0001  0x00001030  AnimateOpen

0x0002  0x00001200  FadeInOpen

0x0003  0x000012c0  FadeOutClose

0x0004  0x00001010  TopXY

请按任意键继续. . .

 

总结

       1.在使用导出函数地址覆盖技术的时候,首先要保证所涉及的两个函数参 数入口要一致,否则调用完成后栈不平衡,这会导致应用程序调用失败;其次,要求用户对两 个函数的内部实现要有充分的了解,使得地址转向后,能够保证应用程序在功能上可以全面 兼容并运行良好。

       2.Windows 64位操作系统和新版本的VS编译器对于安全限制更严格。默认不可以使用固定基址。在Windows 10系统中使用VS2017编译的程序由于会重定位基址,基址重定位后,无法确定正确的基址,覆盖导出函数代码的方法无效,导致程序运行失败。在Windows XP系统中使用VC6.0编译的程序,覆盖导出函数代码的方法有效。使用汇编代码编译的版本,覆盖导出函数代码的方法有效。

3.导出私有函数只支持XP系统中VC6.0编译版本。VS2017编译器未能正常生成私有函数TopXY。


http://www.mrgr.cn/news/47646.html

相关文章:

  • 简单易用的PDF工具箱
  • 概率论与数理统计总复习
  • U盘加密软件哪个好用?免安装、安全、防复制
  • 芯片详细讲解,从而区分CPU、MPU、DSP、GPU、FPGA、MCU、SOC、ECU
  • 5G学习笔记之SNPN系列之UE入网和远程配置
  • 利用ArcGIS快速准确地统计出地块的现状容积率
  • js 条件判断语句
  • 【动态规划】状态 dp
  • 准备进入AI第三阶段:OpenAI推出AI Agent基准MLE-bench!
  • leetcode hot100_part03_滑动窗口
  • 塔吊识别数据集 yolo格式 共5076张图片 已划分好训练验证 txt格式 yolo可直接使用
  • PMP--冲刺题--解题--101-110
  • Python酷库之旅-第三方库Pandas(143)
  • 浏览器内置文字转语音,播报功能Web Speech API - SpeechSynthesisUtterance
  • Paperless-ngx文档管理系统本地部署并实现远程使用搜索查阅文件
  • QFocusFrame Class
  • 【C# 网络编程】基本概念
  • 【MySQL】入门篇—数据库基础:关系数据库概念
  • 01 为什么要学习数据结构与算法
  • 磁盘标签和分区标签
  • 作用域,预解析学习
  • uniapp 编程体验
  • XML XSLT:转换与呈现数据的力量
  • 说一下 HashMap 的实现原理?
  • 【idea】切换多个仓库到一个分支
  • HTTP Content-Type