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与原理分析

  • 相关阅读:
    Flutter form 的表单 input
    FloatingActionButton 实现类似 闲鱼 App 底部导航凸起按钮
    Flutter 中的常见的按钮组件 以及自 定义按钮组件
    Drawer 侧边栏、以及侧边栏内 容布局
    AppBar 自定义顶部导航按钮 图标、颜色 以及 TabBar 定义顶部 Tab 切换 通过TabController 定义TabBar
    清空路由 路由替换 返回到根路由
    应对ubuntu linux图形界面卡住的方法
    [转] 一块赚零花钱
    [转]在树莓派上搭建LAMP服务
    ssh保持连接
  • 原文地址:https://www.cnblogs.com/theseventhson/p/13933230.html
Copyright © 2011-2022 走看看