博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
16位汇编第九讲汇编指令以及逆向中的花指令
阅读量:5352 次
发布时间:2019-06-15

本文共 2868 字,大约阅读时间需要 9 分钟。

                                                                        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,1mov dx,1jmp 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_EXITPROC_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,1push cxmov bx,2push bxCALL PROC_ADDPROC_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,所以就有了花指令去除工具

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

 学习资料链接: 密码:hvjp

转载于:https://www.cnblogs.com/iBinary/p/7487839.html

你可能感兴趣的文章
平面波展开法总结
查看>>
建造者模式
查看>>
ArraySort--冒泡排序、选择排序、插入排序工具类demo
查看>>
composer 安装laravel
查看>>
8-EasyNetQ之Send & Receive
查看>>
Android反编译教程
查看>>
List<string> 去重复 并且出现次数最多的排前面
查看>>
js日志管理-log4javascript学习小结
查看>>
Android之布局androidmanifest.xml 资源清单 概述
查看>>
How to Find Research Problems
查看>>
Linux用户管理
查看>>
数据库第1,2,3范式学习
查看>>
《Linux内核设计与实现》第四章学习笔记
查看>>
使用iperf测试网络性能
查看>>
图片的显示隐藏(两张图片,默认的时候显示第一张,点击的时候显示另一张)...
查看>>
Docker 安装MySQL5.7(三)
查看>>
python 模块 来了 (调包侠 修炼手册一)
查看>>
关于CSS的使用方式
查看>>
分析语句执行步骤并对排出耗时比较多的语句
查看>>
原生JS轮播-各种效果的极简实现
查看>>