当前位置: 首页 > news >正文

花指令简析

几种花指令简析

  • 一、花指令1
    • (一)反汇编代码比对与分析
      • 总结经验:
    • (二)去花
      • 1.反汇编器中手动改字节
      • 2.IDC去花
      • 3. 010 Editor改PE文件
  • 二、花指令2
    • (一)反汇编代码比对与分析
      • 1、call指令
        • (1)call + label
        • (2)call far ptr + label
        • (3)call + reg16
        • (4)call word ptr + 内存单元地址
        • (5)call dword ptr + 内存单元地址
      • 2、ret指令
    • (二)去花
      • 1.反汇编器手动改字节
      • 2.IDC去花
      • 3. 010 Editor改PE文件
  • 三、花指令3
    • (一)反汇编代码比对与分析
    • (二)去花
      • 1.反汇编器手动改字节
      • 2.IDC去花
      • 3. 010 Editor改PE文件
  • 四、花指令4
  • 五、花指令5
  • 六、花指令6
    • (一)反汇编代码比对与分析
    • (二)去花
      • 1.反汇编器手动改字节
      • 2.IDC去花
      • 3. 010 Editor改PE文件
  • 七、花指令7
  • 八、花指令8(配合裸函数)
    • (一)反汇编代码比对与分析
      • 裸函数
        • (1)无参数无返回值的函数框架
        • (2)有参数有返回值的函数框架
        • (3)带局部变量的函数框架
    • (二)去花
      • 1.反汇编器手动改字节
      • 2.IDC去花
      • 3.010 Editor修改

本篇博客我们将给用下面源代码编译出的程序加不同的花指令来分析,并学习如何去除花指令

//实现求n的m次方
#include<stdio.h>
#include<windows.h>
int main()
{MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result=1;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);for (int i = 0; i < m; i++)result *= n;printf("结果为%d", result);return 0;
}

IDA静态反汇编出的汇编

.text:0045E3A0 ; int __cdecl main_0(int argc, const char **argv, const char **envp)
.text:0045E3A0 _main_0         proc near               ; CODE XREF: _main↑j
.text:0045E3A0
.text:0045E3A0 var_F4          = byte ptr -0F4h
.text:0045E3A0 var_30          = dword ptr -30h
.text:0045E3A0 var_24          = dword ptr -24h
.text:0045E3A0 var_18          = dword ptr -18h
.text:0045E3A0 var_C           = dword ptr -0Ch
.text:0045E3A0 var_4           = dword ptr -4
.text:0045E3A0 argc            = dword ptr  8
.text:0045E3A0 argv            = dword ptr  0Ch
.text:0045E3A0 envp            = dword ptr  10h
.text:0045E3A0
.text:0045E3A0                 push    ebp
.text:0045E3A1                 mov     ebp, esp
.text:0045E3A3                 sub     esp, 0F4h
.text:0045E3A9                 push    ebx
.text:0045E3AA                 push    esi
.text:0045E3AB                 push    edi
.text:0045E3AC                 lea     edi, [ebp+var_F4]
.text:0045E3B2                 mov     ecx, 3Dh
.text:0045E3B7                 mov     eax, 0CCCCCCCCh
.text:0045E3BC                 rep stosd
.text:0045E3BE                 mov     eax, ___security_cookie
.text:0045E3C3                 xor     eax, ebp
.text:0045E3C5                 mov     [ebp+var_4], eax
.text:0045E3C8                 mov     ecx, offset unk_53B00F
.text:0045E3CD                 call    j_@__CheckForDebuggerJustMyCode@4 ; __CheckForDebuggerJustMyCode(x)
.text:0045E3D2                 mov     esi, esp
.text:0045E3D4                 push    0               ; uType
.text:0045E3D6                 push    offset Caption  ; "YQC"
.text:0045E3DB                 push    offset Text     ; "未加花指令"
.text:0045E3E0                 push    0               ; hWnd
.text:0045E3E2                 call    ds:MessageBoxA
.text:0045E3E8                 cmp     esi, esp
.text:0045E3EA                 call    j___RTC_CheckEsp
.text:0045E3EF                 mov     [ebp+var_24], 1
.text:0045E3F6                 push    offset aNM      ; "请输入n和m:\n"
.text:0045E3FB                 call    sub_45748D
.text:0045E400                 add     esp, 4
.text:0045E403                 lea     eax, [ebp+var_18]
.text:0045E406                 push    eax
.text:0045E407                 lea     ecx, [ebp+var_C]
.text:0045E40A                 push    ecx
.text:0045E40B                 push    offset aDD      ; "%d%d"
.text:0045E410                 call    sub_4584E6
.text:0045E415                 add     esp, 0Ch
.text:0045E418                 mov     [ebp+var_30], 0
.text:0045E41F                 jmp     short loc_45E42A
.text:0045E421 ; ---------------------------------------------------------------------------
.text:0045E421
.text:0045E421 loc_45E421:                             ; CODE XREF: _main_0+9C↓j
.text:0045E421                 mov     eax, [ebp+var_30]
.text:0045E424                 add     eax, 1
.text:0045E427                 mov     [ebp+var_30], eax
.text:0045E42A
.text:0045E42A loc_45E42A:                             ; CODE XREF: _main_0+7F↑j
.text:0045E42A                 mov     eax, [ebp+var_30]
.text:0045E42D                 cmp     eax, [ebp+var_18]
.text:0045E430                 jge     short loc_45E43E
.text:0045E432                 mov     eax, [ebp+var_24]
.text:0045E435                 imul    eax, [ebp+var_C]
.text:0045E439                 mov     [ebp+var_24], eax
.text:0045E43C                 jmp     short loc_45E421
.text:0045E43E ; ---------------------------------------------------------------------------
.text:0045E43E
.text:0045E43E loc_45E43E:                             ; CODE XREF: _main_0+90↑j
.text:0045E43E                 mov     eax, [ebp+var_24]
.text:0045E441                 push    eax
.text:0045E442                 push    offset aD       ; "\n%d"
.text:0045E447                 call    sub_45748D
.text:0045E44C                 add     esp, 8
.text:0045E44F                 xor     eax, eax
.text:0045E451                 push    edx
.text:0045E452                 mov     ecx, ebp        ; Esp
.text:0045E454                 push    eax
.text:0045E455                 lea     edx, Fd         ; Fd
.text:0045E45B                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:0045E460                 pop     eax
.text:0045E461                 pop     edx
.text:0045E462                 pop     edi
.text:0045E463                 pop     esi
.text:0045E464                 pop     ebx
.text:0045E465                 mov     ecx, [ebp+var_4]
.text:0045E468                 xor     ecx, ebp        ; StackCookie
.text:0045E46A                 call    j_@__security_check_cookie@4 ; __security_check_cookie(x)
.text:0045E46F                 add     esp, 0F4h
.text:0045E475                 cmp     ebp, esp
.text:0045E477                 call    j___RTC_CheckEsp
.text:0045E47C                 mov     esp, ebp
.text:0045E47E                 pop     ebp
.text:0045E47F                 retn
.text:0045E47F _main_0         endp

一、花指令1

__asm {xor eax, eaxtest eax, eax      //产生确定标志位ZFje LABEL1jne LABEL2         //je和jnz指令形成互补跳转LABEL2 :_emit 0x5e     //与pop si机器码相同and eax, ebx_emit 0x50     //与push ax机器码相同xor eax, ebx_emit 0x74     //与汇编助记符 jz 机器码相同add eax, edxLABEL1 :}

加花指令1后的程序源码

#include<stdio.h>
#include<windows.h>
int a = 0;
int main()
{MessageBox(NULL, "加花指令1", "YQC", 0);//MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result=1;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);__asm {xor eax, eaxtest eax, eaxje LABEL1jne LABEL2LABEL2 :_emit 0x5e     //与pop si机器码相同and eax, ebx_emit 0x50     //与push ax机器码相同xor eax, ebx_emit 0x74     //与汇编助记符 jz 机器码相同add eax, edxLABEL1 :}for (int i = 0; i < m; i++)result *= n;printf("结果为%d", result);return 0;
}

(一)反汇编代码比对与分析

下面给出用IDA静态分析加花的程序的主函数部分生成的反汇编代码,此时因为花指令,main函数已经不能F5了。

.text:0045E3A0 ; int __cdecl main_0(int argc, const char **argv, const char **envp)
.text:0045E3A0 _main_0:                                ; CODE XREF: _main↑j
.text:0045E3A0                 push    ebp
.text:0045E3A1                 mov     ebp, esp
.text:0045E3A3                 sub     esp, 0F4h
.text:0045E3A9                 push    ebx
.text:0045E3AA                 push    esi
.text:0045E3AB                 push    edi
.text:0045E3AC                 lea     edi, [ebp-0F4h]
.text:0045E3B2                 mov     ecx, 3Dh ; '='
.text:0045E3B7                 mov     eax, 0CCCCCCCCh
.text:0045E3BC                 rep stosd
.text:0045E3BE                 mov     eax, ___security_cookie
.text:0045E3C3                 xor     eax, ebp
.text:0045E3C5                 mov     [ebp-4], eax
.text:0045E3C8                 mov     esi, esp
.text:0045E3CA                 push    0
.text:0045E3CC                 push    offset unk_510E50
.text:0045E3D1                 push    offset a1       ; "加花指令1"
.text:0045E3D6                 push    0
.text:0045E3D8                 call    ds:MessageBoxA
.text:0045E3DE                 cmp     esi, esp
.text:0045E3E0                 call    j___RTC_CheckEsp
.text:0045E3E5                 mov     dword ptr [ebp-24h], 1
.text:0045E3EC                 push    offset aNM      ; "请输入n和m:\n"
.text:0045E3F1                 call    sub_45748D
.text:0045E3F6                 add     esp, 4
.text:0045E3F9                 lea     eax, [ebp-18h]
.text:0045E3FC                 push    eax
.text:0045E3FD                 lea     ecx, [ebp-0Ch]
.text:0045E400                 push    ecx
.text:0045E401                 push    offset aDD      ; "%d%d"
.text:0045E406                 call    sub_4584E6
.text:0045E40B                 add     esp, 0Ch
.text:0045E40E                 xor     eax, eax
.text:0045E410                 test    eax, eax
.text:0045E412                 jz      short near ptr locret_45E41E+1
.text:0045E414                 jnz     short $+2
.text:0045E416
.text:0045E416 loc_45E416:                             ; CODE XREF: .text:0045E414↑j
.text:0045E416                 pop     esi
.text:0045E417                 and     eax, ebx
.text:0045E419                 push    eax
.text:0045E41A                 xor     eax, ebx
.text:0045E41C                 jz      short loc_45E421
.text:0045E41E
.text:0045E41E locret_45E41E:                          ; CODE XREF: .text:0045E412↑j
.text:0045E41E                 retn    45C7h
.text:0045E421 ; ---------------------------------------------------------------------------
.text:0045E421
.text:0045E421 loc_45E421:                             ; CODE XREF: .text:0045E41C↑j
.text:0045E421                 rol     byte ptr [eax], 1
.text:0045E421 ; ---------------------------------------------------------------------------
.text:0045E423                 db 0
.text:0045E424                 dd 9EB0000h, 83D0458Bh, 458901C0h, 0D0458BD0h, 7DE8453Bh
.text:0045E424                 dd 0DC458B0Ch, 0F445AF0Fh, 0EBDC4589h, 0DC458BE3h
.text:0045E448 ; ---------------------------------------------------------------------------
.text:0045E448                 push    eax
.text:0045E449                 push    offset aD_0     ; "结果为%d"
.text:0045E44E                 call    sub_45748D
.text:0045E453                 add     esp, 8
.text:0045E456                 xor     eax, eax
.text:0045E458                 push    edx
.text:0045E459                 mov     ecx, ebp
.text:0045E45B                 push    eax
.text:0045E45C                 lea     edx, dword_45E488
.text:0045E462                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:0045E467                 pop     eax
.text:0045E468                 pop     edx
.text:0045E469                 pop     edi
.text:0045E46A                 pop     esi
.text:0045E46B                 pop     ebx
.text:0045E46C                 mov     ecx, [ebp-4]
.text:0045E46F                 xor     ecx, ebp
.text:0045E471                 call    j_@__security_check_cookie@4 ; __security_check_cookie(x)
.text:0045E476                 add     esp, 0F4h
.text:0045E47C                 cmp     ebp, esp
.text:0045E47E                 call    j___RTC_CheckEsp
.text:0045E483                 mov     esp, ebp
.text:0045E485                 pop     ebp
.text:0045E486                 retn

对比一下不同的区域,很明显看出加了花指令1的程序因为花指令的存在产生了未被反汇编出的部分
在这里插入图片描述
细看可以注意到,下图三个框框中是源码中没有加入的花指令,只是加了对应的机器码,显然ida把那几个机器码当作汇编指令来翻译了(0x5epop si机器码相同,0x50push ax机器码相同,0x74与汇编助记符 jz机器码相同),

但程序运行过程中是不会受到影响的,这是因为有下面指令的存在,仔细看下面注释你能发现程序运行这个花指令的时候产生确定标志位(ZF),进而出现确定跳转(必定执行je LABEL1跳转指令 ),所以肯定是会绕过干扰代码的,

		xor eax, eax          //eax寄存器置零test eax, eax         //ZF=1,是确定标志位【test不会将结果放在寄存器上,它只影响ZF的状态,如果EAX == 0,那么ZF = 1】je LABEL1             //ZF=1时触发跳转到正常指令处LABEL1 jne LABEL2            //ZF=0时触发跳转到干扰项处LABEL2,与上面的指令形成互补跳转
LABEL2 :/*干扰项所在*/
LABEL1:/*正常代码*/

总结经验:

现在许多的花指令采用生成确定标志位并搭配两个互补的条件跳转指令替代一个强制跳转指令(如jmp)以增加汇编难度的方式。
其实如果一个程序出现下面互补跳转代码,而且跳转代码前某一个标志位一定是确定值,同时指令下方还出现报错的情况,基本可以断定是花指令(可以作为花指令起始或者存在的标志,是充分不必要条件)。
而且运行过程中必然不发生跳转的那一个指令的目标地址或者标号是干扰项。

		xor eax, eax        test eax, eax       //产生确定标志位je LABEL1           jne LABEL2           
LABEL2 :/*干扰项所在*/
LABEL1:/*正常代码*/

那么回到当前花指令分析,这个花指令最主要起作用的地方是让IDA将机器码0x74翻译成了jz指令,致使这个指令的下一个本该翻译成指令(即add eax, edx)的机器码却被翻译成了跳转的地址,进而出现了后面的指令不正常反汇编的情况。
在这里插入图片描述

(二)去花

以IDA为例(OD也可),

既然这个花指令的关键是那个0x74字节码,那么只要从那个字节码下手,使之无效(改成nop)即可,至于花指令中另外两个字节码0x5e0x50,它们并未影响ida的反汇编,这里可以不处理。

去花操作这里给出三种方法:

1.反汇编器中手动改字节

光标移到jz short loc_45E421指令处,按下图所示修改字节码
在这里插入图片描述
直接把jz对应的字节码0x74改成0x90,即nop助记符,点击确认
在这里插入图片描述
然后按Dnop指令下面的不正常指令变成数据,
在这里插入图片描述
然后按C强制把数据反汇编成代码
在这里插入图片描述
对比后效果如下。
在这里插入图片描述
要想F5的话,还差一步,需要手动申明成函数,直接从ret指令到main函数开头之间的代码部分选中,按P一键生成函数。
在这里插入图片描述
F5效果如下,去花成功
在这里插入图片描述

2.IDC去花

针对花指令较多的情况,建议采用idc脚本去花,

先获取jz short loc_45E421的字节码如下图,我们只要取74 03即可,因为0x74代表jz助记符,而add reg16,reg16的字节码刚好为 0x03,对应了add eax,eax
在这里插入图片描述
根据idc的API和语法写出如下idc脚本

#include<idc.idc>
static main()
{auto StartVa, StopVa, Size, i;StartVa=0x0045E3A0;StopVa=0x0045E486;Size=StopVa-StartVa;for (i=0; i<Size; i++){if (Byte(StartVa)==0x74){if(Byte(StartVa+1)==0x03){PatchByte(StartVa, 0x90);MakeCode(StartVa);StartVa++;Message("Find FakeJmp Opcode!!\n");continue;}}StartVa++;}Message("Clear FakeJmp Opcode Ok\n");
}

按下图所示运行一下,或者放到txt文件里面改后缀为.idc,然后file->Script file导入该文件

在这里插入图片描述
修改成功
在这里插入图片描述
但不足的是这个脚本没有实现自动反汇编成汇编代码,运行了该脚本之后依旧有一些没有反汇编成正常汇编代码的部分。依旧需要手动改成数据后再改成代码,最后申明函数(参考第一种方法——IDA中手动改字节)
在这里插入图片描述

3. 010 Editor改PE文件

上面两种方法都是在反汇编好的基础上做修改,其实还可以直接用16进制编辑器,比如010 Editor,直接改字节码,改完后再反汇编,就省得再手动操作。

010 Editor为例,查找字节码74 03 C2 C7(查74 03可能有多个结果)。

如下:
在这里插入图片描述
ctrl+s保存一下,再放到ida,现在已经可以F5了。
在这里插入图片描述

二、花指令2

__asm {push eax;xor eax, eax;test eax, eax;jnz  LABEL1;jz LABEL2;LABEL1:_emit 0xE8;    //与call助记符的机器码相同LABEL2:mov byte ptr[a], 0;call LABEL3;_emit 0xFF;     //与adc助记符的字节码相同LABEL3:add dword ptr ss : [esp], 8;ret;__emit 0x11;mov byte ptr[a], 2;pop eax;}

加花指令2后的程序源码

//实现求n^{m}
#include<stdio.h>
#include<windows.h>
int a = 0;
int main()
{MessageBox(NULL, "加花指令2", "YQC", 0);//MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result=1;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);__asm {push eax;xor eax, eax;test eax, eax;jnz  LABEL1;jz LABEL2;LABEL1:_emit 0xE8;LABEL2:mov byte ptr[a], 0;call LABEL3;_emit 0xFF;LABEL3:add dword ptr ss : [esp], 8;ret;__emit 0x11;mov byte ptr[a], 2;pop eax;}for (int i = 0; i < m; i++)result *= n;printf("结果为%d", result);return 0;
}

(一)反汇编代码比对与分析

给出用IDA静态分析加花的程序的主函数部分而生成的反汇编代码,

.text:0045E3A0 ; int __cdecl main_0(int argc, const char **argv, const char **envp)
.text:0045E3A0 _main_0:                                ; CODE XREF: _main↑j
.text:0045E3A0                 push    ebp
.text:0045E3A1                 mov     ebp, esp
.text:0045E3A3                 sub     esp, 0F4h
.text:0045E3A9                 push    ebx
.text:0045E3AA                 push    esi
.text:0045E3AB                 push    edi
.text:0045E3AC                 lea     edi, [ebp-0F4h]
.text:0045E3B2                 mov     ecx, 3Dh ; '='
.text:0045E3B7                 mov     eax, 0CCCCCCCCh
.text:0045E3BC                 rep stosd
.text:0045E3BE                 mov     eax, ___security_cookie
.text:0045E3C3                 xor     eax, ebp
.text:0045E3C5                 mov     [ebp-4], eax
.text:0045E3C8                 mov     esi, esp
.text:0045E3CA                 push    0
.text:0045E3CC                 push    offset unk_510E50
.text:0045E3D1                 push    offset a2       ; "加花指令2"
.text:0045E3D6                 push    0
.text:0045E3D8                 call    ds:MessageBoxA
.text:0045E3DE                 cmp     esi, esp
.text:0045E3E0                 call    j___RTC_CheckEsp
.text:0045E3E5                 mov     dword ptr [ebp-24h], 1
.text:0045E3EC                 push    offset aNM      ; "请输入n和m:\n"
.text:0045E3F1                 call    sub_45748D
.text:0045E3F6                 add     esp, 4
.text:0045E3F9                 lea     eax, [ebp-18h]
.text:0045E3FC                 push    eax
.text:0045E3FD                 lea     ecx, [ebp-0Ch]
.text:0045E400                 push    ecx
.text:0045E401                 push    offset aDD      ; "%d%d"
.text:0045E406                 call    sub_4584E6
.text:0045E40B                 add     esp, 0Ch
.text:0045E40E                 push    eax
.text:0045E40F                 xor     eax, eax
.text:0045E411                 test    eax, eax
.text:0045E413                 jnz     short loc_45E417
.text:0045E415                 jz      short near ptr loc_45E417+1
.text:0045E417
.text:0045E417 loc_45E417:                             ; CODE XREF: .text:0045E413↑j
.text:0045E417                                         ; .text:0045E415↑j
.text:0045E417                 call    near ptr 7E81E9E2h
.text:0045E41C                 push    ebx
.text:0045E41C ; ---------------------------------------------------------------------------
.text:0045E41D                 db 2 dup(0), 0E8h
.text:0045E420                 dd 1, 48336FFh, 11C30824h
.text:0045E42C ; ---------------------------------------------------------------------------
.text:0045E42C                 mov     byte_537E3C, 2
.text:0045E433                 pop     eax
.text:0045E434                 mov     dword ptr [ebp-30h], 0
.text:0045E43B                 jmp     short loc_45E446
.text:0045E43D ; ---------------------------------------------------------------------------
.text:0045E43D
.text:0045E43D loc_45E43D:                             ; CODE XREF: .text:0045E458↓j
.text:0045E43D                 mov     eax, [ebp-30h]
.text:0045E440                 add     eax, 1
.text:0045E443                 mov     [ebp-30h], eax
.text:0045E446
.text:0045E446 loc_45E446:                             ; CODE XREF: .text:0045E43B↑j
.text:0045E446                 mov     eax, [ebp-30h]
.text:0045E449                 cmp     eax, [ebp-18h]
.text:0045E44C                 jge     short loc_45E45A
.text:0045E44E                 mov     eax, [ebp-24h]
.text:0045E451                 imul    eax, [ebp-0Ch]
.text:0045E455                 mov     [ebp-24h], eax
.text:0045E458                 jmp     short loc_45E43D
.text:0045E45A ; ---------------------------------------------------------------------------
.text:0045E45A
.text:0045E45A loc_45E45A:                             ; CODE XREF: .text:0045E44C↑j
.text:0045E45A                 mov     eax, [ebp-24h]
.text:0045E45D                 push    eax
.text:0045E45E                 push    offset aD_0     ; "结果为%d"
.text:0045E463                 call    sub_45748D
.text:0045E468                 add     esp, 8
.text:0045E46B                 xor     eax, eax
.text:0045E46D                 push    edx
.text:0045E46E                 mov     ecx, ebp
.text:0045E470                 push    eax
.text:0045E471                 lea     edx, dword_45E49C
.text:0045E477                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:0045E47C                 pop     eax
.text:0045E47D                 pop     edx
.text:0045E47E                 pop     edi
.text:0045E47F                 pop     esi
.text:0045E480                 pop     ebx
.text:0045E481                 mov     ecx, [ebp-4]
.text:0045E484                 xor     ecx, ebp
.text:0045E486                 call    j_@__security_check_cookie@4 ; __security_check_cookie(x)
.text:0045E48B                 add     esp, 0F4h
.text:0045E491                 cmp     ebp, esp
.text:0045E493                 call    j___RTC_CheckEsp
.text:0045E498                 mov     esp, ebp
.text:0045E49A                 pop     ebp
.text:0045E49B                 retn

比对一下两者前后的区别
在这里插入图片描述
分析这类汇编,需要先了解一下一些汇编转移指令callret的原理

1、call指令

(1)call + label

这个指令是先将call + 标号的下一条语句的IP放入栈中,然后使当前的IP+16位位移,相当于

push IP
jmp near ptr 标号
(2)call far ptr + label

这个指令是先将call指令的下一个指令的代码段地址入栈,再把call下一条指令的偏移地址入栈,然后使其跳到标号所在处,相当于

push CS
push IP
jmp far ptr 标号
(3)call + reg16

这个指令先将call的下一条指令的IP入栈,然后再以寄存器的值为IP的代码处

push IP
jmp reg16
(4)call word ptr + 内存单元地址

这个指令的是先将call指令的下一条指令的IP入栈,然后跳到以内存单元地址为IP的代码处

push IP
jum word ptr 内存单元地址
(5)call dword ptr + 内存单元地址

这个指令先将call指令的下一条指令的CS入栈,再将call指令的下一条指令的IP入栈,然后跳到以内存单元的高位为CS,低位为IP的代码处

push CS
push IP
jmp dword ptr 内存单元地址

2、ret指令

与上面的call指令对应把由call指令入栈的地址数据都出栈给(CS和)IP,相当于

(pop CS)
pop IP

现在分析这个花指令,

LABEL1标号的是干扰项,跟1号花指令效果一样,不再赘述。

直接从LABEL2开始分析,调用了函数LABEL3,把_emit 0xFF;的指令地址入栈(push IP),此时栈顶指针sp指向的是call指令的下一条指令的地址,即0xFF这个干扰项的地址,但执行add dword ptr ss : [esp], 8;给这个地址值加了8,指向了mov byte ptr[a], 2的地址,巧妙地修改了这个地址,所以接下来的ret指令将该指令的地址出栈到IP寄存器(pop IP),以至于在调用完LABEL3函数之后,下一个指令变成了mov byte ptr[a], 2,这样程序运行不会受到干扰项的影响。

__asm {push eax;xor eax, eax;test eax, eax;jnz  LABEL1;jz LABEL2;LABEL1:_emit 0xE8;           //与call助记符的字节码相同LABEL2:mov byte ptr[a], 0;call LABEL3;          //相当于push IP;jmp near ptr LABEL3_emit 0xFF;           //干扰项,与adc助记符的字节码相同LABEL3:add dword ptr ss : [esp], 8;   //sp寄存器(栈顶寄存器)的值(IP)自增8ret;__emit 0x11;          //干扰项mov byte ptr[a], 2;pop eax;}

在这里插入图片描述

(二)去花

在分析1号花指令的时候,我们得出结论:就这个程序而言,下面的代码基本可以看作是花指令存在的标志。

xor eax, eax         
test eax, eax       
je LABEL1           
jne LABEL2       

但要为了去花,需要确定花指令的具体位置,就当前这个花指令而言,我们注意到有一个push eax,然后紧跟着垃圾指令,所以推断最后势必有个pop eax,所以完全可以以push eax(0x50)为起始,pop eax(0x58)为中止,中间的代码全部nop,从而达到去花的目的。

1.反汇编器手动改字节

反汇编出如下情形,基于以上思想,可以在IDA中patch byte如下:
在这里插入图片描述
直接把push eax(0x50)到pop eax(0x58)都pop即可
在这里插入图片描述
申明成函数后,一键F5反编译成功。
在这里插入图片描述

2.IDC去花

确定nop的范围(以push eax(0x50)为起始,pop eax(0x58)为中止),运行下面脚本就可以去花了。

#include <idc.idc>
/*匹配字符串的函数*/
static matchBytes(StartAddr, Match) 
{ auto Len, i, PatSub, SrcSub; Len = strlen(Match);while (i < Len) { PatSub = substr(Match, i, i+1); SrcSub = form("%02X", Byte(StartAddr)); SrcSub = substr(SrcSub, i % 2, (i % 2) + 1); if (PatSub != "?" && PatSub != SrcSub)    //以问号作为匹配函数中止条件return 0;  if (i % 2 == 1) StartAddr++; i++; }return 1; 
}
static main() 
{ auto Addr, Start, End, Condition, i;Start = 0x45E3A0; //起始地址End = 0x45E49B;   //中止地址Condition = "5033C085C07502????";  //目标字符串for (Addr = Start; Addr < End; Addr++)    //遍历区域内字节码{ if (matchBytes(Addr, Condition)) { Message("Find FakeJmp Opcode!!\n");  for (i = 1; Byte(Addr+i)!=0x58; i++) //出现pop eax则停止patch{PatchByte(Addr+i, 0x90); //nop填充MakeCode(Addr+i); //反汇编转代码} } }AnalyzeArea(Start, End); Message("Clear FakeJmp Opcode Ok "); 
}

如下图所示,最后还要再申明一下函数就可以F5。
在这里插入图片描述

3. 010 Editor改PE文件

关于16进制编辑器的修改操作也是直接把那部分花指令的区域全部nop,这边不再赘述。

三、花指令3

__asm {push ebx;xor ebx, ebx;   test ebx, ebx;jnz LABEL5;jz	LABEL6;LABEL5:_emit 0x21;     //与and助记符的机器码相同LABEL6:pop ebx;}

加花指令3后的程序源码

//实现求n^{m}
#include<stdio.h>
#include<windows.h>
int a = 0;
int main()
{MessageBox(NULL, "加花指令3", "YQC", 0);//MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result=1;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);__asm {push ebx;xor ebx, ebx;test ebx, ebx;jnz LABEL5;jz	LABEL6;LABEL5:_emit 0x21;LABEL6:pop ebx;}for (int i = 0; i < m; i++)result *= n;printf("结果为%d", result);return 0;
}

(一)反汇编代码比对与分析

同样给出用IDA静态分析加花的程序的主函数部分而生成的反汇编代码。

.text:0045E3A0 ; int __cdecl main_0(int argc, const char **argv, const char **envp)
.text:0045E3A0 _main_0:                                ; CODE XREF: _main↑j
.text:0045E3A0                 push    ebp
.text:0045E3A1                 mov     ebp, esp
.text:0045E3A3                 sub     esp, 0F4h
.text:0045E3A9                 push    ebx
.text:0045E3AA                 push    esi
.text:0045E3AB                 push    edi
.text:0045E3AC                 lea     edi, [ebp-0F4h]
.text:0045E3B2                 mov     ecx, 3Dh ; '='
.text:0045E3B7                 mov     eax, 0CCCCCCCCh
.text:0045E3BC                 rep stosd
.text:0045E3BE                 mov     eax, ___security_cookie
.text:0045E3C3                 xor     eax, ebp
.text:0045E3C5                 mov     [ebp-4], eax
.text:0045E3C8                 mov     esi, esp
.text:0045E3CA                 push    0
.text:0045E3CC                 push    offset unk_510E50
.text:0045E3D1                 push    offset a3       ; "加花指令3"
.text:0045E3D6                 push    0
.text:0045E3D8                 call    ds:MessageBoxA
.text:0045E3DE                 cmp     esi, esp
.text:0045E3E0                 call    j___RTC_CheckEsp
.text:0045E3E5                 mov     dword ptr [ebp-24h], 1
.text:0045E3EC                 push    offset aNM      ; "请输入n和m:\n"
.text:0045E3F1                 call    sub_45748D
.text:0045E3F6                 add     esp, 4
.text:0045E3F9                 lea     eax, [ebp-18h]
.text:0045E3FC                 push    eax
.text:0045E3FD                 lea     ecx, [ebp-0Ch]
.text:0045E400                 push    ecx
.text:0045E401                 push    offset aDD      ; "%d%d"
.text:0045E406                 call    sub_4584E6
.text:0045E40B                 add     esp, 0Ch
.text:0045E40E                 push    ebx
.text:0045E40F                 xor     ebx, ebx
.text:0045E411                 test    ebx, ebx
.text:0045E413                 jnz     short loc_45E417
.text:0045E415                 jz      short near ptr loc_45E417+1
.text:0045E417
.text:0045E417 loc_45E417:                             ; CODE XREF: .text:0045E413↑j
.text:0045E417                                         ; .text:0045E415↑j
.text:0045E417                 and     [ebx-39h], ebx
.text:0045E41A                 inc     ebp
.text:0045E41B                 rol     byte ptr [eax], 1
.text:0045E41B ; ---------------------------------------------------------------------------
.text:0045E41D                 db 3 dup(0)
.text:0045E420 ; ---------------------------------------------------------------------------
.text:0045E420                 jmp     short loc_45E42B
.text:0045E422 ; ---------------------------------------------------------------------------
.text:0045E422
.text:0045E422 loc_45E422:                             ; CODE XREF: .text:0045E43D↓j
.text:0045E422                 mov     eax, [ebp-30h]
.text:0045E425                 add     eax, 1
.text:0045E428                 mov     [ebp-30h], eax
.text:0045E42B
.text:0045E42B loc_45E42B:                             ; CODE XREF: .text:0045E420↑j
.text:0045E42B                 mov     eax, [ebp-30h]
.text:0045E42E                 cmp     eax, [ebp-18h]
.text:0045E431                 jge     short loc_45E43F
.text:0045E433                 mov     eax, [ebp-24h]
.text:0045E436                 imul    eax, [ebp-0Ch]
.text:0045E43A                 mov     [ebp-24h], eax
.text:0045E43D                 jmp     short loc_45E422
.text:0045E43F ; ---------------------------------------------------------------------------
.text:0045E43F
.text:0045E43F loc_45E43F:                             ; CODE XREF: .text:0045E431↑j
.text:0045E43F                 mov     eax, [ebp-24h]
.text:0045E442                 push    eax
.text:0045E443                 push    offset aD_0     ; "结果为%d"
.text:0045E448                 call    sub_45748D
.text:0045E44D                 add     esp, 8
.text:0045E450                 xor     eax, eax
.text:0045E452                 push    edx
.text:0045E453                 mov     ecx, ebp
.text:0045E455                 push    eax
.text:0045E456                 lea     edx, dword_45E484
.text:0045E45C                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:0045E461                 pop     eax
.text:0045E462                 pop     edx
.text:0045E463                 pop     edi
.text:0045E464                 pop     esi
.text:0045E465                 pop     ebx
.text:0045E466                 mov     ecx, [ebp-4]
.text:0045E469                 xor     ecx, ebp
.text:0045E46B                 call    j_@__security_check_cookie@4 ; __security_check_cookie(x)
.text:0045E470                 add     esp, 0F4h
.text:0045E476                 cmp     ebp, esp
.text:0045E478                 call    j___RTC_CheckEsp
.text:0045E47D                 mov     esp, ebp
.text:0045E47F                 pop     ebp
.text:0045E480                 retn

给出用IDA静态分析加花的程序的主函数部分而生成的反汇编代码,
在这里插入图片描述
0x21对应操作码是and与操作,所以被ida当成了指令被反汇编成了指令and [ebx-39h], ebx,原理跟1号花指令异曲同工,所以直接进入去花阶段。

(二)去花

1.反汇编器手动改字节

在这里插入图片描述
再把后面的指令转化成数据再转化成代码,整理如下。
在这里插入图片描述
申明成函数后就可以F5了。

2.IDC去花

先确定nop的范围,我们注意到代码xor ebx, ebx;test ebx, ebx; jnz short loc_45E417; jz short near ptr loc_45E417+1前面有个 push ebx,那就以pop ebx为中止,中间代码为花指令全部nop。

#include <idc.idc>
static matchBytes(StartAddr, Match) 
{ auto Len, i, PatSub, SrcSub; Len = strlen(Match);while (i < Len) { PatSub = substr(Match, i, i+1); SrcSub = form("%02X", Byte(StartAddr)); SrcSub = substr(SrcSub, i % 2, (i % 2) + 1); if (PatSub != "?" && PatSub != SrcSub) return 0;  if (i % 2 == 1) StartAddr++; i++; }return 1; 
}
static main() 
{ auto Addr, Start, End, Condition, junk_len, i;Start = 0x0045E3A0; End = 0x0045E480;//"xor ebx, ebx;test ebx, ebx; jnz short loc_45E417;jz short loc_45E418"的字节码作为识别花指令的标识。Condition = "33DB85DB7502740121????";for (Addr = Start; Addr < End; Addr++) { if (matchBytes(Addr, Condition)) { Message("Find FakeJmp Opcode!!\n");Message(Addr);for (i = 1; Byte(Addr+i)!=0x21; i++);PatchByte(Addr+i, 0x90); MakeCode(Addr+i); } }AnalyzeArea(Start, End); Message("Clear Fake-Jmp Opcode Ok "); 
}

在这里插入图片描述

3. 010 Editor改PE文件

查找33DB85DB7502740121,然后改0x21为0x90即可
在这里插入图片描述

四、花指令4

跟3号和1号异曲同工,不再赘述。

void example4()
{__asm {push ebx;xor ebx, ebx;test ebx, ebx;jnz LABEL7;jz	LABEL8;LABEL7:_emit 0xC7;LABEL8:pop ebx;}a = 4;
}

五、花指令5

	__asm {call LABEL9;_emit 0x83;LABEL9:add dword ptr ss : [esp], 8;ret;__emit 0xF3;}

六、花指令6

    LoadLibrary("./hhhh");   //函数返回值存储于eax中_asm {cmp eax, 0;jc LABEL6_1;          //cf=1触发跳转jnc LABEL6_2;         //cf=0触发跳转LABEL6_1:_emit 0xE8;           //与call汇编指令对应LABEL6_2:}

加花指令6后的程序源码

//实现求n^{m}
#include<stdio.h>
#include<windows.h>
int a = 0;
int main()
{MessageBox(NULL, "加花指令6", "YQC", 0);//MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result=1;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);LoadLibrary("./hhhh");//函数返回值存储于eax中_asm {cmp eax, 0;jc LABEL6_1;jnc LABEL6_2;LABEL6_1:_emit 0xE8;LABEL6_2:}for (int i = 0; i < m; i++)result *= n;printf("结果为%d", result);return 0;
}

(一)反汇编代码比对与分析

给出用IDA静态分析加花的程序的主函数部分而生成的反汇编代码。

.text:0045E3A0 ; int __cdecl main_0(int argc, const char **argv, const char **envp)
.text:0045E3A0 _main_0:                                ; CODE XREF: _main↑j
.text:0045E3A0                 push    ebp
.text:0045E3A1                 mov     ebp, esp
.text:0045E3A3                 sub     esp, 0F4h
.text:0045E3A9                 push    ebx
.text:0045E3AA                 push    esi
.text:0045E3AB                 push    edi
.text:0045E3AC                 lea     edi, [ebp-0F4h]
.text:0045E3B2                 mov     ecx, 3Dh ; '='
.text:0045E3B7                 mov     eax, 0CCCCCCCCh
.text:0045E3BC                 rep stosd
.text:0045E3BE                 mov     eax, ___security_cookie
.text:0045E3C3                 xor     eax, ebp
.text:0045E3C5                 mov     [ebp-4], eax
.text:0045E3C8                 mov     esi, esp
.text:0045E3CA                 push    0
.text:0045E3CC                 push    offset unk_510E50
.text:0045E3D1                 push    offset a6       ; "加花指令6"
.text:0045E3D6                 push    0
.text:0045E3D8                 call    ds:MessageBoxA
.text:0045E3DE                 cmp     esi, esp
.text:0045E3E0                 call    j___RTC_CheckEsp
.text:0045E3E5                 mov     dword ptr [ebp-24h], 1
.text:0045E3EC                 push    offset aNM      ; "请输入n和m:\n"
.text:0045E3F1                 call    sub_45748D
.text:0045E3F6                 add     esp, 4
.text:0045E3F9                 lea     eax, [ebp-18h]
.text:0045E3FC                 push    eax
.text:0045E3FD                 lea     ecx, [ebp-0Ch]
.text:0045E400                 push    ecx
.text:0045E401                 push    offset aDD      ; "%d%d"
.text:0045E406                 call    sub_4584E6
.text:0045E40B                 add     esp, 0Ch
.text:0045E40E                 mov     esi, esp
.text:0045E410                 push    offset aHhhh    ; "./hhhh"
.text:0045E415                 call    ds:LoadLibraryA
.text:0045E41B                 cmp     esi, esp
.text:0045E41D                 call    j___RTC_CheckEsp
.text:0045E422                 cmp     eax, 0
.text:0045E425                 jb      short loc_45E429
.text:0045E427                 jnb     short near ptr loc_45E429+1
.text:0045E429
.text:0045E429 loc_45E429:                             ; CODE XREF: .text:0045E425↑j
.text:0045E429                                         ; .text:0045E427↑j
.text:0045E429                 call    near ptr 11629F5h
.text:0045E429 ; ---------------------------------------------------------------------------
.text:0045E42E                 dw 0
.text:0045E430                 dd 8B09EB00h, 0C083D045h, 0D0458901h, 3BD0458Bh, 0C7DE845h
.text:0045E430                 dd 0FDC458Bh, 89F445AFh, 0E3EBDC45h, 50DC458Bh
.text:0045E454 ; ---------------------------------------------------------------------------
.text:0045E454                 push    offset aD_0     ; "结果为%d"
.text:0045E459                 call    sub_45748D
.text:0045E45E                 add     esp, 8
.text:0045E461                 xor     eax, eax
.text:0045E463                 push    edx
.text:0045E464                 mov     ecx, ebp
.text:0045E466                 push    eax
.text:0045E467                 lea     edx, dword_45E494
.text:0045E46D                 call    j_@_RTC_CheckStackVars@8 ; _RTC_CheckStackVars(x,x)
.text:0045E472                 pop     eax
.text:0045E473                 pop     edx
.text:0045E474                 pop     edi
.text:0045E475                 pop     esi
.text:0045E476                 pop     ebx
.text:0045E477                 mov     ecx, [ebp-4]
.text:0045E47A                 xor     ecx, ebp
.text:0045E47C                 call    j_@__security_check_cookie@4 ; __security_check_cookie(x)
.text:0045E481                 add     esp, 0F4h
.text:0045E487                 cmp     ebp, esp
.text:0045E489                 call    j___RTC_CheckEsp
.text:0045E48E                 mov     esp, ebp
.text:0045E490                 pop     ebp
.text:0045E491                 retn

这个花指令属于利用API返回确定值,配合互补跳转语句和添加操作码作为干扰项实现反汇编的效果。
在这里插入图片描述
调用函数,返回值是放在eax中的,这个花指令调用了LoadLibrary函数,加载了一个实际不存在的名为hhhh的库,查询API档案如下,可以看出,这个函数必定返回0,且存入eax,也就是说cmp指令使进位标志寄存器cf=0,产生了确定值,即确定跳转。
在这里插入图片描述

(二)去花

1.反汇编器手动改字节

同样,改0xE8即可
在这里插入图片描述
申明成函数后然后可以F5
在这里插入图片描述

2.IDC去花

确定要nop的范围,直接cmp指令起始,到0xE8干扰项结束,即83 F8 00 72 02 73 01 E8

#include <idc.idc>
static matchBytes(StartAddr, Match) 
{ auto Len, i, PatSub, SrcSub; Len = strlen(Match);while (i < Len) { PatSub = substr(Match, i, i+1); SrcSub = form("%02X", Byte(StartAddr)); SrcSub = substr(SrcSub, i % 2, (i % 2) + 1); if (PatSub != "?" && PatSub != SrcSub) return 0;  if (i % 2 == 1) StartAddr++; i++; }return 1; 
}
static main() 
{ auto Addr, Start, End, Condition, junk_len, i;Start = 0x0045E3A0; End = 0x0045E491;Condition = "83F80072027301E8????";for (Addr = Start; Addr < End; Addr++) { if (matchBytes(Addr, Condition)) { Message("Find FakeJmp Opcode!!\n");Message(Addr);for (i = 0;Byte(Addr+i)!=0xE8; i++){PatchByte(Addr+i, 0x90); MakeCode(Addr+i); }PatchByte(Addr+i, 0x90); MakeCode(Addr+i); } }AnalyzeArea(Start, End); Message("Clear Fake-Jmp Opcode Ok "); 
}

在这里插入图片描述

3. 010 Editor改PE文件

先定位到花指令,然后跟ida中一样修改0xE8为0x90,保存后直接ida打开可以反汇编与反编译

七、花指令7

同样,确定标志位产生确定跳转,配合干扰项,不再赘述。

if (a > 0)return 1;elsereturn 0;_asm {cmp eax, 0;jc LABEL7_1;jz LABEL7_2;LABEL7_1:_emit 0xE8;LABEL7_2:}

八、花指令8(配合裸函数)

void __declspec(naked)__cdecl cnuF(int* a)//裸函数,开辟和释放堆栈由我们自己写。
{//55 8b ec 83__asm{/*保留栈底*/push ebp/*开辟栈空间*/mov ebp, espsub esp, 0x40//0x40是缓冲区大小/*保留现场(寄存器状态)*/push ebxpush esipush edi/*缓冲区写入数据*/mov eax, 0xCCCCCCCC    //0xCCCC在gb2312中是'烫'字mov ecx, 0x10          //cx为下面填'烫'操作计数lea edi, dword ptr ds : [ebp - 0x40]rep stos dword ptr es : [edi]}/*执行的操作*/*a = 1;//花指令_asm    {call LABEL9;_emit 0xE8;_emit 0x01;_emit 0x00;_emit 0x00;_emit 0x00;LABEL9:push eax;push ebx;lea  eax, dword ptr ds : [ebp - 0x0]add dword ptr ss : [eax - 0x50], 26;pop eax;pop ebx;pop eax;jmp eax;__emit 0xE8;_emit 0x03;_emit 0x00;_emit 0x00;_emit 0x00;mov eax, dword ptr ss : [esp - 8];}__asm{/*恢复现场*/pop edipop esipop ebx/*释放栈空间*/mov esp, ebppop ebpret}
}

无函数返回值的裸函数中加花后的源程序源码如下

//实现求n^{m}
#include<stdio.h>
#include<windows.h>
int a = 0;
void __declspec(naked)__cdecl cnuF(int* a)//裸函数,开辟和释放堆栈由我们自己写。
{//55 8b ec 83__asm{/*保留栈底*/push ebp/*开辟栈空间*/mov ebp, espsub esp, 0x40   //0x40是缓冲区大小/*保留现场(寄存器状态)*/push ebxpush esipush edi/*缓冲区写入数据*/mov eax, 0xCCCCCCCC    //0xCCCC在gb2312中是'烫'字mov ecx, 0x10          //cx为下面填'烫'操作计数lea edi, dword ptr ds : [ebp - 0x40]rep stos dword ptr es : [edi]  //用烫填充}/*执行的操作*/*a = 1;MessageBox(NULL, "加花指令8", "YQC", 0);//MessageBox(NULL, "未加花指令", "YQC", 0);int n, m, result, i;printf("请输入n和m:\n");scanf_s("%d%d", &n, &m);/*花指令*/_asm{call LABEL9;_emit 0xE8;    //垃圾指令_emit 0x01;_emit 0x00;_emit 0x00;_emit 0x00;LABEL9:push eax;push ebx;lea  eax, dword ptr ds : [ebp - 0x0]add dword ptr ss : [eax - 0x50], 26;pop eax;pop ebx;pop eax;jmp eax;__emit 0xE8;_emit 0x03;_emit 0x00;_emit 0x00;_emit 0x00;mov eax, dword ptr ss : [esp - 8];}for (result = 1, i = 0; i < m; i++)result *= n;printf("结果为%d", result);__asm{/*恢复现场*/pop edipop esipop ebx/*释放栈空间*/mov esp, ebppop ebpret}}
int main()
{cnuF(&a);return 0;
}

(一)反汇编代码比对与分析

给出用加花的程序的关键函数部分的反汇编代码。

.text:004613F0 sub_4613F0      proc near               ; CODE XREF: sub_45A8EF↑j
.text:004613F0
.text:004613F0 var_14          = byte ptr -14h
.text:004613F0 var_8           = byte ptr -8
.text:004613F0 arg_0           = dword ptr  8
.text:004613F0
.text:004613F0                 push    ebp
.text:004613F1                 mov     ebp, esp
.text:004613F3                 sub     esp, 40h
.text:004613F6                 push    ebx
.text:004613F7                 push    esi
.text:004613F8                 push    edi
.text:004613F9                 mov     eax, 0CCCCCCCCh
.text:004613FE                 mov     ecx, 10h
.text:00461403                 db      3Eh
.text:00461403                 lea     edi, [ebp-40h]
.text:00461407                 rep stosd
.text:00461409                 mov     eax, [ebp+arg_0]
.text:0046140C                 mov     dword ptr [eax], 1
.text:00461412                 mov     esi, esp
.text:00461414                 push    0               ; uType
.text:00461416                 push    offset Caption  ; "YQC"
.text:0046141B                 push    offset Text     ; "加花指令8"
.text:00461420                 push    0               ; hWnd
.text:00461422                 call    ds:MessageBoxA
.text:00461428                 cmp     esi, esp
.text:0046142A                 call    j___RTC_CheckEsp
.text:0046142F                 push    offset aNM      ; "请输入n和m:\n"
.text:00461434                 call    sub_45748D
.text:00461439                 add     esp, 4
.text:0046143C                 lea     eax, [ebp+var_14]
.text:0046143F                 push    eax
.text:00461440                 lea     ecx, [ebp+var_8]
.text:00461443                 push    ecx
.text:00461444                 push    offset aDD      ; "%d%d"
.text:00461449                 call    sub_4584E6
.text:0046144E                 add     esp, 0Ch
.text:00461451                 call    sub_46145B
.text:00461456                 call    sub_46145C
.text:00461456 sub_4613F0      endp ; sp-analysis failed
.text:00461456
.text:0046145B
.text:0046145B ; =============== S U B R O U T I N E =======================================
.text:0046145B
.text:0046145B
.text:0046145B sub_46145B      proc near               ; CODE XREF: sub_4613F0+61↑p
.text:0046145B                 push    eax
.text:0046145B sub_46145B      endp ; sp-analysis failed
.text:0046145B
.text:0046145C
.text:0046145C ; =============== S U B R O U T I N E =======================================
.text:0046145C
.text:0046145C
.text:0046145C sub_46145C      proc near               ; CODE XREF: sub_4613F0+66↑p
.text:0046145C                 push    ebx
.text:0046145D                 db      3Eh
.text:0046145D                 lea     eax, [ebp+0]
.text:00461461                 add     dword ptr ss:[eax-50h], 1Ah
.text:00461466                 pop     eax
.text:00461467                 pop     ebx
.text:00461468                 pop     eax
.text:00461469                 jmp     eax
.text:00461469 sub_46145C      endp ; sp-analysis failed
.text:00461469
.text:0046146B ; ---------------------------------------------------------------------------
.text:0046146B                 call    loc_461473
.text:0046146B ; ---------------------------------------------------------------------------
.text:00461470                 db 36h, 8Bh, 44h
.text:00461473 ; ---------------------------------------------------------------------------
.text:00461473
.text:00461473 loc_461473:                             ; CODE XREF: .text:0046146B↑j
.text:00461473                 and     al, 0F8h
.text:00461475                 mov     dword ptr [ebp-20h], 1
.text:0046147C                 mov     dword ptr [ebp-2Ch], 0
.text:00461483                 jmp     short loc_46148E
.text:00461485 ; ---------------------------------------------------------------------------
.text:00461485
.text:00461485 loc_461485:                             ; CODE XREF: .text:004614A0↓j
.text:00461485                 mov     eax, [ebp-2Ch]
.text:00461488                 add     eax, 1
.text:0046148B                 mov     [ebp-2Ch], eax
.text:0046148E
.text:0046148E loc_46148E:                             ; CODE XREF: .text:00461483↑j
.text:0046148E                 mov     eax, [ebp-2Ch]
.text:00461491                 cmp     eax, [ebp-14h]
.text:00461494                 jge     short loc_4614A2
.text:00461496                 mov     eax, [ebp-20h]
.text:00461499                 imul    eax, [ebp-8]
.text:0046149D                 mov     [ebp-20h], eax
.text:004614A0                 jmp     short loc_461485
.text:004614A2 ; ---------------------------------------------------------------------------
.text:004614A2
.text:004614A2 loc_4614A2:                             ; CODE XREF: .text:00461494↑j
.text:004614A2                 mov     eax, [ebp-20h]
.text:004614A5                 push    eax
.text:004614A6                 push    offset aD_0     ; "结果为%d"
.text:004614AB                 call    sub_45748D
.text:004614B0                 add     esp, 8
.text:004614B3                 pop     edi
.text:004614B4                 pop     esi
.text:004614B5                 pop     ebx
.text:004614B6                 mov     esp, ebp
.text:004614B8                 pop     ebp
.text:004614B9                 retn

这个程序的花指令是放到裸函数中的方式,先简单了解一下裸函数

裸函数

对于一个裸函数而言,就是编译器不会为这个函数生成代码,如开辟和释放栈空间还有ret,这些指令在裸函数中都需要我们自己写,且最后一定不能缺少ret指令。
一般在函数名前面加上 __deplspec(naked),此时这个函数便是裸函数,同时编译器对裸函数也不会进行任何处理。
下面以实现两个传入参数相加的功能为例给出不同裸函数的基本框架(如果对这些指令不是很理解可以参考堆栈图):

(1)无参数无返回值的函数框架
void __declspec(naked) Fun(){__asm{//提升堆栈push ebpmov ebp,espsub ebp,0x40//保护现场push ebxpush esipush edi//向缓冲区填充数据lea edi,dword ptr ds:[ebp-0x40]mov eax,0xCCCCCCCCmov ecx,0x10rep stosd  ;rep stos dword ptr es:[edi]//恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp//返回函数调用前的下一行地址ret}
}
(2)有参数有返回值的函数框架
int __declspec(naked) plus(int x, int y)
{__asm{//提升堆栈push ebpmov ebp,espsub esp,0x40//保护现场push ebxpush esipush edi//向缓冲区填充数据lea edi,dword ptr ds:[ebp-0x40]mov eax,0xCCCCCCCCmov ecx,0x10rep stos dword ptr es:[edi]//函数核心功能块mov eax,dword ptr ds:[ebp+0x8]add eax,dword ptr ds:[ebp+0xC]//恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp//返回函数调用前的下一行地址ret}
}
(3)带局部变量的函数框架
int __declspec(naked) plus(int x, int y)
{__asm{//提升堆栈push ebpmov ebp,espsub esp,0x40//保护现场push ebxpush esipush edi//向缓冲区填充数据lea edi,dword ptr ds:[ebp-0x40]mov eax,0xCCCCCCCCmov ecx,0x10rep stos dword ptr es:[edi]//局部变量入栈mov dword ptr ds:[ebp-0x4]mov dword ptr ds:[ebp-0x8]//函数核心功能块mov eax,dword ptr ds:[ebp+0x8]add eax,dword ptr ds:[ebp+0xC]//恢复现场pop edipop esipop ebx//降低堆栈mov esp,ebppop ebp//返回函数调用前的下一行地址ret}
}

下面用OD分析花指令,从call LABEL9处单步执行,注意观察,如下图。

对call入栈的指令地址进行了修改
在这里插入图片描述
修改之后变成mov eax, dword ptr ss : [esp - 8];(在OD中没有反汇编成功)的地址
在这里插入图片描述
一共三次出栈操作,第三次是将修改后的指令地址出栈到eax,下面有个jmp无条件跳转语句,程序自动跳到mov eax, dword ptr ss : [esp - 8];,绕过垃圾指令
在这里插入图片描述

(二)去花

1.反汇编器手动改字节

在这里插入图片描述

在这里插入图片描述
然后再把位于jmp eax下面的call语句nop掉,
在这里插入图片描述
这个函数依旧会报红,直接把这个函数全选,然后按u重新变成数据,最后再cp,变成代码并申明函数即可。
在这里插入图片描述
效果如下,
在这里插入图片描述
但光这样会出现问题就是因为jmp eax的存在,反汇编引擎不知道跳转的位置,所以部分代码会丢失,被分隔开,产生如下情况;
在这里插入图片描述
所以还需要把jmp eaxnop填充掉,这样就可以F5了
在这里插入图片描述

2.IDC去花

确定要nop的范围:从call LABEL9开始到第二个垃圾指令全部nop

#include <idc.idc>
static matchBytes(StartAddr, Match) 
{ auto Len, i, PatSub, SrcSub; Len = strlen(Match);while (i < Len) { PatSub = substr(Match, i, i+1); SrcSub = form("%02X", Byte(StartAddr)); SrcSub = substr(SrcSub, i % 2, (i % 2) + 1); if (PatSub != "?" && PatSub != SrcSub) return 0;  if (i % 2 == 1) StartAddr++; i++; }return 1; 
}
static main() 
{ auto Addr, Start, End, Condition, junk_len, i;Start = 0x004613F0; End = 0x004614B9;Condition = "E805000000E801000000????";for (Addr = Start; Addr < End; Addr++) { if (matchBytes(Addr, Condition)) { Message("Find FakeJmp Opcode!!\n");for (i = 0;!matchBytes(Addr+i,"368B44????"); i++){PatchByte(Addr+i, 0x90); MakeCode(Addr+i); }} }AnalyzeArea(Start, End); Message("Clear Fake-Jmp Opcode Ok "); 
}

在这里插入图片描述
最后再重新反汇编处理一下

3.010 Editor修改

按照反汇编器中修改的方式修改即可

http://www.xdnf.cn/news/811009.html

相关文章:

  • PHP包含文件函数include、include_once、require、require_once区别总结
  • 【学习笔记】AD中PCB泪滴设计
  • ms08-067漏洞复现
  • 半监督之mixmatch
  • SHFileOperation复制文件夹、文件用法
  • 半透明AlphaBlend
  • Android移动应用开发教程①
  • Html5游戏框架createJs组件--EaselJS(一)
  • [转]FastDb介绍
  • 位运算的基础知识
  • C++图像缩放(StretchBlt,StretchDIBits,双线性内插法)
  • 软件测试面试及笔试题
  • 【Dom4j】Dom4j完整教程详解
  • 盘点日本人最常用的50个网站
  • tp-link无线网卡linux下的驱动,Ubuntu14下安装无线网卡驱动(TP-LINK TL-WN823N)
  • Visual Studio2010 简体中文含MSDN版本下载地址
  • You-Get 就是这么强势!
  • android的m、mm、mmm编译命令的使用
  • 什么是公网、私网、内网、外网?
  • 使用FileZilla等软件搭建ftp服务器
  • android高级面试题(二)
  • 校园后勤设备保修维护管理系统
  • 递推算法题:令人费解的开关『拉灯』
  • 安卓开发中JDK、SDK、NDK、ADT、ANT等概念作用解释
  • linux命令行怎么结束进程,linux结束进程命令
  • 你必须弄懂的Intent Filter匹配规则
  • C#命令行编辑器csc.exe
  • 基于stm32物联网开发板(3)--SYN6288语音模块
  • 《恐怖丛林生存》肉搏攻略,解开星星系统之谜
  • 电脑提示错误代码0xc000007b该怎么解决,几种解决办法