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软件支持。
还有一个就是要配置子系统 和添加汇编代码运行的入口点: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
TITLE Add and Subtract (AddSub.asm)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-4-8 15:45
被wo爱吃大白兔编辑
,原因: