| | |
|
组别 | 士兵 |
级别 | 牙门将军 |
功绩 | 5 |
帖子 | 546 |
编号 | 301657 |
注册 | 2008-12-18 |
| |
| | |
|
|
|
用OLLYDBG修改曹操传EXE实际例子
表达能力有限,不多说,本帖将贴出本人修改EXE的一切代码,绝大部分代码将会注释说明用意,如有错误还望路过的大神们不吝指出...........
注意:有心学习如何用OLLYDBG修改曹操传EXE的枭雄们请一定要先看以下两遍基础教程帖子再来看本帖的内容,因为学东西老想着跳墙走捷径,是没用的哦,基础必须打好。
http://www.xycq.net/forum/thread-194034-1-1.html 如何使用Ollydbg修改曹操传引擎 作者:godtype
http://www.xycq.net/forum/thread-276716-1-1.html OLLYDBG修改曹操传EXE实际操作演示 作者:WHITESHIP
同为初学者,若你看完上面的两个教程贴,掌握了一些基础知识但仍不知如何入手时,此贴应该能帮到你
本帖所举的例子里用到的函数不同引擎各有千秋,所以照抄出事的别赖我
下面贴正文,首当其冲,是特效,没错,新人就是爱弄些特效改改,我也不例外,贴一个上来:
***************特效:特定武将物理攻击无视目标30%的防御力,支持5个武将***************
举例引擎6.0EXE:
跟伤害有关自然要找物理伤害计算函数了:0043BC62 ,WHITESHIP的教程贴有讲到
原地址跳出:
0043BD28 - E9 62A50E00 JMP Ekd5_R.0052628F ;位置不够用,所以跳到新位置写,原0043BD28至0043BD31,10个字节写的就是获取被攻击方防御力的代码
0043BD2D 90 NOP
0043BD2E 90 NOP
0043BD2F 90 NOP
0043BD30 90 NOP
0043BD31 90 NOP
0043BD32 0FB64D E8 MOVZX ECX,BYTE PTR SS:[EBP-18] ;最终跳回来的位置
要无视目标防御力,自然要在函数获取目标防御力时做手脚了,所以如上
空白位置:
0052628F FF75 D4 PUSH DWORD PTR SS:[EBP-2C] ;将存放了发动攻击的武将战场内存地址[EBP-2C]作为参数2输入下列函数
00526292 FF75 08 PUSH DWORD PTR SS:[EBP+8] ;将存放了存放了被攻击的武将战场内存地址[EBP+8]作为参数1输入下列函数
00526295 E8 0D000000 CALL Ekd5_R.005262A7 ;调用自写的函数(005262A7函数地址)
0052629A - E9 935AF1FF JMP Ekd5_R.0043BD32 ;调用完后跳回去0043BD32做剩余操作
0052629F CC INT3 ;〓
005262A0 CC INT3 ;〓
005262A1 CC INT3 ;〓
函数:
005262A7 55 PUSH EBP ; 函数开头必带,照抄就行
005262A8 8BEC MOV EBP,ESP ; 函数开头必带,照抄就行
005262AA 83EC 08 SUB ESP,8 ; 需要用到几个暂存空间就设置几,这里空出2个暂存空间用 每个占4字节,所以2*4=8
005262AD 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C] ; 设置ECX=[EBP+C]上的地址,[EBP+C]就是输入进来的[EBP-2C] 存放了发动攻击的武将战场内存地址
005262B0 66:8B01 MOV AX,WORD PTR DS:[ECX] ; 通过武将战场内存地址获取其data序号 战场内存地址首个数值就是data序号
005262B3 66:8945 FC MOV WORD PTR SS:[EBP-4],AX ; 用[EBP-4]暂存空间来存放获得的data序号
005262B7 33D2 XOR EDX,EDX ; 清空EDX寄存器
005262B9 66:8B82 0B63520>MOV AX,WORD PTR DS:[EDX+52630B] ; 为下面的循环算法作头,要连续比较5个武将data序号,edx作为计数,52630B地址起始存放了为想要有这特效的5个武将data序号
005262C0 66:3945 FC CMP WORD PTR SS:[EBP-4],AX ; 比较发动攻击的武将data序号是否符合上面地址读取到的data序号
005262C4 74 0A JE SHORT Ekd5_R.005262D0 ; 相同则跳过下面的循环判断,转到下面作计算运作
005262C6 42 INC EDX ; 即EDX里的地址+1
005262C7 42 INC EDX ; 两个INC即EDX+2进入第2、3、4....个地址
005262C8 90 NOP
005262C9 83FA 05 CMP EDX,0A ; 比较是否判断过5个地址了,10/2=5,2字节一个武将序号
005262CC 77 21 JA SHORT Ekd5_R.005262EF ; 大于就表示5个地址上的data序号没有一个和发动攻击的武将data序号相同,跳出循环,到后面做正常获取防御力运作
005262CE ^ EB E9 JMP SHORT Ekd5_R.005262B9 ; 小于就跳到上面继续循环,直到5个地址都比较过为止
005262D0 6A 01 PUSH 1 ; 发动攻击的武将data序号与0052630B+EDX的某个地址上的武将data序号相同则开始获取被攻击方防御力
005262D2 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] ; [EBP+8]则是输入进来的[EBP+8](存放了存放了被攻击的武将战场内存地址)
005262D5 E8 E760F1FF CALL Ekd5_R.0043C3C1 ; 根据上面的PUSH 1来获取防御力,0=攻击力 1=防御力 2=精神力 3=爆发力 4=士气
005262DA 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX ; 用[EBP-8]暂存空间来存放输出的EAX,即被攻击的武将防御力(包括装备加成)
005262DD FF75 F8 PUSH DWORD PTR SS:[EBP-8] ; 将[EBP-8](存放了防御力数值)输入下面计算函数(作为参数2)
005262E0 6A 1E PUSH 1E ; 1E(30),也输入到下面的函数计算(作为参数1)
005262E2 E8 AD93FAFF CALL Ekd5_R.004CF694 ; 该函数是根据上面的两个参数进行计算得出结果为: 30%参数2里的数值,输出到EAX里
005262E7 2945 F8 SUB DWORD PTR SS:[EBP-8],EAX ; 将[EBP-8]上的数值减去算出来的30%防御力(004CF694函数输出来的EAX)
005262EA 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] ; 设置EAX=[EBP-8],因为函数结束后输出的要是EAX,所以此步必须
005262ED EB 0A JMP SHORT Ekd5_R.005262F9 ; 跳过下面的正常获取防御力代码,无条件直接到函数尾结束
005262EF 6A 01 PUSH 1 ; 1
005262F1 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8] ; 2
005262F4 E8 C860F1FF CALL Ekd5_R.0043C3C1 ; 3段代码是正常的获取被攻击方的防御力,0043C3C1输出的是EAX
005262F9 8BE5 MOV ESP,EBP ; 函数末尾必带,照抄就行
005262FB 5D POP EBP ; 函数末尾必带,照抄就行
005262FC C2 0800 RETN 8 ; 最后返回母函数,根据PUSH进来的两个参数占用了两个暂存空间要减回去,每个暂存空间占4字节,所以2*4=8
; 以下为武将物理攻击无视目标30%防御力,存放了5个武将data序号地址,占用2*5=10字节
0052630B 0100 ADD DWORD PTR DS:[EAX],EAX ; 注意编辑写法是要写相反的,0100即0001,1号武将,0500即0005,5号武将
0052630D 05 000C0010 ADD EAX,10000C00
00526312 0002 ADD BYTE PTR DS:[EDX],AL
00526314 00 ADD BYTE PTR DS:[EAX],AL
小解:
特效是由武将来决定要不要有效地,所以要获取武将的data序号来识别,再获取存放拥有该特效的武将data序号地址(本帖是52630B起始10个字节)来进行比较是否该武将发动的攻击,符合该条件了就要进行防御力的增减操作(我们要无视30%防御力,也就是目标武将输出来的防御力减掉30%吗,很简单的),最后再补上条件不符合了的正常操作即通过0043C3C1函数输出防御力不做减少算法,其他不明的看注释
选择合适原始地址跳出问题:
究竟该如何判断哪个位置适合跳出,个人观点:①从需要用的数据后面开始查找(本帖需要[EBP-2C]里的数据和[EBP+8]里的数据,所以就要从产生它们的代码后面开始 ②在你找到觉得合适的位置时要看看其他代码有没有跳到你选的位置,没有则好,有则要详细分析是否会造成其他数据出现错误,这个不好说明,纯看自身对代码的理解..........
关于EAX,ECX,EDX类寄存器和[EBP-4]、[EBP-8]、类暂存空间的使用小知识:
虽说两者都是可以用来存放数据啊类的,但是使用时长却往往有很多大的区别,上面函数中用到了一条XOR EDX,EDX,意思是清空了寄存器EDX,可能你会想万一里面存放了重要数据要怎么办,这点可以不用担心的,因为你看后面EAX寄存器的反复使用就知道了,里面的存放的东西一直在改变,也说明了象EAX,ECX,EDX这类寄存器一般只用于超短暂的数据存放(一般不超过3、4段代码,当然不排除个别例外),尤其是和CALL函数一起用时就更短暂了,而[EBP-4]、[EBP-8]、[EBP-C].........类暂存空间的使用时长却往往有可能存到接近函数尾才被使用,所以这点还请注意,调用原始地址里的暂存空间一定要先查清楚存放的数据对后面的代码有没影响,还有一段函数里有多少个暂存空间也要看清楚,一般数量决定于开头的SUB ESP,X,而后的PUSH ECX之类也要算进去,例如该函数最多用3个暂存空间,也就是[EBP-4]、[EBP-8]、[EBP-C]最多用到-C,而你突然来个[EBP-10],即第4个暂存空间,那我可以告诉你你存放在[EBP-10]里的数据是不会有结果的........................
函数间的传递关系:
上面注释有说到RETN X是返回母函数,那么母函数是什么呢?举个例子:A将绝技传给了B,B将绝技又传给了C,C将绝技传给了D,D将绝技传给了E.....................如此绝技一直传递下去,到了某深处回访
A→B→C→D→....................最后回访A←B←C←D←
也就是A是B的母函数,B是C的母函数,C是D的母函数..........而它们之间传递的绝技就是[EBP+8].....[EBP+10]...首个ECX、首个EAX...等等里面存放的数据了,如果你想了解一段函数里首个EAX类的寄存器或是[EBP+8](注意是+,而不是-,为什么看WHITESHIP得教程贴就知道)之类存放了什么数据,有两种方法,①用OB调试凭着修改经验和下面调用的CALL函数去判断 ②乖乖的一条一条函数返回去查看母函数输入的是什么东西,怎么查看该函数(儿子)被哪些函数(母亲)调用了看WHITESHIP的教程贴...........................由此基础贴的内容有多重要
-----------------------------------------------------------------不华丽的分割线--------------------------------------------------------------------------------
****************扩展40个大兵种施放特定类型策略伤害获得加成,每个兵种对应一个策略类型一个伤害加成数值*********************
该函数重点是如何根据兵种编号来获取相对应地址上的数据方法,是目前我唯一知道的法子,还是看毅大的5.0旧引擎学来的........写法有点出入,而且我连伤害也一起扩展对应每个兵种(学以致用吗,你也来一起动手吧,光看不操作也是难学的).............................上面无视30%防御力特效里获取拥有此特效的武将Data序号地址的方法也是效法这个得
原代码位置修改:
0043C1F0 >-\E9 C59F0E00 JMP Ekd5_R.005261BA ; 跳转到扩展40个大兵种施放特定类型策略伤害获得加成地址
0043C1F5 90 NOP
0043C1F6 90 NOP
0043C1F7 90 NOP
0043C1F8 90 NOP
0043C1F9 90 NOP
0043C1FA 90 NOP
0043C1FB 90 NOP
0043C1FC 90 NOP
0043C1FD 90 NOP
0043C1FE 90 NOP
0043C1FF 90 NOP
0043C200 90 NOP
0043C201 90 NOP
0043C202 90 NOP
0043C203 90 NOP
0043C204 90 NOP
新增代码:
; 以下为扩展某兵种施放指定类型策略伤害加成
005261BA 0FB64D 10 MOVZX ECX,BYTE PTR SS:[EBP+10] ; 设置ECX=[EBP+10] [EBP+10] 存放了施放的策略编号
005261BE E8 3FDEF5FF CALL Ekd5_R.00484002
005261C3 E8 44C5F1FF CALL Ekd5_R.0044270C ; 两个call根据策略编号计算出该策略属于什么类型,存到EAX里
005261C8 8945 EC MOV DWORD PTR SS:[EBP-14],EAX ; 用暂存空间[EBP-14]来保存输出来的EAX EAX存放了计算出来的策略类型
005261CB 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-18] ; 设置ECX=[EBP-18] [EBP-18]存放了施放策略的武将战场内存
005261CE E8 D452F1FF CALL Ekd5_R.0043B4A7 ; 运算出武将所属的大兵种
005261D3 8A80 0D625200 MOV AL,BYTE PTR DS:[EAX+52620D] ; 读取存放兵种所指的「策略类型」地址上的数值 序号只有1字节所以用AL
005261D9 3945 EC CMP DWORD PTR SS:[EBP-14],EAX ; 比较策略类型是否符合上面读取到的数值
005261DC - 0F85 2360F1FF JNZ Ekd5_R.0043C205 ; 不相同则跳回去做剩余运作
005261E2 8B4D E8 MOV ECX,DWORD PTR SS:[EBP-18] ;
005261E5 E8 BD52F1FF CALL Ekd5_R.0043B4A7 ; 再次读取施放策略的武将所属兵种,因为上面输出的EAX已经变质了
005261EA 8A80 37625200 MOV AL,BYTE PTR DS:[EAX+526237] ; 读取存放兵种所指的策略类型*「伤害加成数值」地址
005261F0 FF75 FC PUSH DWORD PTR SS:[EBP-4] ; 将[EBP-4]里的数据输入下列函数 [EBP-4]存放了策略造成的伤害
005261F3 50 PUSH EAX ; 将读取到的伤害加成也输入进行计算
005261F4 E8 9B94FAFF CALL Ekd5_R.004CF694 ; 计算伤害加成
005261F9 0145 FC ADD DWORD PTR SS:[EBP-4],EAX ; 得出的伤害加成值加入[EBP-4]里
005261FC - E9 0460F1FF JMP Ekd5_R.0043C205 ; 无条件跳回去做剩余运作
; 以下为兵种施放指定类型策略伤害加成,存放兵种所指的「策略类型」
0052620D 03FF ADD EDI,EDI ; **起始地址 40个字节对应40个兵种
0052620F FFFF ??? ; 未知命令
00526211 FFFF ??? ; 未知命令
00526213 FF02 INC DWORD PTR DS:[EDX]
00526215 FFFF ??? ; 未知命令
00526217 FFFF ??? ; 未知命令
00526219 05 FFFFFFFF ADD EAX,-1
0052621E FFFF ??? ; 未知命令
00526220 FFFF ??? ; 未知命令
00526222 FFFF ??? ; 未知命令
00526224 FFFF ??? ; 未知命令
00526226 FFFF ??? ; 未知命令
00526228 FFFF ??? ; 未知命令
0052622A FFFF ??? ; 未知命令
0052622C FFFF ??? ; 未知命令
0052622E FFFF ??? ; 未知命令
00526230 FF01 INC DWORD PTR DS:[ECX]
00526232 FFFF ??? ; 未知命令
00526234 FF00 DEC ESP
; 以下为兵种施放指定类型策略伤害加成,存放兵种所指的「伤害加成数值」
00526237 1900 SBB DWORD PTR DS:[EAX],EAX ; **起始地址 40个字节对应40个兵种
00526239 0000 ADD BYTE PTR DS:[EAX],AL
0052623B 0000 ADD BYTE PTR DS:[EAX],AL
0052623D 001400 ADD BYTE PTR DS:[EAX+EAX],DL
00526240 0000 ADD BYTE PTR DS:[EAX],AL
00526242 006400 00 ADD BYTE PTR DS:[EAX+EAX],AH
00526246 0000 ADD BYTE PTR DS:[EAX],AL
00526248 0000 ADD BYTE PTR DS:[EAX],AL
0052624A 0000 ADD BYTE PTR DS:[EAX],AL
0052624C 0000 ADD BYTE PTR DS:[EAX],AL
0052624E 0000 ADD BYTE PTR DS:[EAX],AL
00526250 0000 ADD BYTE PTR DS:[EAX],AL
00526252 0000 ADD BYTE PTR DS:[EAX],AL
00526254 0000 ADD BYTE PTR DS:[EAX],AL
00526256 0000 ADD BYTE PTR DS:[EAX],AL
00526258 0000 ADD BYTE PTR DS:[EAX],AL
0052625A 001400 ADD BYTE PTR DS:[EAX+EAX],DL
0052625D 0000 ADD BYTE PTR DS:[EAX],AL ; **终结地址
小解:
这段代码不是以新建函数格式来写的,直接是从原始地址跳出然后继续续写的,所以不是一点要以新建函数的格式来新代码。同样跟伤害有关,自然要在伤害函数上动手脚啦,不过这里是策略的伤害计算函数哦,物理与策略是有区分的哦。要施放策略方受益,自然要查找出哪个暂存空间是存放施放策略武将的数据的(这里找到的是[EBP-18]武将战场内存),还有兵种,这里的CALL 0043B4A7函数就是根据武将战场内存(其实该函数里面实际是透过战场内存计算出Data内存,再根据Data内存计算出兵种的)计算出所属的大兵种编号输出到EAX里,[EAX+52620D] 即兵种编号+上52620D得出该兵种对应的新地址位置,例:输出的EAX兵种编号是0C,即0C+52620D=526219,那么该地址存放的策略类型就是对应该兵种的,下面再测试策略类型是否符合就可以进入伤害加成计算了,这方法还是较好理解的....................
空白位置查找:
对于初学者,我个人认为是直接增加一区域段来自由自在的写代码最合适不过,不用去努力找也不用考虑位置不够和原版的某些函数可能存在冲突,例如:就像上面函数就需要一些空白地址来存放兵种所指的「伤害加成数值」了,你若误以为此位置是空白位置的那肯定就会造成上列函数的计算错误的
-----------------------------------------------------------------不华丽的分割线--------------------------------------------------------------------------------
*******************装备了带有特效的装备施放策略命中率+20%自身最大生命值**************
跟命中率有关,自然要找策略命中率(同样有物理和策略区分,别找错了)函数动手啦(本帖使用的是6.0EXE的函数0043B6F3),原始地址自己找个合适的跳出吧,下面代码就是怎么做带有特效号的装备或兵种的判断
空白位置:
005260E3 6A 01 PUSH 1 ; (是否要读取DATA效果值,0要,1不要)
005260E5 6A 01 PUSH 1 ; (效果值是否叠加)
005260E7 6A 62 PUSH 62 ; (宝物特效号)
005260E9 6A 64 PUSH 64 ; (兵种特效号)与宝物特效号完全不同的而且根据不同引擎拥有,这点要注意,我们不需要判断兵种特效,所以给个没有用的特效号
005260EE 8B4D DC MOV ECX,DWORD PTR SS:[EBP-24] ; [EBP-24]存放了施放策略的武将DATA内存
005260F1 E8 A292FAFF CALL Ekd5_R2.004CF398 ; 一同输入004CF398该函数,做装备、效果值测试
005260F6 85C0 TEST EAX,EAX ; 判断上面函数中所有是否有符合的测试项
005260F8 - 0F84 A458F1FF JE Ekd5_R2.0043B9A2 ; JE表示EAX=0(没有装备或发生)时跳转,JNZ则相反 godtype的教程贴详细去看
005260FE 8B4D DC MOV ECX,DWORD PTR SS:[EBP-24] ; 设置ECX=[EBP-24] [EBP-24]存放了施放策略的武将DATA内存
00526101 66:8B41 1C MOV AX,WORD PTR DS:[ECX+1C] ; 通过武将data内存来获取其最大生命值(data内存只能获取生命最大值,当前生命值则战场内存可以获得),godtype教程贴内容了
00526105 66:50 PUSH AX ; 获取到的数值作为参数2直接输入下列函数
00526107 6A 14 PUSH 14 ; 将要加成的数值作为参数1输入
00526109 E8 8695FAFF CALL Ekd5_R2.004CF694 ; 计算结果——20%参数2的数值输出到EAX
0052610E 0145 F0 ADD DWORD PTR SS:[EBP-10],EAX ; [EBP-10]存放了策略命中率的数值,将计算出来的结果+进去
00526111 - E9 8C58F1FF JMP Ekd5_R2.0043B9A2 ; 无条件跳回去
小解:
带有特效号的装备或兵种的判断只需要两个主数据,就是找出存放了施放策略的武将DATA内存(要被攻击的武将受此效果就找被攻击的武将DATA内存,战场内存也可以,不过要进行转变为DATA内存才能进行004CF398函数的运作),怎么转变就看godtype得教程贴,然后就看上面的写法,一目了然,这部分没什么好说的
-----------------------------------------------------------------不华丽的分割线--------------------------------------------------------------------------------
关于我们需要的数据(例如上面的武将战场内存啊、武将DATA内存)一时间怎么找都找不到,经验又不足,该怎么办呢?看两句代码:
005263A1 36:8B0D F4274900 MOV ECX,DWORD PTR SS:[4927F4] ; 4927F0存放的是物理战斗信息地址(基础贴内容) 4927F0+4即直接获取发动攻击的武将的Data编 号
005263A8 3E:894D FC MOV DWORD PTR DS:[EBP-4],ECX ; 用暂存空间[EBP-4]来存放获取到的发动攻击武将的Data编号
这两句代码就是教你当你怎么都找不着你需要的某些数据时,可直接用第一句代码所写的MOV ECX,DWORD PTR SS:[4927F0+X] 来直接获取数据,不过比较占字节,而且godtype的教程贴有看的话都知道不是什么数据都可以通过4927F0来获得,有些需要换算才能得出另一个数据,第二句是将获得的数据保存下来,注意暂存空间我上面说了要查清楚该空间是否有存放其它后续代码调用的重要数据才可用它哦
未完待续..........
[ 本帖最后由 a117398902 于 2015-7-5 11:23 编辑 ]
|
|
|
|