zoukankan      html  css  js  c++  java
  • windows花指令和堆栈溢出原理

    1、今天拿到一个exe,用IDA打开后在main的代码如下,想直接F5,报错如下:

         细看代码,有两个比较有意思的地方:

    •    第一个红框,JZ和JNZ跳转到同一个地址:0x4010A1+1=0x4010A2
    •    第二个红框,也就是0x4010A1的开始地址是一个call指令,5字节长度;再下一个指令就从0x4010A6开始了;
    •    0x4010A1处指令call的跳转地址是0x52285E33h,这个明显比用户空间大很多:用户空间一般从0x00400000,很难直接跳转到0x52285E33h;事实上,从IDA看,.text段在0x00413FE0就已经结束了,所以这里的跳转地址肯定有问题(IDA也标红处理)

          综合,0x4010A2就不是指令的入口地址,这里遇到花指令了;

        

     2、选中call指令,右键“D”转成db数据,如下:

        

      既然jz和jnz的目的地都是0x4010A2,那就从0x4010A2开始选中剩余db代码,右键“Analyze selected area”,如下:

         

       终于看到了“庐山真面目”:0x4010A2原来是个lea指令,前面哪个0xe8彻底没用了;

       

     直接把原0xe8打patch,改成0x90,也就是NOP,避免影响其他指令的执行,如下:

      

      随后同样选中0x90,右键analyze seleced area,转成nop指令;最后快捷键P还原成完整的函数;

     

        往上,有个函数执行了system("cmd")代码,这里可以获取shell,先把函数改名cmd_shell;

        

        4、先在重点分析main函数,从第1行代码开始:

    (1)这个简单,就是保存原ebp,然后开辟58h的栈空间,最后赋初事值0xcc

    .text:00401070                 push    ebp
    .text:00401071                 mov     ebp, esp
    .text:00401073                 sub     esp, 58h
    .text:00401076                 push    ebx
    .text:00401077                 push    esi
    .text:00401078                 push    edi
    .text:00401079                 lea     edi, [ebp-58h]
    .text:0040107C                 mov     ecx, 16h
    .text:00401081                 mov     eax, 0CCCCCCCCh
    .text:00401086                 rep stosd

    (2)紧接着从ebp-0x14到ebp-0x4赋值0;

    text:00401088                 mov     dword ptr [ebp-14h], 0
    .text:0040108F                 xor     eax, eax
    .text:00401091                 mov     [ebp-10h], eax
    .text:00401094                 mov     [ebp-0Ch], eax
    .text:00401097                 mov     [ebp-8], eax
    .text:0040109A                 mov     [ebp-4], eax

    (3)花指令的这几行代码直接略过,到了最关键的代码之一:scanf   这里直接把用户输入的数字保存在ebp-0x18单元中

    .text:004010A2                 lea     ecx, [ebp-18h]  ; 用户通过scanf输入的数字保存在ebp-0x18这里,比如输入6
    .text:004010A5                 push    ecx
    .text:004010A6                 push    offset aD       ; "%d"
    .text:004010AB                 call    _scanf
    .text:004010B0                 add     esp, 8

          紧接着把用户输入的数字*4后减去0x14h作为偏移,ebp作为基址,写入cmd_shell函数的入口地址;

    .text:004010B3                 mov     edx, [ebp-18h]  ; edx=6
    .text:004010B6                 mov     dword ptr [ebp+edx*4-14h], offset cmd_shell

           这个程序中最大的漏洞就在这里了:稍微有点windows32位逆向经验的同学都知道,整个栈都是用ebp加减常数来寻址的,比如ebp+4是函数调用前上个帧的ebp地址;ebp+8是函数调用完的返回地址,ebp+12开始是函数参数;ebp自身开始时函数的局部变量,空间是esp减去常数分配的;具体到这个程序,如果用户输入6,也就是edx=6,那么ebp+edx*4-14h=ebp+8,刚好是main函数的返回地址。如果这里用cmd_shell的地址覆盖,一旦main执行完,就会跳转到cmd_shell执行,这就是传说中的栈溢出(如果这是个网络服务,黑客完全可以精心构造一段字符串发送过来得到反弹shell);完全绕开了原来的跳转流程;前面所有代码执行完后的堆栈示意图如下:

              

           代码执行的效果:输入6以后,马上得到当前目录的shell;通过whoami查询发现是administrator权限,也能查看当前目录的文件;

          

     5、程序完整的C代码如下:

    #include "stdafx.h"
    #include "stdlib.h"
    
    void shell(){
        system("cmd");
    }
    
    int main(int argc, char* argv[])
    {
        int a[5]={0};
        int x;
        _asm{
            jz label;
            jnz label;
            _emit 0xE8;
    label:
        }
        scanf("%d",&x);
        //a[x] = (int)&shell;
        a[x] = (int)shell;
        printf("Hello World!
    ");
        return 0;
    }

    参考:

    1、https://www.bilibili.com/video/BV1mK411A75G?from=search&seid=10691647714478259112   花指令patch与原理分析

  • 相关阅读:
    VUE vue和element框架搭配实现导航跳转,底部导航跳转页面
    【HDFS篇14】HA高可用 --- Federation架构设
    【HDFS篇13】HA高可用 --- YARN-HA集群配置
    【HDFS篇12】HA高可用 --- HDFS-HA集群配置
    【HDFS篇11】HA高可用
    【HDFS篇10】DataNode相关概念
    【HDFS篇09】集群安全模式
    【HDFS篇08】NameNode故障处理
    【HDFS篇07】NameNode和SecondearyNameNode
    【HDFS篇06】HDFS数据读写流程
  • 原文地址:https://www.cnblogs.com/theseventhson/p/13933230.html
Copyright © 2011-2022 走看看