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

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

主程序调用子程序的流程示意图:

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

这里主要介绍call传参,以及使用ret

Call的原理是什么?

  首先先看一段汇编程序

jmp PROC_ADD           ;跳转到函数执行
d_One: jmp END_EXIT   ;跳转到程序结束位置,结束程序 

PROC_ADD:
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是干啥的,可以看下参数.

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

正好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平栈

四丶花指令

 请看下面的汇编代码16位汇编第九讲汇编指令以及逆向中的花指令
                                                                        16位汇编第九讲汇编指令以及逆向中的花指令
四丶花指令

我们发现jmp的地方下面申请了一个字节,但是在汇编的时候,这1个字节和mov的机器码在一起了

因而产生的汇编代码就出错了,花指令混淆就是这样,这段代码还是可以正常执行的

对抗手法

1.如果是动态的调试,那么花指令是没用的(动态调试就是一步一步走)为什么,因为为了保证汇编代码不出错

每走一次代码都会重新反汇编

2.花指令主要对抗的是静态调试,因为病毒是不能运行的,只能看二进制和汇编,这个时候怎么办

我们发现了,他要jmp, jmp 1个字节,这个时候可以写个工具去弄,把jmp变为NOP(就是告诉CPU不执行)

现在我们在WINHEX中找到,然后改为 90机器码(代表NOP)

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

修改的时候,先看下反汇编 找到01的地方,改为90则NOP掉了,那么正确的反汇编就出现了

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

然后发现花指令去除了,这个就是最简单的花指令,当然这个可以通过寻找jmp的跳转的字节数,把里面的内容依次修改为NOP,所以就有了花指令去除工具

注意,这里是最简单的花指令,还有更复杂的,道高一尺魔高一丈,所以没有完整的花指令去除工具,到最后,可能你需要自己去分析,自己去修改了.

 学习资料链接: http://pan.baidu.com/s/1slHi4vN 密码:hvjp