首页
社区
课程
招聘
关于网游基址问题
发表于: 2010-9-27 15:57 8024

关于网游基址问题

2010-9-27 15:57
8024
好多文章都说,网游中的一些基址每次进入游戏都是不变化的(游戏不更新的情况下)。
有人解释说,这些基址在程序编译的时候,就确定了,不能改变。

我想请教一下,网游中的基址,到底是怎么回事,是不是真的不变化,为什么不变化?

和我们编写的程序代码有关么?跟代码的编译有关系么?

本人小菜,希望知道的能够给我讲解一下,谢谢了!!!

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 177
活跃值: (278)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
编译的时候编译器决定的值就是不变的。反汇编出来看起来像硬编码的东西就是基址了。还有函数、全局变量之类的,他们的偏移是固定的,加上所在模块起始地址就是实际地址,这个也可以做基址
2010-9-27 16:09
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
天堂猪:编译的时候编译器决定的值就是不变的。反汇编出来看起来像硬编码的东西就是基址了
------------------------------
再请教一下,关于“编译的时候编译器决定的值就是不变的”,其中这个值,编译器是根据什么来决定的?
这个值代表的是什么?
程序运行的时候,这个值与进程的地址空间有什么关系?
2010-9-27 16:41
0
雪    币: 2109
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
其实有可能会变:
LoadLibrary, LoadLibraryEx 不能指定载入的位址, 所以不做
特别的处理, 基址不变.

但是我可以在载入真正的数值运算DLL 之前, 先载入乱数(1 ~ N) 个
无用的DLL, 占用DLL 的位址空间, 这样基址就变了.

载入的基址可以用下列的简化的想法来思考.

主程序: M, 基本上位置不变. 载入的顺序基本不变.

系统DLL: AAAA(长度代表大小), BBB, CCCCC, DDDDDD,
游戏 DLL: II, J, KKKKK, LLLLLL

所以每次载入的基址都一样:
M AAAABBBCCCCCDDDDDDIIJKKKKKLLLLLL

如果Windows 改版, DLL 大小变了, 基址就变了. (AAAA->AAA)
M AAABBBCCCCCDDDDDDIIJKKKKKLLLLLL

如果游戏改版, DLL 大小变了, 基址就变了. (II->III, J->JJJJJ)
M AAABBBCCCCCDDDDDDIIIJJJJJJKKKKKLLLLLL

DLL 的大小一样时, Windows 每次载入的位置固定.
2010-9-27 17:04
0
雪    币: 93
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
其实摆渡一下就好了
内存里面放的是运行程序的编码   
要运行那些东西 先把硬盘里的数据移动到内存里
然后按寻址  找到相应程序的内容 即基址
0X之类的是内存地址来的   
WINDOS XP 是运行在在支持虚拟地址空间的计算机上,虚拟地址空间或者映射到一段真实的物理内存,或者映射到交换文件中的页帧。不同的应用程序可能会操作同一个虚拟地址,但是其对应的物理地址不一定相同,比如进程A和进程B都访问adrs1地址,进程A的地址经过全局表和局部表转换后变为一个指向物理a1内存的地址,而进程B 的地址经过全局表和局部表转换后变为一个指向物理b1内存的地址,而且这个地址所在页并不在物理内存中,而是在交换文件中,于是系统就进行内存交换,将相应的页读入进行操作
文件偏移也比较好理解,文件开始的第一个字节偏移量为0之后每经过一个字节偏移量就加1
2010-9-27 17:06
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
enthos:您说主程序M载入的基址 基本上位置不变。
能不能把这块详细的说一下,我就是不明白为什么程序每次运行的时候,主程序的基址都一样呢。
是不是这个基址就是指的主程序的入口点?
如果是,那么这个入口点是在编译的时候就确定的么?
。。。。。。。。。。。又回到我第二次的问题了。
希望能帮我解答一下。
2010-9-27 17:15
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
爱已绑定:谢谢您的回复,不过,我想知道的是,为什么程序每次运行,所谓的基址都是不变化的呢
2010-9-27 17:20
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
刚查资料:
主程序的入口点的地址,在编译的时候就是确定的。
执行程序代码之前,需要通过PE文件头来找到入口点的地址,然后执行代码指令
------------------------
过程中可能很复杂
--------
然后根据enthos的说明,就可以理解了,基址基本不变的原因。

谢谢上面各位的热心帮助。希望有人再补充,明天我会结贴!
2010-9-27 17:40
0
雪    币: 57
活跃值: (55)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
网游的基地址一般情况下是不变的,对于未加壳的exe程序,由于其无需重定位,其基地址你可以查看器pe结构中的ImageBase获得。对于dll,其在内存中的地址可能每次都不一样(重定位的原因),对于系统dll(kernel32.dll,user32.dll....)在同一个版本系统中加载地址是不变的,这与windows为了提高加载效率对其基地址分别设置了不同的值。
由于pe文件是由连接器生成的,故基地址通常还跟编译器有关,在windows下,exe的基地址通常为0x400000,对于dll,在6.0下的基地址和vs下的基地址都不一样……
对于编译后的二进制文件,其内部内存结构一般情况下是固定的,除非你loadlibrary,随机数等等……
2010-9-27 17:59
0
雪    币: 11
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
连接器链接时把目标文件构建成pe格式文件,pe 格式中有代码段数据段的大小,偏移,以及载入内存后载入的位置,操作系统执行exe程序时解析pe格式,根据格式载入指定内存位置。所以最终还是由连接器决定,连接器链接程序时把段信息设置为默认值,当然所有段基址也自定义,比如ld就有脚本可以指定段的内存位置等等。

所以全局的变量和代码等都是固定位置的,像函数局部变量这些存储于堆栈,根据函数调用顺序的不同最终的地址也不同,还有动态分配的空间(new和malloc分配)和动态分配的资源,内存地址不一定每次都会相同。
2010-9-27 18:18
0
雪    币: 93
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
我是这样理解的:
程序每次编译以后,长度是固定的,而里面的变量、函数需要定位地址(而不是使用我们编程时的变量名或者函数名),这个地址相对于此程序某个起始位置是相对一定的,你在程序中定义的常量(比如角色)的地址相对于这个起始地址也是一定的,那个这个常量的相对地址就可以理解为基址。
2010-9-27 18:27
0
雪    币: 270
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
都说了是编译的时候都已经确定了全局变量,全局类,函数等的地址,而且主程序每次加载的地址都是一样的,那怎么会变,偏移至少都是不会改变的,更新除外。
2010-9-28 01:07
0
雪    币: 196
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
已经结贴了,不过希望路过的能够继续补充自己的理解!
2010-9-28 11:06
0
雪    币: 392
活跃值: (89)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
14
编译链接的时候确定的;每次更新的时候,都会patch一下主程序;至于这个地址,不一定就是imagebase或者entrypoint,只要找到每次加载程序时的一个固定的不变的地址,通过偏移能找到其他的数据地址,就可以作为基址。这个很灵活的
2010-11-4 23:21
0
游客
登录 | 注册 方可回帖
返回
//