12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
三国霸业 战车-珍宝-觉醒-攻城掠地SF-全新玩法 免费玩新区 攻城掠地私服 进入游戏
手游私服盒子 各类免费游戏 0.1折送海量资源 各类手游私服 进入游戏
皇家MU2 《奇迹 2:传奇》韩国网禅公司《奇迹》正统续作。 3D锁视角Mmrpg 暗黑3+传奇+流放之路+奇迹 进入游戏
查看: 293|回复: 0

PE文件笔记十六 代码重定位

[复制链接]

303

主题

303

帖子

616

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
616
发表于 2021-5-7 23:23:47 | 显示全部楼层 |阅读模式
继续PE系列笔记的更新
PE其它笔记索引可前去:
PE文件笔记一 PE介绍
前面在PE文件笔记十五 导入表中学习了导入表,接着要学习重定位表,但在学习重定位表前,要先了解一下代码重定位
代码重定位

在学习重定位表之前,要知道什么是代码重定位
代码重定位定义

代码重定位是把可执行代码从内存的一个地方移动到别的一个地方去,包管该部分代码还能正常执行
重定位的提出

可执行代码从内存的一个地方移动到别的一个地方,全部的字节码(硬编码)均保持不变;如果代码指令中的某些操作数不跟着地点发生改变,势必会导致步伐运行出错。这里的某些操作数是指那些使用了绝对地点定位的步伐指令中的操作数
为更好地学习重定位,联合下面的实例分析:
代码

#include int main(){        int result=0;        _asm{_code:                xor eax,eax                mov al,byte ptr ds:[_data]                jmp _end_data:                _emit 0x61_end:                mov result,eax        }        printf("%X\n",result);        return 0;}代码说明

上面的代码十分简短简单,主要看汇编的代码
汇编代码分为三段:代码段_code、数据段_data、竣事段_end
代码段

代码段就是取出数据段的数据,然后生存到寄存器eax
数据段

数据段只存储了一个数据0x61
竣事段

将先前生存到寄存器eax中的数据赋值给变量result
运行结果


可以看到,代码能够正常地取出数据区的内容并打印出来
反汇编对应的硬编码

5:        _asm{6:    _code:7:            xor eax,eax0040D73F 33 C0                xor         eax,eax8:            mov al,byte ptr ds:[_data]0040D741 3E A0 49 D7 40 00    mov         al,ds:[_data (0040d749)]9:            jmp _end0040D747 EB 01                jmp         _end (0040d74a)10:   _data:11:           _emit 0x610040D749 61                   db 61h12:   _end:13:           mov result,eax0040D74A 89 45 FC             mov         dword ptr [ebp-4],eax14:       }这里关注一下出现地点的两个地方的硬编码:
第一处

8:            mov al,byte ptr ds:[_data]0040D741 3E A0 49 D7 40 00    mov         al,ds:[_data (0040d749)]取出0040d749地点对应的数据,取出的数据宽度为一个字节,然后赋值给al(eax的低8位)
可以看到这里的硬编码直接就是写死的地点0040d749(49 D7 40 00 小端存储),为绝对地点
第二处

9:            jmp _end0040D747 EB 01                jmp         _end (0040d74a)这里的jmp跳转则是采用偏移的方式,其偏移为01(前面的EB 表示jmp)
要跳转的地点 = 当前地点 + 当前指令长度 + 偏移 = 0040D747 + 2 + 1 = 0040D74A
第二处的代码则是采用了相对地点的方法举行寻址
没重定位带来的题目

前面的代码中存在绝对地点,因此如果将代码移到别的地方一定导致结果错误
于是为了验证这一点,举行以下的演示:
首先复制其对应的硬编码:
33 C0 3E A0 49 D7 40 00 EB 01 61 89 45 FC然后用OD随便打开一个步伐
随便选中一行代码,然后 右键→二进制→编辑(或使用快捷键Ctrl+E)

在弹出来的编辑窗口中,取消勾选保持大小,然后将硬编码粘贴进去

得到结果:

可以看到,此时采用相对地点的jmp指令后面跳转的地点发生了变化,依然能够跳转到我们想要的位置
但是mov指令由于接纳了绝对地点,它去取的地点仍旧是先前的地点,没有对应去取下面的数据:0x61
也因此导致了,代码位置变化以后,其运行的结果就不正确了
修正重定位

通过前面,可以知道,代码出错的缘故原由在于mov指令后面采用了绝对地点
于是将mov 指令后面的地点改为相对地点即可
代码

#include int main(){        int result=0;        _asm{_code:                call _call                xor ebx,ebx                                mov bl,byte ptr ds:[eax+8]                jmp _end_data:                _emit 0x61_call:                mov eax,dword ptr ss:[esp]                ret_end:                mov result,ebx        }        printf("%X\n",result);        return 0;}代码说明

代码中多了一个_call段,该段用来调用call,根据堆栈的特性,获得的[esp]里存储的地点为xor ebx,ebx这一行指令的地点
不了解为什么在call里面可以通过这种方法获取到返回地点的可以回顾:逆向基础笔记七 堆栈图(重点)
获取到地点后将地点生存到eax中
之后返回以后通过xor ebx,ebx这一行的地点+偏移8得到_data的地点,此时采用的便是相对地点的方式
修正后对应的硬编码

5:        _asm{6:    _code:7:            call _call0040D73F E8 09 00 00 00       call        _call (0040d74d)8:            xor ebx,ebx0040D744 33 DB                xor         ebx,ebx9:            mov bl,byte ptr ds:[eax+8]0040D746 3E 8A 58 08          mov         bl,byte ptr ds:[eax+8]10:           jmp _end0040D74A EB 06                jmp         _end (0040d752)11:   _data:12:           _emit 0x610040D74C 61                   popad13:   _call:14:           mov eax,dword ptr ss:[esp]0040D74D 36 8B 04 24          mov         eax,dword ptr ss:[esp]15:           ret0040D751 C3                   ret16:   _end:17:           mov result,ebx0040D752 89 5D FC             mov         dword ptr [ebp-4],ebx18:       }这里关注一下出现地点的地方的硬编码
7:            call _call0040D73F E8 09 00 00 00       call        _call (0040d74d)这里的call调用采用偏移的方式,其偏移为09(前面的E8 表示call)
要跳转的地点 = 当前地点 + 当前指令长度 + 偏移 = 0040D73F + 5 + 9 = 0040D74D
于是此时的代码就全部是采用相对地点了,此时代码就支持重定位了
测试重定位后的硬编码

依旧要先将重定位的硬编码复制出来:
E8 09 00 00 00 33 DB 3E 8A 58 08 EB 06 61 36 8B 04 24 C3 89 5D FC然后用OD随便打开一个步伐
随便选中一行代码,然后 右键→二进制→编辑(或使用快捷键Ctrl+E)

在弹出来的编辑窗口中,取消勾选保持大小,然后将硬编码粘贴进去

得到结果:

可以看到采用了相对地点后,移动完代码的位置其代码依然满意我们的需求
F8单步步过到最后一行代码,检察ebx此时的值

可以看到此时的ebx能够正确地获取到数据区的内容( •̀ ω •́ )✧
采用重定位技术的利益

从上面的例子中,不难的得出采用重定位技术的利益:
如果在代码编写中使用重定位技术,你就可以将代码随意地部署到内存中,而不影响步伐的运行
总结


  • 采用重定位技术,可以让代码段在恣意内存中运行
  • 重定位技术的核心就在:不使用绝对地点,而使用相对地点
  • 使用的是绝对地点还是相对地点,归根结底取决于其对应的硬编码

来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-11-24 19:26 , Processed in 0.093750 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

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