• 花指令


    刚在52破解看了一篇花指令的文章,感觉挺好的。

    第一种花指令是jmp+垃圾数据

    比如

    jmp label

    //这里存放垃圾指令或数据

    label:

    //正常指令

    push ebp

    mov ebp,esp

    第二种是假分支跳转

     xor eax, eax;        

     test eax, eax;        

     jnz  LABEL1;     

      jz LABEL2;

     

    xor eax,eax这让eax为0,逻辑运算指令会影响ZF标志位的,所以会置ZF为1,那么永远会跳转到LABEL2处,这样LABEL1处的代码全部是垃圾指令,不管看起来多么正常,统统都是垃圾指令。

    第三种是call和retn配合,看起来好像调用了一个函数,但实际上啥事也没做就返回了。

    我写了一段测试代码。

    int main(int argc, char* argv[])
    {
    	
    	printf("hello world");
    	int a;
        __asm {
            call LABEL9;
            _emit 0x55;
    		_emit 0x8b;
    		_emit 0xec;
    		_emit 0xff;
    		_emit 0x83;
    		_emit 0xec;
    		_emit 0xc;
        LABEL9:
            add dword ptr ss : [esp], 0x0D;
            ret;
            __emit 0xF3;
        }
        
    	a = 3;
    
    
    
    return 0;
    
    }
    

      

            _emit 0x55;
    		_emit 0x8b;
    		_emit 0xec;
    		_emit 0xff;
    		_emit 0x83;
    		_emit 0xec;
    		_emit 0xc;
    这中间有_emit的都是垃圾数据,干扰分析者的。
    我们真正有效的代码就是
    int a;
    a=3;
    return 0;
    没了。
     
    add dword ptr ss : [esp], 0x0D;

    这个改变函数返回地址的,调用完call Lable9之后,栈顶会存放函数的返回地址,也就是_emit 0x8b这个数据的地址。由于是垃圾数据,我们必须不能让它返回到这个地址,要改一下

    改到下一句有效代码的地址处,也就是a=3;这句代码的地址,那么就需要让返回地址加一个值,加多少呢?这个我是反汇编之后用OLLYDBG调试之后算出来的。具体看一下下面的图

    0040D708   .  68 6C2F4200                push tes22.00422F6C                      ; /Arg1 = 00422F6C ASCII "hello world"
    0040D70D   .  E8 5EFFFFFF                call tes22.0040D670                      ; 	es22.0040D670
    0040D712   .  83C4 04                    add esp,0x4
    0040D715   .  E8 07000000                call tes22.0040D721
    0040D71A   .  55                         push ebp
    0040D71B   .  8BEC                       mov ebp,esp
    0040D71D      FF                         db FF
    0040D71E   .  83EC 0C                    sub esp,0xC
    0040D721   .  36:830424 0D               add dword ptr ss:[esp],0xD
    0040D726   .  C3                         retn
    0040D727   ?  f3:c745 fc 03000000        rep mov dword ptr ss:[ebp-0x4],0x3

    调用完call 0040D721时,栈顶的返回地址是0040D71A,我们想让它返回到0040D727这个正常的地方,0040D727-0040D71A=0x0D,也就是说返回地址需要+0xD

    这就是

    add dword ptr ss:[esp],0xD 这句代码中为什么要加0xD的原因,加多少是和你添加的垃圾数据有关系的,你加的数据越多,这个值就越大。

    有个问题,0xD这个值是我编译之后查看Ollydbg才算出来的,能不能在编写程序的时候就可以知道,这个地方不会呀。



    这种干扰效果还是比较明显的。我们看一下在IDA中的效果。
    0040D708                 push    offset aHelloWorld ; "hello world"
    .text:0040D70D                 call    _printf
    .text:0040D712                 add     esp, 4
    .text:0040D715                 call    near ptr loc_40D71D+4
    .text:0040D71A                 push    ebp
    .text:0040D71B                 mov     ebp, esp
    .text:0040D71D
    .text:0040D71D loc_40D71D:                             ; CODE XREF: _main_0+25p
    .text:0040D71D                 inc     dword ptr [ebx-7CC9F314h]
    .text:0040D71D _main_0         endp ; sp-analysis failed
    .text:0040D71D
    .text:0040D723                 add     al, 24h
    .text:0040D725                 or      eax, 45C7F3C3h
    .text:0040D72A                 cld
    .text:0040D72B                 add     eax, [eax]
    .text:0040D72B ; ---------------------------------------------------------------------------
    .text:0040D72D                 db 2 dup(0), 33h
    .text:0040D730 ; ---------------------------------------------------------------------------
    .text:0040D730                 rcr     byte ptr [edi+5Eh], 5Bh
    .text:0040D734                 add     esp, 44h
    .text:0040D737                 cmp     ebp, esp
    .text:0040D739                 call    __chkesp
    .text:0040D73E                 mov     esp, ebp
    .text:0040D740                 pop     ebp
    .text:0040D741                 retn

    是不是感觉特别乱呀,花指令就是这种效果,让你感觉很烦。




    还有一种是也是看似分支跳转实际上是无条件跳转
    #include "stdafx.h"
    #include "windows.h"
    int main(int argc, char* argv[])
    {
        int a;
        printf("hello world");
            LoadLibrary("fldsjfljsfljsflsjflsjfl");
        __asm{
            cmp eax, 0;
            jc LABEL6_1;
            jnc LABEL6_2;
        LABEL6_1:
            _emit 0xE8;
        LABEL6_2:
        }
        a = 41;
    
    
    
    return 0;
    
    }

    用LoadLibrary加载一个文件,这个文件很明显不管是谁的电脑上都不可能存在的一个文件,那么返回值一定是0,也就是说cmp eax,0的结果一定是0,也就是一定不会产生进位后者借位

    ,也就是CF标志位一定不会置1,也就是LABEL6_1的流程永远不会到达,那么Lable6_1的代码就是垃圾代码。我曾经遇到过这种花指令。当时很头疼就放下了。今天自己调试了一遍,感觉我有可以了。

    看一下在OD中的效果。

    0040D708   .  68 6C2F4200   push tes22.00422F6C                          ; /Arg1 = 00422F6C ASCII "hello world"
    0040D70D   .  E8 5EFFFFFF   call tes22.0040D670                          ; 	es22.0040D670
    0040D712   .  83C4 04       add esp,0x4
    0040D715   .  8BF4          mov esi,esp
    0040D717   .  68 A82F4200   push tes22.00422FA8                          ; /FileName = "fldsjfljsfljsflsjflsjfl"
    0040D71C   .  FF15 6CA14200 call dword ptr ds:[<&KERNEL32.LoadLibraryA>] ; LoadLibraryA
    0040D722   .  3BF4          cmp esi,esp
    0040D724   .  E8 3739FFFF   call tes22.00401060
    0040D729   .  83F8 00       cmp eax,0x0
    0040D72C   .  72 02         jb short tes22.0040D730
    0040D72E   .  73 01         jnb short tes22.0040D731
    0040D730   >  E8 C745FC29   call 2A3D1CFC
    0040D735   ?  0000          add byte ptr ds:[eax],al
    0040D737   ?  0033          add byte ptr ds:[ebx],dh
    0040D739   ?  c05f 5e 5b    rcr byte ptr ds:[edi+0x5e],0x5b
    0040D73D   .  83C4 44       add esp,0x44
    0040D740   .  3BEC          cmp ebp,esp
    0040D742   .  E8 1939FFFF   call tes22.00401060
    0040D747   .  8BE5          mov esp,ebp

    看下在IDA中的效果,和在OD中的效果差不多。

  • 相关阅读:
    Java实现币值最大化问题
    Java实现币值最大化问题
    Java实现币值最大化问题
    Java实现币值最大化问题
    ddd
    雷军:小米最坏的时候已过去 2017目标营收千亿(确实有些新意)
    真正的转变从不确定中来
    很多人知道自己的斤两,他之所以抱怨工资低,不是觉得薪水和自己的能力不匹配,而是因为工资确实不够用(笑死了)
    CodeSmith
    sb2-admin
  • 原文地址:https://www.cnblogs.com/yfish/p/15356139.html
Copyright © 2020-2023  润新知