16位汇编第九讲汇编指令以及逆向中的花指令

                                                                        16位汇编第九讲汇编指令以及逆向中的花指令

 

一丶LOOP指令(循环指令)

作用:   循环指令利用cx计数器自动减1,方便实现计数循环的程序结构 例如:   
mov cx,3 loop1:    ;标号 ..... LOOP loop1;不断的循环标号,然后cx-- 直到变为零
每次循环过后,cx都会自减,直到cx == 0,不过现在的loop指令不常用了,因为局限性太大,比如loop只能自减,而不能自增,所以我们都用 JCC 指令,来模拟loop指令

二丶子程序指令(函数的概念基于子程序指令)

问题? 什么是子程序   1.子程序是完成特定功能的一段程序   2.当主程序(调用程序)需要执行这个功能的时候,采用call调用指令转移到改子程序的起始处执行   3.当运行万子程序的功能的时候,采用 ret 返回指令回到主程序继续执行 如果懂C语言或者别的更高级的语言的请看   这个其实就是函数,为了代码的重用性,可利用性研究出来的,否则汇编代码一多就会很乱,比如有效的管理代码 比如ret指令,其实就是平衡栈的,在C语言中变成了语法,为return了

1.最原始的Call

主程序调用子程序的流程示意图:    这里主要介绍call传参,以及使用ret Call的原理是什么?   首先先看一段汇编程序
jmp PROC_ADD ;跳转到函数执行 d_One: jmp END_EXIT  ;跳转到程序结束位置,结束程序

PROC_ADD:
;函数ADD方法
mov ax,
1
mov bx,1
add ax,bx ;ax和bx相加,结果保存到ax中,ax当做返回值返回
jmp d_ONE ;跳转到 函数执行后的吓一吓一跳指令继续执行

END_EXIT: ;程序结束的代码不关注
mov ax,
4c00h
int 21h
看到上面的代码发现了什么,是不是和我们上面的图很像 主程序 -> 子程序的add方法, 然后 -> 跳转回来,跳转到下一条指令继续指令 这个就是雏形了,但是你有没有想过,这个add只能实现1 + 1 了,根本就不通用,怎么办,而且如果调用多次怎么办, 一直加标号,一直调用吗,显然是不切实际的.

2.Call 带有参数的传递

上面发现了一个大缺陷,就是不能参数传递,这样就不行了,那么我们要想办法,可不可以在外面传入参数 看代码:   
mov cx,1 mov dx,1 jmp PROC_ADD ;跳转到函数执行 d_One: jmp END_EXIT  ;跳转到程序结束位置,结束程序 PROC_ADD: ;函数ADD方法 mov ax,cx ;改为cx mov bx,dx ;改为dx add ax,bx ;ax和bx相加,结果保存到ax中,ax当做返回值返回 jmp d_ONE ;跳转到 函数执行后的吓一吓一跳指令继续执行 END_EXIT: ;程序结束的代码不关注 mov ax, 4c00h int 21h
我们发现,在外部寄存器更改了,就可以修改参数了,但是还有问题,寄存器一共才多少个,当我们参数有10个怎么办 比如CreateProcess API,它的参数就有10个以上,不用关心API是干啥的,可以看下参数. 正好10个,我们的寄存器都不够用了怎么办

3.更高级的Call带参数

  我们这个时候就会想到,寄存器已经不能满足我们的需求,这个时候,可以使用栈,我们可以使用栈来保存信息 出栈的时候栈平衡(就是使栈空间不被破坏)一下
mov cx,2 push cx ;压栈 mov dx,1 push dx        ;调用函数 CALL PROC_ADD mov dl,al mov ah,2h       ;执行显示al内容 int 21h jmp END_EXIT PROC_ADD: mov bp,sp mov ax,[bp +2]      ; 从栈中取出内容,注意为什么+2 mov bx,[bp+ 4] add ax,bx ret
在这里应该注意到了,我们用Call调用的时候,为什么函数内部要+2 原因是当这个子程序执行完毕的时候,需要返回到主程序执行,所以主程序的下一条指令已经压栈了,所以+2位置,可以取得参数 最后调用ret平栈 当程序遇到ret的时候,做的事情 1. 首先修改IP的值,IP的值, =  (ss栈段寄存器) * 16 + (sp栈顶)的值, 2.(sp栈顶) = (sp栈顶) + 2 需要注意的是,ret只会把最后压入的返回地址返回,但是参数还没有平栈,只能在调用完毕之后,在返回地址出的下一条指令自己平栈

4.Call的详细调用

mov cx,1 push cx mov bx,2 push bx CALL PROC_ADD PROC_ADD: ...... ret
ret的作用,就是从栈栈中取出返回地址,然后赋值给IP继续执行吓一条指令 但是注意,这里并没有平栈,我们必须在外面自己平栈 比如,我们我们入栈两个参数,比如  add sp,4   让sp平栈

四丶花指令

   请看下面的汇编代码 我们发现jmp的地方下面申请了一个字节,但是在汇编的时候,这1个字节和mov的机器码在一起了 因而产生的汇编代码就出错了,花指令混淆就是这样,这段代码还是可以正常执行的 对抗手法 1.如果是动态的调试,那么花指令是没用的(动态调试就是一步一步走)为什么,因为为了保证汇编代码不出错 每走一次代码都会重新反汇编 2.花指令主要对抗的是静态调试,因为病毒是不能运行的,只能看二进制和汇编,这个时候怎么办 我们发现了,他要jmp, jmp 1个字节,这个时候可以写个工具去弄,把jmp变为NOP(就是告诉CPU不执行) 现在我们在WINHEX中找到,然后改为 90机器码(代表NOP) 修改的时候,先看下反汇编 找到01的地方,改为90则NOP掉了,那么正确的反汇编就出现了   然后发现花指令去除了,这个就是最简单的花指令,当然这个可以通过寻找jmp的跳转的字节数,把里面的内容依次修改为NOP,所以就有了花指令去除工具 注意,这里是最简单的花指令,还有更复杂的,道高一尺魔高一丈,所以没有完整的花指令去除工具,到最后,可能你需要自己去分析,自己去修改了.  学习资料链接: http://pan.baidu.com/s/1slHi4vN 密码:hvjp
posted @ 2017-09-07 01:33 iBinary 阅读(...) 评论(...) 编辑 收藏