最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

CE AA 教程

来源:动视网 责编:小OO 时间:2025-09-30 21:02:49
文档

CE AA 教程

本帖最后由cn_zou于2011-1-813:52编辑此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。本人英语渣,出现误译及错别字请多包涵。原文地址:http://forum.cheatengine.org/viewtopic.php?t=95363------------------------------内容表------------------------------I.介绍II.寄存器II.a32位寄存器II.b16位寄存器I
推荐度:
导读本帖最后由cn_zou于2011-1-813:52编辑此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。本人英语渣,出现误译及错别字请多包涵。原文地址:http://forum.cheatengine.org/viewtopic.php?t=95363------------------------------内容表------------------------------I.介绍II.寄存器II.a32位寄存器II.b16位寄存器I
本帖最后由 cn_zou 于 2011-1-8 13:52 编辑

此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。

本人英语渣,出现误译及错别字请多包涵。

原文地址:http://forum.cheatengine.org/viewtopic.php?t=95363

------------------------------

内容表

------------------------------

I. 介绍

II. 寄存器

II.a 32位寄存器

II.b 16位寄存器

III. 指令

III.a JMP

III.b MOV

III.c Push/Pop + The Stack

III.d alloc/label/registersymbol

III.e Call and Ret

III.f 其他

IV. Array of Bytes

V. 结尾

VI. 人员名单/致谢词

额外内容: 写一个脚本

------------------------------

I. 介绍

------------------------------

'哟,我猜你在读这个是因为下面两件事中的一个。

1) 你正在试图学习自动汇编 (我不会叫你菜鸟,因为每个人都是从哪里开始的,对吧 =) )

or

2) 你想测试你的自动汇编知识 (作为扩展)。

那么,如果你是前者,那就慢慢的体会好每个部分,并且在继续进行前确认自己已经明白了这章。

Dark Byte wrote:

大多数人都认为AA很难,其实它可容易了。

来自CE作者自己的话

如果是后者,那我不会给你提任何的建议,即使我想帮忙。如果你发现有什么错了,或者含糊或者认为我可以做的更好,请告诉我。我一直处于自我学习的状态! 等等!别问,我知道你在想什么。

You wrote:

为什么我非要听一个还在学习的人的话?

好,我来告诉你,我的朋友。即使我仍然在学习,我了解AA,并且我认为与你分享知识是一件很棒的事。 =)

Edit: 这个是很久以前写的,但是现在我学到了很多,并且已经重新检查了。

现在,让我们投身入奇幻的电脑世界

------------------------------

II. 寄存器

------------------------------

这些也许你已经在一些脚本中看到过,它们被非常广泛的使用。有两种寄存器被使用,接下来来进行讲解。

---------------

II.a 32 Bit

---------------

首先,我将解释每个寄存器是如何得到它们的名字的,这会帮助你记住它们哪个是哪个。首先,以E开头 (如果你注意了下面,你会发现所有的寄存器都是以E开头的) 它告诉你这个寄存器是32位寄存器。而A,B,C,D的含义你看完描述就能明显得体会到了。像SI, DI, BP,SP,IP也是一样。在 EAX, EBX, ECX, EDX后面的X,他简单的表示已经没有更多的字母了。有点像一个 NOP 命令 (之后你将读到)。如果你注意了,你会发现每个32位寄存器都是3个字母。

EAX: 累加器(Acculmulator register)。能够用来当存储器

EBX: 从前, 它是个基础寄存器,但现在只是个闲着的存储器

ECX: 计数器(Cou

nting register)。也能用来当存储器

EDX: 数据寄存器(Data register)。 跟之前三个一样,能用来当存储器。

ESI: 源址变址寄存器(SourceIndex register)。 是字符串形式的指针变量,但你现在还不用担心那部分。 能够用来当存储器。

EDI: 目的变址寄存器(DestinyIndex register)。又一次,能够当作存储器,并且是个字符串形式的指针变量, 但别担心。

EBP: 机制指针寄存器(Base Pointer register)。 是用来临时存储ESP, 当然也可以像常规的存储器那样使用。

ESP: 原址指针寄存器(Source Pointer register)。它在堆栈里指向寄存器和地址(这个内容待会再说)。

EIP: 指令指针寄存器(Instruction Pointer register)。 错误的使用会使你正在试图修改的程序崩溃。

---------------

II.b 16 Bit

---------------

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:

jmp 00123EAA

关于操作代码你应该知道两点。

首先, 在操作码里,一般都会有个地址或者寄存器,以及一个显而易见的命令。地址是Hex形式的,是Hexadecimal的缩写。Hexadecimal是16进制数。 就如同10进制那样。

按照这种思路想一想。如同上面提到的那样,我们一般使用十进制。这就意味着我们在一个列里不能有“10”, 因为它占了两个地方。 而16进制,10至15都可以放在一个列里头。但是你会发现,“10”并没有出现在列里头。

先冷静, 这是因为在Hex进制里,10是用A表示的,而11是用B,直到15是F。再往后,它就是10,然后11,直到1F, 如果超过了20(十进制)就得从15(十六进制)往后算。有个简单的转换方法就是用操作系统自带的计算器,这里不赘述了。

还有,每一个地址都有它的操作码和字节码。这个字节数就是代表操作码是什么, 每一个命令都一一对应已经定义好的字节码。我知道那些常用函数的字节码是什么,如果你想知道那些字节码的话,你还是指望别人吧,推荐去拜Google大神 =)

最后,想注释很方便。 要注释

的话, 就把"//"放在命令后边或某块空处,然后打上你想打的。如果你不打 "//" ,那电脑就会以为你在打命令呢。

现在,让我们来了解每个命令都是干啥的。

---------------

III.a JMP

---------------

JMP 命令是最常使用的命令之一 (就如同 MOV 那样, 接下来会讲)。 也许你在操作码和脚本里看到的"JMP" 不像"MOV" 那么多,那是因为 JMP 命令有很多变种。下面就是列表。

JMP: 始终跳转(Always jump to)

JE/JZ: 相等则跳转(Jump to if equal)

JNE/JNZ: 不等则跳转(Jump to if not equal)

JA: 无符号大于则跳转( Jump to if Above)

JG: 有符号大于则跳转(Jump to if Greater)

JNA: 无符号不大于则跳转(Jump to if not Above)

JNG: 有符号不大于则跳转(Jump to if not Greater)

JB: 无符号小于则跳转(Jump to if Below)

JL: 有符号小于则跳转(Jump to if Lower)

JNB: 无符号不小于则跳转(Jump to if not Below)

JNL: 有符号不小于则跳转(Jump to if not Lower)

JAE: 无符号大于等于则跳转(Jump to if Above or Equal)

JGE: 有符号大于等于则跳转(Jump to if Greater orEqual)

JNAE: 无符号不大于等于则跳转(Jump to if not Above orEqual (即 JB) )

JNGE: 有符号不大于等于则跳转(Jump to if not greaterthan or Equal (即JL) )

现在你大致了解了,应该有些疑惑。 "Jump to if greater"或者JG都是条件跳转。 条件跳转都如同它们名字所描述的那样,会在条件成立的情况下跳转。通常,都会有CMP或者其他的比较函数在上面,这个待会再提。以上大抵就是JMP的故事。

---------------

III.b MOV

---------------

前文已经提过, MOV 命令是最被广泛实用的命令,因为它是那么给力。 下面就是MOV的例子:

Code:

mov eax,ebx

这个的意思是 "把ebx里存的地址放到eax里"。注意在两个寄存器之间还有个逗号,而不是空格。 最开始这可能有些令人费解,但是它真的很容易,下面来好好解释一下。

"Mov"是"move"的意思。 寄存器自身表示"这个寄存器里存的地址"。 基本上来说, "把ebx里存的地址放到eax的地址里面去", 这会把eax之前的值覆盖并彻底消灭掉。=D你可以通过这个方法复制ebx并把它粘贴到eax里。

另一种Mov命令。

Code:

mov eax,[ebx]

这个的意思是把ebx里面的值存到eax所存的地址里,很简单, 把寄存器或者地址用[]那么一括,就表示寄存器或者地址的值了。

下面这段代码什么效果都没有。

Code:

mov [eax],[ebx]

没效果,上面的代码啥用没有。你不能!你不能直接把一个值存在另一个值里面。你可以间接得先把值存在其他的东西里 ;) 参考下面的代码。

Code:

push eax //先让eax入栈—这个待会解释

mov eax,[0100200A] //把值0100200A存

到eax里

mov [ebx],eax //把(值0100200A) 存到ebx的值里面

pop eax //然后让eax出栈,这个也待会讲

解释这个是为了MOV函数。继续...

本帖最后由 cn_zou 于 2011-1-8 14:20 编辑

---------------

III.c Push and Pop + The Stack

---------------

你已经看了上面的Push和Pop 命令的用法。等等!我是尤里!我能读你的思想!

You wrote:

那个push和pop都是干啥的?还有啥是stack?

好,你读了前文, 在"Push"之后,我是这么注释的。

Code:

//Push eax onto the stack (让eax入栈)

这个基本上就是把eax存到堆栈里。而pop eax 基本上就是把eax从堆栈中清除。CEF的Skyone写了一个非常非常好的关于堆栈的解释,我甚至无法容忍自己不让你像我那样获得对此学习的快乐;)

Skyone wrote:

堆栈是用来存放可变的空白的值。它就如同: 你有用来做作业的一张纸, 但是之后你的朋友打电话叫你给Phil打电话,他的电话是 555-05。 你慌了,没地方记啊,所以你把它写在了作业本上了。 之后你撂下电话, 就可以把Phil's电话写在电话薄上了。 在写完号码之后, 你就把号码从作业本用橡皮擦掉了, 然后打电话给Phil,并且继续做作业。

把值push to stack (入栈)就是 "在作业本上写下Phil的电话号码" 而pop就是 "把电话号码录入到电话薄上, 然后再从作业本上擦掉。"

继续...

---------------

III.d Alloc/Label/RegisterSymbol

---------------

我一般喜欢用两种方法来区分Auto Assembler脚本

1) 简单的地址改变

如同下面的简单代码:

Code:

[enable]

00ABC123:

mov eax,ebx

[disable]

00ABC123:

mov ebx,eax

这是在改变地址00ABC123里面的操作码。

但是也有非常复杂的脚本,就如同dICE 或 pID00的脚本。 (我不会在这里介绍, 因为那真的没什么必要去学)

在非常复杂的脚本当中,你会在最顶上看到某些函数,(注意,我并没有经常使用)在一个复杂的脚本当中通常会出现"alloc","label"函数,有时还会出现"registersymbol"。

````````````

Label

````````````

我认为"label"函数是三个函数中最有重要的。 他能够允许你用在脚本中使用"label"定义的变量,如同下面这样。 (摸丸:label用于定义用于跳转的标签)

Code:

label(Continue)

AutoAssembler:

mov eax,02

cmp eax,03

jne Continue

je SayWhat

Continue:

//...

//...

SayWhat:

jmp 0 //insta-crash! =D

首先应该注意此脚本的一些问题,这个脚本没有 "alloc" 函数, 之后我就讲

接着,如果你明白为什么程序执行了对应jne的label,那你做得不错。

注意所有的labels(跳转标签)都在我的脚

本中定义了,否则他们不会编译。

````````````

Alloc

````````````

现在开始讲解"alloc"函数。 它是用来按照你的设想来分配X量的内存的函数 (hence,alloc,allocate)。 这些内存不是那些用过的, 而是那些你在运行程序中可以覆盖的没有被使用的内存。 就如同我说的,它会分配X量的内存。 X是个字节数的变量。1024bytes, 或者1 kb(kilobyte) 一般就足够你用了。现在我们了解了alloc函数,让我来演示下如何来使用它,并利用之前所学到的一切。(摸丸:按照尺寸划分一块内存,并给它起个名字)

Code:

alloc(AutoAssembler,1024)

alloc(SayWhat,1024)

label(Continue)

AutoAssembler:

mov eax,02

cmp eax,03

jne Continue

je SayWhat

Continue:

//...

SayWhat:

jmp 0

注意为什么我不这么做

Code:

label(AutoAssembler)

或者

Code:

label(SayWhat)

因为当用alloc划分出内存的时候,他们在Cheat Engine的词典中就自动得已经定义好了,便于我们调用。

````````````

RegisterSymbol

````````````

最后,函数"registersymbol"。 它可以添加你Cheat Table中你注册的标志。注意,你始终需要去为它分配内存。让我们在我们的脚本中试一试。

Code:

alloc(AutoAssembler,1024)

alloc(SayWhat,1024)

alloc(WooHoo,1024)

label(Continue)

registersymbol(WooHoo)

AutoAssembler:

mov eax,02

cmp eax,03

jne Continue

je SayWhat

Continue:

cmp eax,[WooHoo]

SayWhat:

jmp 0

````````````

Counterparts

````````````

现在,让我们来继续最后的一小段: the counterparts。

有两种使用AutoAssembler script的方法。第一种,你可以注入一些东西。第二种,你可以把它添加到Cheat Table中。如果你决定要把它填到cheat table (当今大多数脚本都是如此), 那你的代码需要enable和disable两部分代码,如下。

Code:

[ENABLE]

alloc(AutoAssembler,1024)

alloc(SayWhat,1024)

alloc(WooHoo,1024)

label(Continue)

registersymbol(WooHoo)

AutoAssembler:

mov eax,02

cmp eax,03

jne Continue

je SayWhat

Continue:

cmp eax,[WooHoo]

[DISABLE]

现在,你会注意到,Disable部分什么也没有,不过一会就不会了!;)

你在Disable部分中所想达到的就是:撤销你在Enable部分中所做的。

如何撤销内存分配和注册中的标记。现在,我感觉有个问题要来了

You wrote:

你是怎么办的?

简单来说,我的朋友。通过dealloc和 unregister symbol 函数! 哦,等等又有问题要来了。

"那label怎么办?" 你问?

嗯,没必要去撤销label。 =) 这意味着在Disable部分中,你大概要从开始那段中扔掉一半的代码! =)

那我

们为什么不把学的加进脚本里呢?

Code:

[ENABLE]

alloc(AutoAssembler,1024)

alloc(SayWhat,1024)

alloc(WooHoo,1024)

label(Continue)

registersymbol(WooHoo)

AutoAssembler:

mov eax,02

cmp eax,03

jne Continue

je SayWhat

Continue:

cmp eax,[WooHoo]

[DISABLE]

dealloc(AutoAssembler)

dealloc(SayWhat)

dealloc(WooHoo)

unregistersymbol(WooHoo)

哦这儿...还有个问题。

You wrote:

为什么你不用那个"1024"了?

因为计算机知道你分配的AutoAssembler是大小为1024 bytes 的 (我们就把它当个例子试一试吧),你只是需要deallocAutoAssembler,它就知道应该取消分配AutoAssembler的全部1024 bytes了。(很抱歉,解释的有些迷糊)

本帖最后由 cn_zou 于 2011-1-8 14:30 编辑

---------------

III.e Call and Ret

---------------

Call 函数和JMP 函数很相似。 唯一的不同是Call有个返回到之前代码的功能。这个简单例子利用了下面的两个函数。

Code:

mov [0100579C],10 //把地址的值改成10

cmp [0100579C],0 //把它和0进行比较

call NameGoesHere //调用或者跳转到 NameGoesHere

jmp 01002FF5

NameGoesHere:

dec [0100579C] //地址的值减1

cmp [0100579C],0 //跟0进行比较

jne NameGoesHere //如果不想等就返回到

//NameGoesHere的开始,否则 继续

ret //返回到之前,刚好是调用(call)函数之后

---------------

III.f Others

---------------

现在,很显然,在Auto Assembler还有很多很多其他的函数,不然它就是个很局限的语言。

我会继续尽我所能解释更多的函数。 (哦,老兄...)

`````

Nop

`````

Nop: 这个我之前提过。 它意味着 "无操作", 大体上它可以抵消它之前的代码。

`````

Inc/Dec

`````

Inc: 加一。 用于给寄存器或地址加一。 用法如下。

Code:

inc eax

Dec: 减一,跟Inc似的

`````

Add/Sub

`````

Add: 加法。 用法如下。

Code:

add eax,02 //给eax加2,并且将结果保存在eax中

Sub: 减法,用法类似Add

`````

Lea

`````

这个有点让人迷糊, 但还是继续吧。看下边的脚本。

Code:

mov eax,00123ABC

lea ebx,[eax+DEF]

也许你分不清楚,[eax+DEF] 是一个指针。 LEA把后面被指向的[eax+DEF]的地址替换给前面被指向的ebx里。

`````

And/Or/Xor

`````

好,我不知道如何清晰的说明“异或(xor)”在英文中的含义 –很多网站都只是用几行字这么描述的...

Them wrote:

我估计你明白这些逻辑操作符的行为

如果谁能给我用英文为XOR做个定义我将感激不尽。即使如此,我还是不需要帮助就能解释它们是如何在汇编中

工作的。 ;)

首先,它们都有着类似于add、sub命令一样的语法,如下。

Code:

and eax,ebx

每个eax 和 ebx 都可能是任何东西。哦不对, 他不可能是 "mymom"。 -。-;

回到脚本。来处理这个,(对,我知道我们都不是电脑...) 我们先要给两个寄存器值。就把12给eax,把27给ebx吧。下面,我们把它换成二进制的—那个零和一的语言。 =O 有问题吗?

You wrote:

怎么把十进制转成二进制啊?

我的傻朋友啊, 你怎么把你的好友计算器给忘了,用十进制把数输入,然后再点二进制啊! 有些事情需要注意,计算器不允许输入小数,它会简单的四舍五入下然后再转成二进制。

我搞出了:

Code:

EAX = 1100

&

EBX = 11011

好,还能回想起小学时做的数学填空题吗?让我们在这儿做下。

Code:

and eax,ebx

EAX = 1100

EBX = 11011

------------

现在,ADD(与)方法是如果都是1则是1,否则就是0。那就让我们来做出这道题吧。

Code:

and eax,ebx

EAX = 01100 (加个0更轻松)

EBX = 11011

-----------------

01000

现在我们把01000改成十进制,我们就会得到8,那个被存在EAX里的值。

接下来, 是OR(或) 函数。 现在让我们用相同的方法来轻松一下

Code:

or eax,ebx

EAX = 01100

EBX = 11011

-----------------

OR函数的功能与AND函数正相反。都是0,则得0, 否则就得1。

Code:

or eax,ebx

EAX = 01100

EBX = 11011

------------------

11111

把11111转成十进制,那会得到31,是EAX里存的值。

最后,是XOR(异或)函数。还是用那个方法。

Code:

xor eax,ebx

EAX = 01100

EBX = 11011

-----------------

好,XOR函数是如果两个数相同就得0,不同就得1。

Code:

xor eax,ebx

EAX = 01100

EBX = 11011

-----------------

10111

我们把它转换成23,而23就是储存在EAX里的值。顺便一提,无论当我们写的是脚本、代码还是别的什么,你都不需要考虑EAX里面装的什么BlahBlahBlah的东西, 我之所以这么做是让你知道它是如何工作的。

`````

好,这就是你所有需要知道的命令,(伙计,这可真长...) 让我们开始下一章节吧...

文档

CE AA 教程

本帖最后由cn_zou于2011-1-813:52编辑此文很适合AA入门,看上去很长,但作者一直用一种比较诙谐的讲述方式,读下来并不难,而且本文的内容一点都不难。本人英语渣,出现误译及错别字请多包涵。原文地址:http://forum.cheatengine.org/viewtopic.php?t=95363------------------------------内容表------------------------------I.介绍II.寄存器II.a32位寄存器II.b16位寄存器I
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top