首页
社区
课程
招聘
[分享] 如何像吃大白兔奶糖一样的了解,学习,读懂汇编(一)?
发表于: 2018-4-4 11:09 5161

[分享] 如何像吃大白兔奶糖一样的了解,学习,读懂汇编(一)?

2018-4-4 11:09
5161
1.首先,声明本文纯为共享系列,您可以理解我是追随大佬的脚步学习并学会汇编,涉及到的知识您可以在看雪知识库中查询,此为本人汇编学习的纪念版。
2.目的,要想做一名安全开发的人,只懂得一些基础技术还远远不够,有了内核驱动编程的基础,发现做安全开发,比如过滤驱动就可以解决很多方面得安全问题,但我发现自己好像不会破解,不懂得破解就不能预防那些随时可能出现得破解套路,在研究几天对一些加壳或无壳的exe程序以后,我发觉玩破解的人大多都要使用到OD来反汇编找到破解的地址,然后去修改一些关键节点,实现软件的破解,那这就可能会出现一种安全问题,在破解的代码中介入木马病毒,然后公布给那些需要(或者说类似我这种比较爱破解软件的玩家)可能就会出现一系列的大问题。故此,出于工作(咳咳:主要还是为了Game)的目的,我要学汇编。
3.学习之前,本人大学已学习单片机原理课程,对汇编的基础知识有一定的了解(咳咳:应该是说一面之缘,学的不太好),此外对计算机原理也有一点点的印象,然而应该没什么软用。没关系,这几天研究研究,发现汇编并没有那么困难把,看雪知识库https://bbs.pediy.com/thread-53710-1.htm中的资料就讲的很好,但是图片没有看到,我也不是很确定是自己电脑的问题还是楼主没有上传的问题,这里你可以理解为是抄袭他的呢?没关系啦,来看此贴都是为了学习汇编的同仁,懂得啦!
4.您在看此贴之前,您需要准备 Win XP, Win 7 32,Win7 64  3个虚拟得操作系统,当然,如果您相信我得实现成果,那您只需要其中一个即可。 

我比较爱吃大白兔,所以,接下来我希望仅有一点点基础的我能像吃糖一样的学会汇编。

1.要吃糖之前,我们要有钱才能吃到糖。
对于计算机来说,CPU + 主板上的RAM内存+扩展卡上的RAM内存+显卡内存+ ROM(装了系统的BIOS,显卡BIOS,网卡BIOS)内存 + 磁盘 + 端口( Serail外设USB) 这些就是计算机组成部分了。计算机通过CPU来控制其他各个部分的功能执行,具体我不多说了。
我们首先关注的就是计算机的内存,最先的就是CPU了,CPU中的寄存器非常的重要,对于各个操作系统来说,通过Debug来查看各类寄存器的信息。
因为使用的是虚拟机,请选择进入系统后,运行CMD, 输入DEBUG进入dos的debug模式。
输入R查看CPU寄存器的信息。
XP下:
 

这个东西就要分析一波咯,我自己的理解,如有不对,望大佬指正。
CPU控制程序的运行(广义上说程序=算法+数据),程序在运行周期是会将程序的可执行文件(广义说 dll也是可执行文件)从内存中按寻址的能力(比如8位CPU一次寻址可以读8位地址,16位的CPU寻址一次可以读16位,32位可以读32位,64位可以读64位)一次一次读取到CPU的寄存器中,各种寄存器对于计算来说都有自己的特性功能,拿此XP版本的操作系统来说,我们观察到的寄存器就有如下方面:
1.AX,BX,CX,DX 这4个寄存器是的16位的数据寄存器(看到AX=0000,判定他是4*4位),也可称为通用寄存器,主要用来保存一般的运算结果和操作数,比如很简单的ADD  AX 0X0101 指令就会将0x0101加入到寄存器AX中这4个寄存器作为通用寄存器还可以分割成8个独立的8位寄存器(AX:AH-AL,BX:BH-BL,CX:BH-BL,DX:DH-DL),可以单独使用。其中,在使用加(ADD)减( SUB)  乘除输入输出操作时使用(AH-AL)会方便很多,因此它也被称作累加器。
2.SP,BP 这2个寄存器是指针寄存器,主要用来保存堆栈内存储单元在段内地址得偏移(就是程序咯),用于访问堆栈内的存储单元,BP作为基指针寄存器,用它可直接存取堆栈中的数据,SP作为堆栈指针寄存器,用它可以用来访问栈顶。也可已作为通用寄存器,可存储算术逻辑运算的操作数和运算结果。但不能分割成8位独立得寄存器。
3.SI,DI 这2个寄存器是变址寄存器,主要用来保存存储单元(其实就是内存)在段内地址的偏移,方便于内存寻址,一般来说指针存放于此没得毛病。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果,但不可分割成8位独立得寄存器。
4.DS,ES,SS,CS,IP是段寄存器,DS-数据段寄存器,其值为数据段的段值;ES-附加段寄存器,其值为附加数据段的段值;SS-堆栈段寄存器,其值位堆栈段得段值;其值位堆栈段得段值,CS-代码段寄存器,其值为代码段段值;
5.IP是指令指针寄存器,存放下次将要执行的指令在代码段的偏移量。
6.NV,UP,EI,PL,NZ,NA,PO,NC这8个是标志寄存器中的值,因为这个寄存器比较特殊,所以真正要看懂它必须要去研究它的位数。
 
溢出标志位 OF(Over flow flag) OV(1) NV(0)
方向标志位 DF(Direction flag) DN(1) UP(0)
中断标志位 IF(Interrupt flag) EI(1) DI(0)
符号标志位 SF(Sign flag) NG(1) PL(0)
零标志位     ZF(Zero flag) ZR(1) NZ(0)
辅助标志位  AF(Auxiliary carry flag) AC(1) NA(0)
奇偶标志位    PF(Parity flag) PE(1) PO(0)
进位标志位   CF(Carry flag) CY(1) NC(0)
好了,了解这些,我们可以出门吃糖了,怎么个吃法?操作寄存器,算是走出了家门啦。
来,按大佬的学法,我们来用debug 命令来操作操作寄存器。
1.按什么套路来玩?搞个简单的作为测试就好啦,修改AX寄存器的值。改为6666H怎么样?

那确实可以修改寄存器咯,那我加深点,搞个加法运算,1+1=2怎么样?
加法运算是操作,需要操作码的,那我也不知道咋玩机器码呀。没事,咱学汇编不管你什么机器码的。
思考一下,要执行汇编语言,我们debug 是有一个A指令的,用来存汇编代码,怎么存?当然是寄存器咯,一看,两个寄存器要用的,一个是CS:IP,CS用来存代码段,IP用来指向该代码段开始位置的偏移量。好了,随便选个放代码的位置,8888:8888,怎么样?1 + 1汇编怎么写?流程是这样的,先将1放入到AX寄存器中(mov ax,1),然后使用ADD ax,1 执行1+1 ,结果会存入到AX寄存器中 按Enter  退出编辑汇编代码状态,利用R命令修改CS寄存器的值为 8888,IP也是8888,然后执行T命令(请注意T命令每次也是只执行那一次代码运算,你写了几行就要T几次)来执行汇编代码,然后R确认最后我们的汇编运算结果。

  
可以看到,CS段代码寄存器的值没有发生改变,而IP指令指针寄存器的值随着代码的运行跟着发生了变化,因此判定,程序每次运行,都会引起指令寄存器值的变化,因为程序运行时的地址是随着它的运算而变化的。
回到机器码的问题,我是看不懂机器码的,比如ADD那一行,050100就是它的机器码,我并不能理解。我想只要知道我们的汇编代码被翻译成机器码然后存入到计算机的内存中,也就是此处的8888:8888:8888 ~8888:888e中了,不管这么多能明白就好了,我们抓住重点。
此外还有一个破解是修改内存的知识需要理解,怎么做呢?通过寻址来找打执行代码的内存,并修改内存数据,实现程序变种,这样可以看作是破解程序的第一次入门吧。debug通过D命令查看内存怎么解释呢?B80100  是mov ax,1代码的机器码    050100是add ax,1代码的机器码,执行后AX寄存器就会为2,为了达到验证效果,我们只要将后面的3DF9CD修改为050100,T执行后,得到的AX寄存器值为3,则说明验证正确。
 
通过E命令来修改内存,将3D,F9 CD 修改为 05 01 00;
E 8888:888E  05 01 88  修改完内存后再执行代码。

注意,此处就不是执行2次了,而是执行3,最后一次得到结果应该是3

验证正确,说明只要汇编代码写对了,翻译过来的机器码就可以被执行,而且,请注意我们不知道它机器码的长度,不要轻易判断内存中机器码是何种机器码。
还有,我认为还有必要说的就是将内存中的机器码翻译成汇编代码,这个就是逆向的过程了,由可执行文件翻译成汇编代码,从汇编代码中推敲出C语言实现,这样就完成了整个逆向流程了。使用U命令可以反汇编,U 8888:8888 看到了结果的同仁应该和我一样的激动吧。

简单的入门级实验,揭穿汇编的本质,需要编译为机器码,最后CPU执行的是机器码。而修改可执行文件的内存就是一种对机器码的修改,至于修改的套路则是反汇编后搞清楚逆向部分的实质,然后定位出要修改内存的点,比如说很久很久以前的破解套路,找到要查注册码的内存位置,修改跳转指令,直接跳转至下一执行从而跳过注册码检查。
紧接着您可以学习一波大佬的汇编代码,于我来说,我认为吃到一块小糖就满足了,接下来我需要的就是存储知识面了:认识并学会使用CPU的操作指令,列个表仅供参考。希望您读到此处对汇编有了一些理解嗯,边吃糖边玩汇编。
1.比较简单却又很复杂的数据传送指令:
    简单在于理解容易,复杂在于变种很多。
    格式:mov dest,src  功能:把一个字节,字或双字从源操作数src传送至目的操作数dest。
    这里又要谈到AX,BX,CX,DX寄存器,他们都是16位的寄存器,事实上对于32位的XP系统来说,具有32位寻址能力,他们会作为EAX,EBX,ECX,EDX的低16位而存在,我很想再debug中演示这个有趣的32位寄存器用于数据传送实验,但是因为debug是兼容dos而留下来的,dos里只能进行寄存器16位寻址,所以写入这个汇编指令会报错
所以,我们需要使用汇编开发工具来实现我们的验证。
引入真正的汇编开发。
2018/04/08 续
     清明节过去,回到工作中,回到学习中。闲下的几天,我思考了很多关于汇编学习思路的问题,应对于操作系统的版本,以及方便于学习,我决定不在XP上进行汇编演示,不是我不愿意去搭建汇编开发环境,我觉着有好的环境,不用白不用,也可以理解为小小的偷懒吧。我在Win 7 32 位和64位上都安装了VS 2013 ,对于此软件来说,自身由微软开发而且集成了那么多功能,其中就有汇编开发环境,无需搭建,只修改一下配置就完事了。就像是茫茫街道中,大白兔选择了我,而我恰巧也选择了它。
回到我们论题,汇编开发语言第一句,MOV指令。
对于Win 7 32位,你依旧可以参照Debug去验证前面在XP下的实验。而Win 7 64位不再支持,需要下载Debug box软件支持。
这些说明了什么呢?说明针对Window 2000以后的操作系统支持的32位架构其实本质上是基于16位的,不过他们因为增强了寻址能力,在架构上将独立的4个通用16位寄存器合并为2个32位寄存器,很明显,在debug模式下,依旧无法验证32位寄存器用法。接下来,请在Win 7 32位下开启我们的VS 2013,建立一个新的空项目,创建完成后属性生成依赖项中生成自定义,选择masm,  
还有一个就是要配置子系统 和添加汇编代码运行的入口点:main

然后添加一个汇编源文件test.asm

然后添加于源代码(此处来源代码非本人所写,因过于简单,不注明出处):
TITLE Add and Subtract              (AddSub.asm)  
  
; This program adds and subtracts 32-bit integers.  
; Last update: 2/1/02  
  
  
INCLUDELIB kernel32.lib  
  
.MODEL flat,stdcall  
  
;.code  
ExitProcess PROTO,                      ; exit program  
    dwExitCode:DWORD        ; return code  
  
  
.data  
.code  
main PROC  
  
    mov eax,10000h      ; EAX = 10000h  
mov ebx,10000h      ; EBX = 10000h
mov ecx,10000h      ; ECX = 10000h
mov edx,10000h      ; EDX = 10000h

;mov ax,10000h      ; AX = 10000h 此行必报错 因为16位寄存器下不能放5*4数据bit
mov ax,1000h      ; AX = 1000h  
mov bx,1000h      ; BX = 1000h  
mov cx,1000h      ; CX = 1000h  
mov dx,1000h      ; DX = 1000h  

;mov ah,100h      ; AH = 100h 此行必报错 因为8位寄存器下不能放3*4数据bit
mov ah,88h      ; AH = 88h  
mov bh,88h      ; BH = 88h  
mov ch,88h      ; CH = 88h  
mov dh,88h      ; DH = 88h  

;mov al,110h      ; AL = 110h  此行必报错 因为8位寄存器下不能放3*4数据bit
mov al,11h      ; BL = 11h 
mov bl,11h      ; BL = 11h  
mov cl,11h      ; CL = 11h  
mov dl,11h      ; DL = 11h  
    push 0h  
    call ExitProcess  
  
main ENDP  
END main  
调试寄存器技巧,先加一个断点,一定要先F5运行,然后快捷件 Ctrl + Alt+G 调出寄存器值查看。
注意观察,寄存器值的变化。




相信此处您可以看明白寄存器8位AH,8位AL ,16位AX和32位EAX的关系了吧,看到此处,我有了一些大胆的想法,尽管我们不能抛弃AX真正的寄存器编码风格,但能掌握住EAX的低16bit寄存器就是AX寄存器,而低16bit的AX又是有高8bit AH和低8bit AL组成的,从实验结果看这点是毋庸置疑的,因此,今后的汇编代码中,我应该会很少使用到AX这种低16bit寄存器,而大多数都如同反编译出来的代码一般,使用的是EAX这种32位的寄存器。
为了更快的学习汇编,回忆起当初研究过的MSP430芯片,读他的芯片手册让我头疼不已,给我的体会是,要学习X86 汇编,我们当然需要查看你它的手册啦,但因为现阶段不需要对它进行硬件编程,所以我们的汇编代码需要的是手册中完整的指令集。为了给自己一个对X86汇编的全貌,我下面列出手册中的所以指令集:









不需要你去仔细的阅读,但最后一个NOTES 要认真读一下,很重要。
看罢,我们要研究的是生成的EXE反汇编代码,利用VS2013的反汇编,先打断点然后启动后,调试 ,窗口,反汇编(快捷键 Alt+8),和我们写的汇编代码竟然是惊人的相似。为了得到MOV EAX,10000h的代码,我需要对EXE文件进行反汇编 ,请注意,不是说不能使用Debug 来进行得到机器码,而是debug 无法使用32位寄存器,所以,此刻我们需要一个工具,工具千千万,我先选一个IDA来反汇编玩玩。

研究机器码,我发现机器码和汇编代码之前的联系其实就是上面的那一张表,您可以自行学习有关汇编代码翻译成机器码的知识,此处我不做解释,研究机器码可能会拖慢学习节奏,但却可能会让您更加理解到汇编代码是怎么被翻译成机器语言并存为可执行文件然后执行的。

[课程]FART 脱壳王!加量不加价!FART作者讲授!

最后于 2018-4-8 15:45 被wo爱吃大白兔编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (6)
雪    币: 7652
活跃值: (4319)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主是有多爱大白兔  名字都是  ,期待更新,支持
2018-4-4 12:37
0
雪    币: 30
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
3
这位汇编大神,看来,需要你来拯救这一位只会问个不停的人

https://bbs.pediy.com/thread-188752.htm

https://bbs.pediy.com/thread-222977.htm

https://bbs.pediy.com/thread-223304.htm
2018-4-4 13:05
0
雪    币: 687
活跃值: (97)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
4
iqguks 这位汇编大神,看来,需要你来拯救这一位只会问个不停的人 https://bbs.pediy.com/thread-188752.htm https://bbs.pediy.com/thre ...
老兄,跟帖学汇编,最关键的还是要靠自己脚踏实地的去做实验才会体会到其中的味道,愿同仁都可一起吃糖。
2018-4-4 16:50
0
雪    币: 123
活跃值: (316)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
game程序都x64了,你讲单片机的汇编何用?还用的dos窗口,ce的AA脚本你可知否?
2018-4-7 04:50
0
雪    币: 687
活跃值: (97)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
taizhong game程序都x64了,你讲单片机的汇编何用?还用的dos窗口,ce的AA脚本你可知否?
sorry  ,作为刚入门汇编的小白,我确实不懂的地方很多很多,所以这一篇确实起不到什么大作用,我是自己玩一下,想知道汇编的前因后果,然后顺便记录一下自己的过程,虽然没什么作用,但我还是很想分享一下,因为看雪知识库中的教程确实很好,细节之处可能我这个算作小小补充。
最后于 2018-4-8 11:05 被wo爱吃大白兔编辑 ,原因:
2018-4-8 11:04
0
雪    币: 189
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
64位还是128位,只是执行数据越来越大了,但是反汇编还是离不开加减乘除补等等吧,我前些时候想了解手游,他们说现在都是C++写SO加密游戏了,因为java容易破解,所以,觉得要学外挂或驱动,始终离不开C或C++吧
2018-4-9 08:34
0
游客
登录 | 注册 方可回帖
返回
//