qweytr_1 发表于 2019-3-31 15:26

[终于明白了祖传优化的意义][肯读汇编代码的萌新来辣][CT脚本(抛砖引玉砸人版)][请版主【不要】设置回复可见][请大家积极参与讨论,不要灌水,谢谢]

本帖最后由 qweytr_1 于 2019-4-3 13:41 编辑

4c59fbb8

在开始之前,我希望解释一下我失败的经过,这款游戏真的不愧是祖传优化……
用imul计算整除除法我也是头一回见(原理,a/b=a*,而mod 18446744073709551616是可以预先算出来存起来的,于是神奇的imul成功地将0x669C/0x21转化成了0x669C*0xF83E0F83E0F83E1)
以及,4c59fbb8是我追码时候做的esp记录,后来发现,手工记录显然不如CE记录有效,而x86的辣鸡结构不能直接内存对拷任你本事通天大都要过一遍寄存器——这就给CE的trace功能一个很强大的支持,你可以先trace,保存trace文本,然后用notepad++之类的工具打开,进行搜索

首先谢过fearlessrevolution.com的CT表,以及论坛@pad123 的无私汉化,没这些,我大概只能从头开始啃了

闲话少说,开始正文……

首先放一个“体验极差”:
81 FA 3F 42 0F 00 7E 4A C7 01 3F 42 0F 00
改成
81 FA 3F 42 0F 00 90 90 C7 01 3F 42 0F 00

nop掉一个jle,如果不出意外,四大源素会变成999999
仔细阅读这段代码,不难作出
物品不减:
{ Game   : Nelke_and_the_Legendary_Alchemists.exe
Version:
Date   : 2019-04-03
Author : Neutron

This script does blah blah blah
}

define(address,"Nelke_and_the_Legendary_Alchemists.exe"+247990)
define(bytes,83 FA 03 77 20 48 63 C2 8B 14 81 41 03 D0)



assert(address,bytes)
alloc(newmem,$1000,"Nelke_and_the_Legendary_Alchemists.exe"+247990)

label(code)
label(return)

newmem:

code:
mov eax,0
cmp r8d,eax
cmovl r8d,eax
cmp edx,03
ja Nelke_and_the_Legendary_Alchemists.exe+2479B5
jmp return

address:
jmp newmem
return:



address:
db bytes
// cmp edx,03
// ja Nelke_and_the_Legendary_Alchemists.exe+2479B5

dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "Nelke_and_the_Legendary_Alchemists.exe"+247990

"Nelke_and_the_Legendary_Alchemists.exe"+247982: 5F                  -pop rdi
"Nelke_and_the_Legendary_Alchemists.exe"+247983: E9 98 42 00 00      -jmp Nelke_and_the_Legendary_Alchemists.exe+24BC20
"Nelke_and_the_Legendary_Alchemists.exe"+247988: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+247989: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798A: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798B: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798C: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798D: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798E: CC                  -int 3
"Nelke_and_the_Legendary_Alchemists.exe"+24798F: CC                  -int 3
// ---------- INJECTING HERE ----------
"Nelke_and_the_Legendary_Alchemists.exe"+247990: 83 FA 03            -cmp edx,03
"Nelke_and_the_Legendary_Alchemists.exe"+247993: 77 20               -ja Nelke_and_the_Legendary_Alchemists.exe+2479B5
// ---------- DONE INJECTING----------
"Nelke_and_the_Legendary_Alchemists.exe"+247995: 48 63 C2            -movsxdrax,edx
"Nelke_and_the_Legendary_Alchemists.exe"+247998: 8B 14 81            -mov edx,
"Nelke_and_the_Legendary_Alchemists.exe"+24799B: 41 03 D0            -add edx,r8d
"Nelke_and_the_Legendary_Alchemists.exe"+24799E: 48 8D 0C 81         -lea rcx,
"Nelke_and_the_Legendary_Alchemists.exe"+2479A2: 78 54               -js Nelke_and_the_Legendary_Alchemists.exe+2479F8
"Nelke_and_the_Legendary_Alchemists.exe"+2479A4: 89 11               -mov ,edx
"Nelke_and_the_Legendary_Alchemists.exe"+2479A6: 81 FA 3F 42 0F 00   -cmp edx,000F423F
"Nelke_and_the_Legendary_Alchemists.exe"+2479AC: 7E 4A               -jle Nelke_and_the_Legendary_Alchemists.exe+2479F8
"Nelke_and_the_Legendary_Alchemists.exe"+2479AE: C7 01 3F 42 0F 00   -mov ,000F423F
"Nelke_and_the_Legendary_Alchemists.exe"+2479B4: C3                  -ret
}




这个CT表的目标是,提升临时帮工们的素质,每次只产出十几个也太无力了些,明明头像是辣么萌的妹纸,分明萌是第一生产力啊~
为了生产力,我们首先需要找到生产力的算法

尝试以通草产量搜索,未果,不得以,找出以前写CE炼金的精神,开始啃汇编码

注意到产量与适性应是正相关的,而本作适性又与基础数值挂钩,于是以基础数值为基础,开始读代码
于是,我读到了祖传优化……比如imul做除法,又比如,长长一大段不知所云,再比如,栈内元素从来不用,rsp常常括号内挂着+30标志……也没谁了

追码有一个特别技巧,右键,跟踪,然后让CE生成一串跟踪堆栈之类的东西,而后不要用CE,直接存起来。文本编辑器打开保存文件之后Ctrl+F比CE好用10000倍……

贴一下计算公式
这是一个从地址09BA结尾的程序里面读出来的,某次追码得到的花园产量计算公式:

xmm7=(=0)
xmm6=某个奇怪的数字/100


xmm2=(=1.00)
xmm2=xmm2*xmm7
xmm7=(=0)
xmm1=(double)(edi(=00000007))
xmm2=xmm2*xmm6
xmm0=(double)ebx
xmm2=xmm2+xmm0
xmm3=(double)eax
xmm2=xmm2*xmm1
xmm3=xmm3+xmm2


最后,计算结果被存到了esi中,也就是,如果能改掉esi的值,emmm...
有爱自取整合随意,顺手抄上了GPL v3的license,反正大家也不可能用这个脚本卖钱嘛……
如果准备整合的话,记得在整合之后的脚本注明GPL许可(这是个人感觉GPL最好的一点,现在真心觉得开源程序都是良心程序)


{ Game   : Nelke_and_the_Legendary_Alchemists.exe
Version: (-1.#INF)
Date   : 2019-03-31
Author : 云中子3529

This script is free script: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program comes with ABSOLUTELY NO WARRANTY;

本来我理应可以写一个非常漂亮的aobscan脚本,然而我的CE坏了,aobscan激活之后没有反应(我不确定是不是我写错了),于是我用了这种注入方式
倘若今后版本升级,请手动aobscan一下define的66 0F...这串字节,并更新下面的那一个define,如果660F...这串字符搜不到,请把“可写入”的对勾取消掉
脚本并没有实现最开始那种单纯的“增加帮工产量”的目的——测试发现帮工产量是人工产量的一半,没找到也懒得继续找帮工产量如何修改了
就这样吧
我在64那里用英语注释了一句,如果你们觉得产量100偏小,你们可以把这个数字改成C8或者#200
开心就好。
}

define(address,"Nelke_and_the_Legendary_Alchemists.exe"+25E5B2)
define(bytes,66 0F 6E C3 0F 5B C0 0F 5B C9 F3 0F 58 D0 66 0F 6E D8 0F 5B DB F3 0F 59 D1 F3 0F 58 DA F3 0F 2C F3)



assert(address,bytes)
alloc(newmem,$1000,"Nelke_and_the_Legendary_Alchemists.exe"+25E5B2)

label(code)
label(return)

newmem:

code:
db bytes
mov rax 64//Here, you could change 0x64(=100) to any number you want.
cmp esi eax
cmovl esi eax
jmp return

address:
jmp newmem
db 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
return:



address:
db bytes
// movd xmm0,ebx
// cvtdq2ps xmm0,xmm0

dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: "Nelke_and_the_Legendary_Alchemists.exe"+25E5B2

"Nelke_and_the_Legendary_Alchemists.exe"+25E588: E8 B3 9A FE FF         -call Nelke_and_the_Legendary_Alchemists.exe+248040
"Nelke_and_the_Legendary_Alchemists.exe"+25E58D: 8B C8                  -mov ecx,eax
"Nelke_and_the_Legendary_Alchemists.exe"+25E58F: E8 BC 0B 00 00         -call Nelke_and_the_Legendary_Alchemists.exe+25F150
"Nelke_and_the_Legendary_Alchemists.exe"+25E594: F3 0F 10 54 24 78      -movss xmm2,
"Nelke_and_the_Legendary_Alchemists.exe"+25E59A: F3 0F 59 D7            -mulss xmm2,xmm7
"Nelke_and_the_Legendary_Alchemists.exe"+25E59E: 0F 28 7C 24 20         -movaps xmm7,
"Nelke_and_the_Legendary_Alchemists.exe"+25E5A3: 66 0F 6E CF            -movd xmm1,edi
"Nelke_and_the_Legendary_Alchemists.exe"+25E5A7: 33 FF                  -xor edi,edi
"Nelke_and_the_Legendary_Alchemists.exe"+25E5A9: F3 0F 59 D6            -mulss xmm2,xmm6
"Nelke_and_the_Legendary_Alchemists.exe"+25E5AD: 0F 28 74 24 30         -movaps xmm6,
// ---------- INJECTING HERE ----------
"Nelke_and_the_Legendary_Alchemists.exe"+25E5B2: 66 0F 6E C3            -movd xmm0,ebx
"Nelke_and_the_Legendary_Alchemists.exe"+25E5B6: 0F 5B C0               -cvtdq2ps xmm0,xmm0
"Nelke_and_the_Legendary_Alchemists.exe"+25E5B9: 0F 5B C9               -cvtdq2ps xmm1,xmm1
"Nelke_and_the_Legendary_Alchemists.exe"+25E5BC: F3 0F 58 D0            -addss xmm2,xmm0
"Nelke_and_the_Legendary_Alchemists.exe"+25E5C0: 66 0F 6E D8            -movd xmm3,eax
"Nelke_and_the_Legendary_Alchemists.exe"+25E5C4: 0F 5B DB               -cvtdq2ps xmm3,xmm3
"Nelke_and_the_Legendary_Alchemists.exe"+25E5C7: F3 0F 59 D1            -mulss xmm2,xmm1
"Nelke_and_the_Legendary_Alchemists.exe"+25E5CB: F3 0F 58 DA            -addss xmm3,xmm2
"Nelke_and_the_Legendary_Alchemists.exe"+25E5CF: F3 0F 2C F3            -cvttss2si esi,xmm3
// ---------- DONE INJECTING----------
"Nelke_and_the_Legendary_Alchemists.exe"+25E5D3: 40 38 7C 24 60         -cmp ,dil
"Nelke_and_the_Legendary_Alchemists.exe"+25E5D8: 74 33                  -je Nelke_and_the_Legendary_Alchemists.exe+25E60D
"Nelke_and_the_Legendary_Alchemists.exe"+25E5DA: 8B DF                  -mov ebx,edi
}
另外,“翻译”了一下任务选项,找到了不少东西的含义,虽然还没胆子修主线任务以及加人口的国策任务,也没找到哪里能改任务种类,不过只要你把“需要几个才能完成任务”跟“已完成数量”都锁定成相同的数值,基本上任务是可以自动完成的
      <CheatEntry>
          <ID>182</ID>
          <Description>"Highlighted Request"</Description>
          <Options moHideChildren="1"/>
          <LastState Activated="1"/>
          <VariableType>Auto Assembler Script</VariableType>
          <AssemblerScript>{ Game   : Nelke_and_the_Legendary_Alchemists.exe
Version:
Date   : 2019-03-29
Author : Zach

This script does blah blah blah
}




aobscanmodule(Request_List,Nelke_and_the_Legendary_Alchemists.exe,41 0F BF 56 06) // should be unique
alloc(newmem,$1000,Request_List)
globalalloc(RequestList,4)
label(code)
label(return)

newmem:
mov ,r14
code:
movsx edx,word ptr
jmp return

Request_List:
jmp newmem
return:
registersymbol(Request_List)



Request_List:
db 41 0F BF 56 06

unregistersymbol(Request_List)
dealloc(newmem)
dealloc(Request_List)
{
// ORIGINAL CODE - INJECTION POINT: "Nelke_and_the_Legendary_Alchemists.exe"+1DA769

"Nelke_and_the_Legendary_Alchemists.exe"+1DA73D: 0F 84 8D 07 00 00      -je Nelke_and_the_Legendary_Alchemists.exe+1DAED0
"Nelke_and_the_Legendary_Alchemists.exe"+1DA743: 48 8B 0D 16 5B D9 00   -mov rcx,
"Nelke_and_the_Legendary_Alchemists.exe"+1DA74A: 48 85 C9               -test rcx,rcx
"Nelke_and_the_Legendary_Alchemists.exe"+1DA74D: 75 0C                  -jne Nelke_and_the_Legendary_Alchemists.exe+1DA75B
"Nelke_and_the_Legendary_Alchemists.exe"+1DA74F: E8 FC 50 EA FF         -call Nelke_and_the_Legendary_Alchemists.exe+7F850
"Nelke_and_the_Legendary_Alchemists.exe"+1DA754: 48 8B 0D 05 5B D9 00   -mov rcx,
"Nelke_and_the_Legendary_Alchemists.exe"+1DA75B: 8B D7                  -mov edx,edi
"Nelke_and_the_Legendary_Alchemists.exe"+1DA75D: E8 BE 51 EA FF         -call Nelke_and_the_Legendary_Alchemists.exe+7F920
"Nelke_and_the_Legendary_Alchemists.exe"+1DA762: 4C 8B E8               -mov r13,rax
"Nelke_and_the_Legendary_Alchemists.exe"+1DA765: 0F BE 58 05            -movsx ebx,byte ptr
// ---------- INJECTING HERE ----------
"Nelke_and_the_Legendary_Alchemists.exe"+1DA769: 41 0F BF 56 06         -movsx edx,word ptr
// ---------- DONE INJECTING----------
"Nelke_and_the_Legendary_Alchemists.exe"+1DA76E: 45 33 C0               -xor r8d,r8d
"Nelke_and_the_Legendary_Alchemists.exe"+1DA771: 48 8B 4E 10            -mov rcx,
"Nelke_and_the_Legendary_Alchemists.exe"+1DA775: E8 96 CA 26 00         -call Nelke_and_the_Legendary_Alchemists.exe+447210
"Nelke_and_the_Legendary_Alchemists.exe"+1DA77A: 41 0F BF 56 04         -movsx edx,word ptr
"Nelke_and_the_Legendary_Alchemists.exe"+1DA77F: 45 33 C0               -xor r8d,r8d
"Nelke_and_the_Legendary_Alchemists.exe"+1DA782: 48 8B 4E 20            -mov rcx,
"Nelke_and_the_Legendary_Alchemists.exe"+1DA786: E8 85 CA 26 00         -call Nelke_and_the_Legendary_Alchemists.exe+447210
"Nelke_and_the_Legendary_Alchemists.exe"+1DA78B: 41 0F BF 4E 06         -movsx ecx,word ptr
"Nelke_and_the_Legendary_Alchemists.exe"+1DA790: 66 0F 6E C9            -movd xmm1,ecx
"Nelke_and_the_Legendary_Alchemists.exe"+1DA794: 0F 5B C9               -cvtdq2ps xmm1,xmm1
}
</AssemblerScript>
          <CheatEntries>
            <CheatEntry>
            <ID>183</ID>
            <Description>"基址"</Description>
            <VariableType>2 Bytes</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>0</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>192</ID>
            <Description>"讨伐/贩卖/生产 对象编号"</Description>
            <VariableType>2 Bytes</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>2</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>191</ID>
            <Description>"需要几个才能完成任务"</Description>
            <VariableType>Byte</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>4</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>190</ID>
            <Description>"已经完成的数量"</Description>
            <VariableType>Byte</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>6</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>194</ID>
            <Description>"发起人编号"</Description>
            <VariableType>Byte</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>8</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>195</ID>
            <Description>"奖励金钱"</Description>
            <VariableType>2 Bytes</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>c</Offset>
            </Offsets>
            </CheatEntry>
            <CheatEntry>
            <ID>193</ID>
            <Description>"剩余回合数"</Description>
            <VariableType>2 Bytes</VariableType>
            <Address>RequestList</Address>
            <Offsets>
                <Offset>10</Offset>
            </Offsets>
            </CheatEntry>
          </CheatEntries>
      </CheatEntry>
      </CheatEntries>
    </CheatEntry>

页: [1]
查看完整版本: [终于明白了祖传优化的意义][肯读汇编代码的萌新来辣][CT脚本(抛砖引玉砸人版)][请版主【不要】设置回复可见][请大家积极参与讨论,不要灌水,谢谢]