CEAA完整中文 教程.docx
《CEAA完整中文 教程.docx》由会员分享,可在线阅读,更多相关《CEAA完整中文 教程.docx(27页珍藏版)》请在冰豆网上搜索。
CEAA完整中文教程
CEAA教程:
AVeryInDepthTutorialonAutoAssembler精华
此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。
本人英语渣,出现误译及错别字请多包涵。
原文地址:
http:
//forum.cheatengine.org/viewtopic.php?
t=95363
------------------------------
内容表
------------------------------
I.介绍
II.寄存器
II.a32位寄存器
II.b16位寄存器
III.指令
III.aJMP
III.bMOV
III.cPush/Pop+TheStack
III.dalloc/label/registersymbol
III.eCallandRet
III.f其他
IV.ArrayofBytes
V.结尾
VI.人员名单/致谢词
额外内容:
写一个脚本
------------------------------
I.介绍
------------------------------
'哟,我猜你在读这个是因为下面两件事中的一个。
1)你正在试图学习自动汇编(我不会叫你菜鸟,因为每个人都是从哪里开始的,对吧=))
or
2)你想测试你的自动汇编知识(作为扩展)。
那么,如果你是前者,那就慢慢的体会好每个部分,并且在继续进行前确认自己已经明白了这章。
Dark Bytewrote:
大多数人都认为AA很难,其实它可容易了。
来自CE作者自己的话
如果是后者,那我不会给你提任何的建议,即使我想帮忙。
如果你发现有什么错了,或者含糊或者认为我可以做的更好,请告诉我。
我一直处于自我学习的状态!
等等!
别问,我知道你在想什么。
You wrote:
为什么我非要听一个还在学习的人的话?
好,我来告诉你,我的朋友。
即使我仍然在学习,我了解AA,并且我认为与你分享知识是一件很棒的事。
=)
Edit:
这个是很久以前写的,但是现在我学到了很多,并且已经重新检查了。
现在,让我们投身入奇幻的电脑世界
------------------------------
II.寄存器
------------------------------
这些也许你已经在一些脚本中看到过,它们被非常广泛的使用。
有两种寄存器被使用,接下来来进行讲解。
---------------
II.a32Bit
---------------
首先,我将解释每个寄存器是如何得到它们的名字的,这会帮助你记住它们哪个是哪个。
首先,以E开头(如果你注意了下面,你会发现所有的寄存器都是以E开头的)它告诉你这个寄存器是32位寄存器。
而A,B,C,D的含义你看完描述就能明显得体会到了。
像SI,DI,BP,SP,IP也是一样。
在EAX,EBX,ECX,EDX后面的X,他简单的表示已经没有更多的字母了。
有点像一个NOP命令(之后你将读到)。
如果你注意了,你会发现每个32位寄存器都是3个字母。
EAX:
累加器(Acculmulatorregister)。
能够用来当存储器
EBX:
从前,它是个基础寄存器,但现在只是个闲着的存储器
ECX:
计数器(Countingregister)。
也能用来当存储器
EDX:
数据寄存器(Dataregister)。
跟之前三个一样,能用来当存储器。
ESI:
源址变址寄存器(SourceIndexregister)。
是字符串形式的指针变量,但你现在还不用担心那部分。
能够用来当存储器。
EDI:
目的变址寄存器(DestinyIndexregister)。
又一次,能够当作存储器,并且是个字符串形式的指针变量,但别担心。
EBP:
机制指针寄存器(BasePointerregister)。
是用来临时存储ESP,当然也可以像常规的存储器那样使用。
ESP:
原址指针寄存器(SourcePointerregister)。
它在堆栈里指向寄存器和地址(这个内容待会再说)。
EIP:
指令指针寄存器(InstructionPointerregister)。
错误的使用会使你正在试图修改的程序崩溃。
---------------
II.b16Bit
---------------
16位寄存器和32位寄存器很相似,他们间有两个区别。
一是,32位寄存器名字是三个字母,而16位寄存器是两个字母。
还有一件事就是16位寄存器比32位寄存器多但别担心。
16位寄存器我们一般都用不上。
AX:
参照EAX
BX:
参照EBX
CX:
参照ECX
DX:
参照EDX
SI:
参照ESI
DI:
参照EDI
BP:
参照EBP
SP:
参照ESP
IP:
参照EIP
---------------
关于寄存器的内容还很多。
如果你想学习更多关于寄存器的只是,那就去拜Google大神吧。
对于绝大多数的学习者来说求知欲都是很重要的。
------------------------------
III.命令
------------------------------
当今,什么语言没有它自己的函数和命令呢?
与英文相比,命令像个单词,而操作代码像个句子。
操作代码并不难,比如:
Code:
jmp00123EAA
关于操作代码你应该知道两点。
首先,在操作码里,一般都会有个地址或者寄存器,以及一个显而易见的命令。
地址是Hex形式的,是Hexadecimal的缩写。
Hexadecimal是16进制数。
就如同10进制那样。
按照这种思路想一想。
如同上面提到的那样,我们一般使用十进制。
这就意味着我们在一个列里不能有“10”,因为它占了两个地方。
而16进制,10至15都可以放在一个列里头。
但是你会发现,“10”并没有出现在列里头。
先冷静,这是因为在Hex进制里,10是用A表示的,而11是用B,直到15是F。
再往后,它就是10,然后11,直到1F,如果超过了20(十进制)就得从15(十六进制)往后算。
有个简单的转换方法就是用操作系统自带的计算器,这里不赘述了。
还有,每一个地址都有它的操作码和字节码。
这个字节数就是代表操作码是什么,每一个命令都一一对应已经定义好的字节码。
我知道那些常用函数的字节码是什么,如果你想知道那些字节码的话,你还是指望别人吧,推荐去拜Google大神=)
最后,想注释很方便。
要注释的话,就把"//"放在命令后边或某块空处,然后打上你想打的。
如果你不打"//",那电脑就会以为你在打命令呢。
现在,让我们来了解每个命令都是干啥的。
---------------
III.aJMP
---------------
JMP命令是最常使用的命令之一(就如同MOV那样,接下来会讲)。
也许你在操作码和脚本里看到的"JMP"不像"MOV"那么多,那是因为JMP命令有很多变种。
下面就是列表。
JMP:
始终跳转(Alwaysjumpto)
JE/JZ:
相等则跳转(Jumptoifequal)
JNE/JNZ:
不等则跳转(Jumptoifnotequal)
JA:
无符号大于则跳转(JumptoifAbove)
JG:
有符号大于则跳转(JumptoifGreater)
JNA:
无符号不大于则跳转(JumptoifnotAbove)
JNG:
有符号不大于则跳转(JumptoifnotGreater)
JB:
无符号小于则跳转(JumptoifBelow)
JL:
有符号小于则跳转(JumptoifLower)
JNB:
无符号不小于则跳转(JumptoifnotBelow)
JNL:
有符号不小于则跳转(JumptoifnotLower)
JAE:
无符号大于等于则跳转(JumptoifAboveorEqual)
JGE:
有符号大于等于则跳转(JumptoifGreaterorEqual)
JNAE:
无符号不大于等于则跳转(JumptoifnotAboveorEqual(即JB))
JNGE:
有符号不大于等于则跳转(JumptoifnotgreaterthanorEqual(即JL))
现在你大致了解了,应该有些疑惑。
"Jumptoifgreater"或者JG都是条件跳转。
条件跳转都如同它们名字所描述的那样,会在条件成立的情况下跳转。
通常,都会有CMP或者其他的比较函数在上面,这个待会再提。
以上大抵就是JMP的故事。
---------------
III.bMOV
---------------
前文已经提过,MOV命令是最被广泛实用的命令,因为它是那么给力。
下面就是MOV的例子:
Code:
moveax,ebx
这个的意思是"把ebx里存的地址放到eax里"。
注意在两个寄存器之间还有个逗号,而不是空格。
最开始这可能有些令人费解,但是它真的很容易,下面来好好解释一下。
"Mov"是"move"的意思。
寄存器自身表示"这个寄存器里存的地址"。
基本上来说,"把ebx里存的地址放到eax的地址里面去",这会把eax之前的值覆盖并彻底消灭掉。
=D你可以通过这个方法复制ebx并把它粘贴到eax里。
另一种Mov命令。
Code:
moveax,[ebx]
这个的意思是把ebx里面的值存到eax所存的地址里,很简单,把寄存器或者地址用[]那么一括,就表示寄存器或者地址的值了。
下面这段代码什么效果都没有。
Code:
mov[eax],[ebx]
没效果,上面的代码啥用没有。
你不能!
你不能直接把一个值存在另一个值里面。
你可以间接得先把值存在其他的东西里;)参考下面的代码。
Code:
pusheax //先让eax入栈—这个待会解释
moveax,[0100200A] //把值0100200A存到eax里
mov[ebx],eax //把(值0100200A)存到ebx的值里面
popeax //然后让eax出栈,这个也待会讲
---------------
III.cPushandPop+TheStack
---------------
你已经看了上面的Push和Pop命令的用法。
等等!
我是尤里!
我能读你的思想!
You wrote:
那个push和pop都是干啥的?
还有啥是stack?
好,你读了前文,在"Push"之后,我是这么注释的。
Code:
//Pusheaxontothestack(让eax入栈)
这个基本上就是把eax存到堆栈里。
而popeax基本上就是把eax从堆栈中清除。
CEF的Skyone写了一个非常非常好的关于堆栈的解释,我甚至无法容忍自己不让你像我那样获得对此学习的快乐;)
Skyone wrote:
堆栈是用来存放可变的空白的值。
它就如同:
你有用来做作业的一张纸,但是之后你的朋友打电话叫你给Phil打电话,他的电话是555-6405。
你慌了,没地方记啊,所以你把它写在了作业本上了。
之后你撂下电话,就可以把Phil's电话写在电话薄上了。
在写完号码之后,你就把号码从作业本用橡皮擦掉了,然后打电话给Phil,并且继续做作业。
把值pushtostack (入栈)就是"在作业本上写下Phil的电话号码"而pop就是"把电话号码录入到电话薄上, 然后再从作业本上擦掉。
"
继续...
---------------
III.dAlloc/Label/RegisterSymbol
---------------
我一般喜欢用两种方法来区分AutoAssembler脚本
1)简单的地址改变
如同下面的简单代码:
Code:
[enable]
00ABC123:
moveax,ebx
[disable]
00ABC123:
movebx,eax
这是在改变地址00ABC123里面的操作码。
但是也有非常复杂的脚本,就如同dICE或pID00的脚本。
(我不会在这里介绍,因为那真的没什么必要去学)
在非常复杂的脚本当中,你会在最顶上看到某些函数,(注意,我并没有经常使用)在一个复杂的脚本当中通常会出现"alloc","label"函数,有时还会出现"registersymbol"。
````````````
Label
````````````
我认为"label"函数是三个函数中最有重要的。
他能够允许你用在脚本中使用"label"定义的变量,如同下面这样。
(摸丸:
label用于定义用于跳转的标签)
Code:
label(Continue)
AutoAssembler:
moveax,02
cmpeax,03
jneContinue
jeSayWhat
Continue:
//...
//...
SayWhat:
jmp0//insta-crash!
=D
首先应该注意此脚本的一些问题,这个脚本没有"alloc"函数,之后我就讲
接着,如果你明白为什么程序执行了对应jne的label,那你做得不错。
注意所有的labels(跳转标签)都在我的脚本中定义了,否则他们不会编译。
````````````
Alloc
````````````
现在开始讲解"alloc"函数。
它是用来按照你的设想来分配X量的内存的函数(hence,alloc,allocate)。
这些内存不是那些用过的,而是那些你在运行程序中可以覆盖的没有被使用的内存。
就如同我说的,它会分配X量的内存。
X是个字节数的变量。
1024bytes,或者1kb(kilobyte)一般就足够你用了。
现在我们了解了alloc函数,让我来演示下如何来使用它,并利用之前所学到的一切。
(摸丸:
按照尺寸划分一块内存,并给它起个名字)
Code:
alloc(AutoAssembler,1024)
alloc(SayWhat,1024)
label(Continue)
AutoAssembler:
moveax,02
cmpeax,03
jneContinue
jeSayWhat
Continue:
//...
SayWhat:
jmp0
注意为什么我不这么做
Code:
label(AutoAssembler)
或者
Code:
label(SayWhat)
因为当用alloc划分出内存的时候,他们在CheatEngine的词典中就自动得已经定义好了,便于我们调用。
````````````
RegisterSymbol
````````````
最后,函数"registersymbol"。
它可以添加你CheatTable中你注册的标志。
注意,你始终需要去为它分配内存。
让我们在我们的脚本中试一试。
Code:
alloc(AutoAssembler,1024)
alloc(SayWhat,1024)
alloc(WooHoo,1024)
label(Continue)
registersymbol(WooHoo)
AutoAssembler:
moveax,02
cmpeax,03
jneContinue
jeSayWhat
Continue:
cmpeax,[WooHoo]
SayWhat:
jmp0
````````````
Counterparts
````````````
现在,让我们来继续最后的一小段:
thecounterparts。
有两种使用AutoAssemblerscript的方法。
第一种,你可以注入一些东西。
第二种,你可以把它添加到CheatTable中。
如果你决定要把它填到cheattable(当今大多数脚本都是如此),那你的代码需要enable和disable两部分代码,如下。
Code:
[ENABLE]
alloc(AutoAssembler,1024)
alloc(SayWhat,1024)
alloc(WooHoo,1024)
label(Continue)
registersymbol(WooHoo)
AutoAssembler:
moveax,02
cmpeax,03
jneContinue
jeSayWhat
Continue:
cmpeax,[WooHoo]
[DISABLE]
现在,你会注意到,Disable部分什么也没有,不过一会就不会了!
;)
你在Disable部分中所想达到的就是:
撤销你在Enable部分中所做的。
如何撤销内存分配和注册中的标记。
现在,我感觉有个问题要来了
You wrote:
你是怎么办的?
简单来说,我的朋友。
通过dealloc和unregistersymbol函数!
哦,等等又有问题要来了。
"那label怎么办?
"你问?
嗯,没必要去撤销label。
=)这意味着在Disable部分中,你大概要从开始那段中扔掉一半的代码!
=)
那我们为什么不把学的加进脚本里呢?
Code:
[ENABLE]
alloc(AutoAssembler,1024)
alloc(SayWhat,1024)
alloc(WooHoo,1024)
label(Continue)
registersymbol(WooHoo)
AutoAssembler:
moveax,02
cmpeax,03
jneContinue
jeSayWhat
Continue:
cmpeax,[WooHoo]
[DISABLE]
dealloc(AutoAssembler)
dealloc(SayWhat)
dealloc(WooHoo)
unregistersymbol(WooHoo)
哦这儿...还有个问题。
You wrote:
为什么你不用那个"1024"了?
因为计算机知道你分配的AutoAssembler是大小为1024bytes的(我们就把它当个例子试一试吧),你只是需要deallocAutoAssembler,它就知道应该取消分配AutoAssembler的全部1024bytes了。
(很抱歉,解释的有些迷糊)
---------------
III.eCallandRet
---------------
Call函数和JMP函数很相似。
唯一的不同是Call有个返回到之前代码的功能。
这个简单例子利用了下面的两个函数。
Code:
mov[0100579C],10 //把地址的值改成10
cmp[0100579C],0 //把它和0进行比较
callNameGoesHere //调用或者跳转到NameGoesHere
jmp01002FF5
NameGoesHere:
dec[0100579C] //地址的值减1
cmp[0100579C],0 //跟0进行比较
jneNameGoesHere //如果不想等就返回到
//NameGoesHere的开始,否则继续
ret //返回到之前,刚好是调用(call)函数之后
---------------
III.fOthers
---------------
现在,很显然,在AutoAssembler还有很多很多其他的函数,不然它就是个很局限的语言。
我会继续尽我所能解释更多的函数。
(哦,老兄...)
`````
Nop
`````
Nop:
这个我之前提过。
它意味着"无操作",大体上它可以抵消它之前的代码。
`````
Inc/Dec
`````
Inc:
加一。
用于给寄存器或地址加一。
用法如下。
Code:
inceax
Dec:
减一,跟Inc似的
`````
Add/Sub
`````
Add:
加法。
用法如下。
Code:
addeax,02//给eax加2,并且将结果保存在eax中
Sub:
减法,用法类似Add
`````
Lea
`````
这个有点让人迷糊,但还是继续吧。
看下边的脚本。
Code:
moveax,00123ABC
leaebx,[eax+DEF]
也许你分不清楚,[eax+DEF]是一个指针。
LEA把后面被指向的[eax+DEF]的地址替换给前面被指向的ebx里。
`````
And/Or/Xor
`````
好,我不知道如何清晰的说明“异或(xor)”在英文中的含义–很多网站都只是用几行字这么描述的...
Them wrote:
我估计