Re 花指令学习

概念

花指令又名垃圾代码、脏字节,英文名是junk code。花指令就是在不影响程序运行的情况下,往真实代码中插入一些垃圾代码,从而影响反汇编器的正常运行;或是起到干扰逆向分析人员的静态分析,增加分析难度和分析时间。总结就是企图隐藏掉不想被逆向工程的代码块(或其它功能)的一种方法, 在真实代码中插入一些垃圾代码的同时还保证原有程序的正确执行, 而程序无法很好地反编译, 难以理解程序内容, 达到混淆视听的效果。

花指令的分类


可执行花指令

顾名思义,可以执行的花指令,这部分垃圾代码会在程序运行的时候执行,但是执行这些指令没有任何意义,并不会改变寄存器的值,同时反汇编器也可以正常的反汇编这些指令。目的是为了增加静态分析的难度,加大逆向分析人员的工作量。

不可执行花指令

不可以执行的花指令,这类花指令会使反编译器在反编译的时候出错,反汇编器可能错误的反汇编这些指令。根据反汇编的工作原理,只有花指令同正常指令的前几个字节被反汇编器识别成一组无用字节时,才能破坏反汇编的结果。因此,插入的花指令应当是一些不完整的指令,被插入的不完整指令可以是随机选择的。
为了能够有效迷惑反汇编器,同时又确保代码的正确运行,花指令必须满足两个基本特征,即:

垃圾数据必须是某个合法指令的一部分。
程序运行时,花指令必须位于实际不可执行的代码路径。

原理

反编译器的线性反编译(理解花指令的重点)

反编译器的工作原理是,从exe的入口AddressOfEntryPoint处开始,依序扫描字节码,并转换为汇编,比如第一个16进制字节码是0xE8,一般0xE8代表汇编里的CALL指令,且后面跟着的4个字节数据跟地址有关,那么反编译器就读取这一共5个字节,反编译为CALL 0x地址 。

对应的,有些字节码只需要一个字节就可以反编译为一条指令,例如0x55对应的是push ebp,这条语句每个函数开始都会有。同样,有些字节码又需要两个、三个、四个字节来反编译为一条指令。

也就是说,如果中间只要一个地方反编译出错,例如两条汇编指令中间突然多了一个字节0xE8,那反编译器就会将其跟着的4个字节处理为CALL指令地址相关数据给反编译成一条CALL 0x地址指令。但实际上0xE8后面的四个字节是单独的字节码指令。这大概就是线性反编译

线性扫描和递归下降

1.线性扫描算法
线性扫描算法p1从程序的入口点开始反汇编,然后对整个代码段进行扫描,反汇编扫描过程中所遇到的每条指令。线性扫描算法的缺点在于在冯诺依曼体系结构下,无法区分数据与代码,从而导致将代码段中嵌入的数据误解释为指令的操作码,以致最后得到错误的反汇编结果。

特点:从入口开始,一次解析每一条指令,遇到分支指令不会递归进入分支。

2.递归下降算法
递归下降采取另外一种不同的方法来定位指令。递归下降算法强调控制流的概念。控制流根据一条指令是否被另一条指令引用来决定是否对其进行反汇编,遇到非控制转移指令时顺序进行反汇编,而遇到控制转移指令时则从转移地址处开始进行反汇编。通过构造必然条件或者互补条件,使得反汇编出错。

特点:递归下降分析当遇到分支指令时,会递归进入分支进行反汇编。

花指令的构造

jx+jnx

 __asm {
        jz s;
		jnz s;
		_emit 0xC7;
s:

jnz实际上是fake的,因为jz这个指令,让ida认为jz下面的是另外一个分支,所以这里去除,就是将jnz下面包括jnz 全c了,然后把loc_402669+1的字节码全给nop了

这种混淆去除方式也很简单,特征也很明显,因为是近跳转,所以ida分析的时候会分析出jz或者jnz会跳转几个字节,这个时候我们就可得到垃圾数据的长度,将该长度字节的数据全部nop掉即可解混淆。

call pop / add esp

 这里call指令,其实本质就是jmp&push 下一条指令的地址,但是这里其实就是一个jmp指令

所以 push这条指令是多余的,需要add esp,4 调整堆栈,但是ida会默认把call 后面的那个地址

当成一个函数。

stx/jx

clc是清除EFlags寄存器的carry位的标志,而jnb是根据cf==0时跳转的,然而jnb这个分支指令,ida

又将后面的部分认作成了另外的分支

jmp xxx红色

看下花指令源代码, 实际是e9在搞鬼,ida会默认将e9后面的4个字节当成地址,只要nop掉就行 

多重跳转的

利用idapython去除

def nop(addr,endaddr):
    while(addr<endaddr):
        PatchByte(addr,0x90)
        addr+=1
def undefine(addr,endaddr):
    while addr<endaddr:
        MakeUnkn(addr,0)
        addr+=1
def dejunkcode(addr,endaddr):
    while addr<endaddr:
        MakeCode(addr)
        # 匹配模版
        if GetMnem(addr)=='jmp' and GetOperandValue(addr,0)==addr+5 and Byte(addr+2)==0x12:
            next=addr+10
            nop(addr,next)
            addr=next
            continue
        addr+=ItemSize(addr)

永恒跳转

最简单的jmp指令
jmp s
  db junk_code;
s:

这种jmp单次跳转只能骗过线性扫描算法,会被IDA识别(递归下降)

多层跳转
__asm {
        jmp s1;
        _emit 68h;
    s1:
        jmp s2;
        _emit 0CDh;
        _emit 20h;
    s2:
        jmp s3;
        _emit 0E8h;
    s3:
    }

和单次跳转一样,这种也会被IDA识别。将花指令改写一下骗过IDA

       __asm {
            _emit 0xE8
            _emit 0xFF
            //_emit 立即数:代表在这个位置插入一个数据,这里插入的是0xe8
        }

可以看到IDA错误的识别loc_411877处的代码,成功的实现了花指令的目的

常用指令含义

push ebp ----把基址指针寄存器压入堆栈
pop ebp ----把基址指针寄存器弹出堆栈
push eax ----把数据寄存器压入堆栈
pop eax ----把数据寄存器弹出堆栈
nop -----不执行
add esp,1-----指针寄存器加1
sub esp,-1-----指针寄存器加1
add esp,-1--------指针寄存器减1
sub esp,1-----指针寄存器减1
inc ecx -----计数器加1
dec ecx -----计数器减1
sub esp,1 ----指针寄存器-1
sub esp,-1----指针寄存器加1
jmp 入口地址----跳到程序入口地址
push 入口地址---把入口地址压入堆栈
retn ------ 反回到入口地址,效果与jmp 入口地址一样
mov eax,入口地址 ------把入口地址转送到数据寄存器中.
jmp eax ----- 跳到程序入口地址
jb 入口地址
jnb 入口地址 ------效果和jmp 入口地址一样,直接跳到程序入口地址
xor eax,eax 寄存器EAX清0
CALL 空白命令的地址 无效call

栈指针平衡

这里借用大佬的图来看一个栈针平衡的示例,总结就是先进后出,每一次pop和push要改变esp让栈平衡

例题:

[HNCTF 2022 WEEK2]e@sy_flower

当使用IDA分析伪代码时,有花指令会发生

无法查看伪代码,需要去给出的地址查看具体发生的问题

要设置一下IDA,让它显示出栈指针(Options-General-Disassembly-"Stack pointer")

可以把stack pointer打开,然后再把number of opcode bytes 设为5

发现jz和jnz互补跳转了,后面地址+1已经提示了跳转的字节大小。

 选中这一行,Edit-Patch program-Change bytes,把第一个e9改为90

对main函数用P重新定义下,再F5反编译

逻辑就是输入的flag先互换位置,再与0x30异或

enc = list('c~scvdzKCEoDEZ[^roDICUMC')
flag = []
for i in range(len(enc)):
    flag.append(chr(ord(enc[i])^0x30))
    
for i in range(int(len(flag)/2)):
    tmp = flag[2*i]
    flag[2 * i] = flag[2 * i + 1]
    flag[2 * i + 1] = tmp
    
for i in flag:
    print(i,end="")

[MoeCTF 2022]chicken_soup

查壳32,打开分析后发现401000和401080对v4加密了,点击进去,就发现401000和401080被加花了

jz和jnz互补跳转。打开opcode bytes的显示,然后分别对E9改为90nop掉,然后用P再F5

进去main,可以看到sub_401000和sub_401080分别对v4进行加密

思路:输入字符串---->flag长度检验为38个—>经过2个函数指针的运算后----->与加密过后的数据进行比较

第一层加密,即flag[i] = flag[i] + flag[i+1]

第二层加密,即每个字符自身左移4位与自身右移4位进行按位与运算
即flag[i] >> 4 | flag[i] << 4

直接逆回去

enc =[0xcd,0x4d,0x8c,0x7d,0xad,0x1e,0xbe,0x4a,0x8a,0x7d,0xbc,0x7c,0xfc,0x2e,0x2a,0x79,0x9d,0x6a,0x1a,0xcc,0x3d,0x4a,0xf8,0x3c,0x79,0x69,0x39,0xd9,0xdd,0x9d,0xa9,0x69,0x4c,0x8c,0xdd,0x59,0xe9,0xd7]

for i in range(len(enc)):
	enc[i] = ((enc[i]//16 | enc[i]<<4)) & 0xff
	print((enc[i]))

for i in range(len(enc)-1, 0, -1):
    enc[i-1] -= enc[i]

print(bytes(enc))

参考:

手脱花指令及IDA脚本编写 - 『脱壳破解区』 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

【逆向学习】花指令的去除_去除花指令-CSDN博客

花指令的模式识别以及处理 - YenKoc - 博客园 (cnblogs.com)

[原创][花指令]由易到难全面解析CTF中的花指令-软件逆向-看雪-安全社区|安全招聘|kanxue.com

CTF逆向Reverse 花指令介绍 and NSSCTF靶场入门题目复现_Sciurdae的博客-CSDN博客

汇编跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等_jg指令-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/218858.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开发的客户收到样品表示质量不如原供应商如何应对

有小伙伴问&#xff0c;在开发客户的过程当中&#xff0c;给客户寄了样品&#xff0c;客户说他的样品没有原来供应商的好怎么办&#xff1f; 这个问题我们来想一下&#xff0c;客户既然愿意把地址给我们&#xff0c;愿意去接你的样品&#xff0c;说明什么&#xff1f;说明客户…

系列十五、SpringBoot的启动原理分析

一、概述 所谓SpringBoot的启动原理&#xff0c;翻译成大白话就是"当我们在主启动类上运行run方法时&#xff0c;SpringBoot底层到底做了什么事情&#xff0c;能够帮助我们启动一个Spring的web应用"&#xff0c;上边用大白话解释了一下什么是SpringBoot的启动原理&am…

PyQt6 QTabWidget选项卡控件

​锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计37条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话…

0001微信报Dynamic.dll,微信报DynamicDll64.dll 环境

0001微信报Dynamic.dll&#xff0c;微信报DynamicDll64.dll 1. 环境 操作系统&#xff1a;Windows10专业版 2. 现象 某赛通加密客户端升级后&#xff0c;企业微信和微信报如下错误 分析 该加密软件升级导致的异常 3. 解决办法 企业微信&#xff1a;粘贴DynamicDll.dll到…

ULAM公链第九十六期工作总结

迈入12月&#xff0c;接下来就是雪花&#xff0c;圣诞&#xff0c;新年和更好的我们&#xff01;愿生活不拥挤&#xff0c;笑容不必刻意&#xff0c;愿一切美好如期而至&#xff01; 2023年11月01日—2023年12月01日关于ULAM这期工作汇报&#xff0c;我们通过技术板块&#xff…

MISRA C 2012 标准浅析

MISRA(The Motor Industry Software Reliability Association)&#xff0c;汽车工业软件可靠性联会&#xff1b; 1994年&#xff0c;英国成立。致力于协助汽车厂商开发安全可靠的软件的跨国协会&#xff0c;其成员包括&#xff1a;AB汽车电子、罗孚汽车、宾利汽车、福特汽车、捷…

堆排序详细讲解(一文足矣JAVA)

目录 1、什么是堆 2、大顶堆 3、小顶堆 4、排序思想&#xff1a; 5、代码实现 1、什么是堆 在计算机科学中&#xff0c;堆&#xff08;Heap&#xff09;是一种特殊的数据结构&#xff0c;通常是一个可以被看作近似完全二叉树的数组对象。在堆中&#xff0c;父节点的值总是…

四通道轨-轨运算芯片 D8054,外围应用简便,低功耗2.3mA (典型值)运放供电电流

D8054是一款四通道轨-轨运算放大器&#xff0c;外围应用简便&#xff0c;价格低廉。封装形式为SOP14&#xff0c;TSSOP14&#xff0c; SOP16&#xff0c; TSSOP16。 主要特点&#xff1a; ● 轨-轨输出&#xff0c;输出失调2mV (典型值) ● 高速250MHz&#xff0c;-3dB带…

网络细节核心笔记

来源&#xff0c;做个笔记&#xff0c;讲的还蛮清楚通信原理-2.5 数据封装与传输05_哔哩哔哩_bilibili 交换机

java人工智能交互医院智慧导诊系统源码

随着人工智能技术的快速发展&#xff0c;语音识别与自然语言理解技术的成熟应用&#xff0c;基于人工智能的智能导诊导医逐渐出现在患者的生活视角中&#xff0c;智能导诊系统应用到医院就医场景中&#xff0c;为患者提供导诊、信息查询等服务&#xff0c;符合智慧医院建设的需…

python代码样式规范

https://peps.python.org/pep-0008/

微软 Power Platform 零基础 Power Pages 网页搭建实际案例实践(三)

微软 Power Platform 零基础 Power Pages 网页搭建教程之案例实践学习&#xff08;三&#xff09;结合Power Apps和Power Automate Power Pages 实际案例学习 微软 Power Platform 零基础 Power Pages 网页搭建教程之案例实践学习&#xff08;三&#xff09;结合Power Apps和Po…

「Verilog学习笔记」时钟分频(偶数)

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1nsmodule even_div(input wire rst ,input wire clk_in,output wire clk_out2,output wire clk_out4,output wire clk_out8); //********…

鸿蒙Harmony应用开发,一起来写一个“遥遥领先”的开眼App

前言 最近不知道怎么鸿蒙Harmony突然就很火&#xff0c;到处都是鸿蒙开发相关的文章&#xff0c;培训机构的也是各种推鸿蒙应用&#xff0c;不知道是真的&#x1f525;了&#xff0c;还是在贩卖焦虑&#xff01;不过看热度不错&#xff0c;那也就来了解了解咱们的遥遥领先&…

css悬浮展示隐藏内容,从下向上展示

标题 <div class"cont"><div class"box"><img src"./images/1.jpg" alt""><p class"title">无锡2日1晚自由行(5钻)【5.23-5.25抢购】</p><div><p class"txt_a">席位充…

Java 并发编程面试题——Java 线程间通信方式

目录 1.✨Java 线程间有哪些通信方式&#xff1f;1.1.volatile 和 synchronized 关键字1.2.等待/通知机制1.2.1.概述1.2.2.经典范式 1.3.管道输入/输出流1.4.信号量 2.Thread.join() 有什么作用&#xff1f;它的使用场景是什么&#xff1f;3.Java 中需要主线程等待子线程执行完…

计算机毕设:基于机器学习的生物医学语音检测识别 附完整代码数据可直接运行

项目视频讲解: 基于机器学习的生物医学语音检测识别 完整代码数据可直接运行_哔哩哔哩_bilibili 运行效果图: 数据展示: 完整代码: #导入python的 numpy matplotlib pandas库 import pandas as pd import numpy as np import matplotlib.pyplot as plt #绘图 import se…

【STM32入门】3.OLED屏幕

1.OLED引脚 OLED屏幕的接线按图所示&#xff0c;本例中用的是4管脚OLED屏幕 2.驱动程序 配套的驱动程序是“OLED.c"&#xff0c;主要由以下函数构成&#xff1a;1、初始化&#xff1b;2、清屏&#xff1b;3、显示字符&#xff1b;4、显示字符串&#xff1b;5、显示数字…

python中的输入输出

文章目录 输入函数input()例子1.如何输入获得两个字符串?&#xff08;若输入abc def或abc,def)2.如何输入获得两个整数?&#xff08;若输入34,567)3.如何输入后获得一个元素均为数值型的列表?&#xff08;若输入12,3.4,567或[12,3.4,567]&#xff09; 输出输出函数print()pr…

Windows或mac要远程控制小米手机,用什么软件?

想要远程控制小米手机的各位不用烦恼&#xff0c;其实用AirDroid就可以直接解决跨品牌跨系统远程控制小米手机的问题。AirDroid是一种广泛使用的远程控制软件&#xff0c;专为安卓设备设计&#xff0c;可以让你在任何地方访问和控制你的小米手机。 不管你用的是哪个品牌的台式电…