欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]4.堆溢出和COM漏洞寻找

[原创]4.堆溢出和COM漏洞寻找

堆溢出

  • 案例代码
#include "stdafx.h"

#include <string.h>

#include <stdlib.h>

#include <windows.h>

#include <iostream.h>

struct tagNode

{

    char szName[8];

  struct tagNode *pNext;

};

struct tagTest

{

  short Magic;

  short nLength;

  char *szBuf;

};

void test(char *szPwd)

{

  tagNode *pHead = NULL; 

  tagNode *pNode = NULL; 

  FILE *fp = NULL;

  fp = fopen("name.txt", "r+");

  if (fp == NULL)

  {

    exit(-1);

  }

  int nRet = EOF;

  for (int i = 0; i < 3; i++)

  {

    pNode = new struct tagNode;

    nRet = fscanf(fp, "%s", pNode->szName);

    pNode->pNext = pHead;

    pHead = pNode;

  }

  for (pNode = pHead; pNode != NULL; pNode = pNode->pNext)

  {

    printf("%s\r\n", pNode->szName);

  }

  pNode = pHead;

  fscanf(fp, "%s", pNode->szName);

  pNode = pHead->pNext;

  fscanf(fp, "%s", pNode->szName);

  for (pNode = pHead; pNode != NULL; pNode = pNode->pNext)

  {

    printf("%s\r\n", pNode->szName);

  }

  if (fp)

  {

    fclose(fp);

    fp = NULL;

  }

}

int main(int argc, char* argv[])

{

  char szPwd[] = "Hello";

  test(szPwd);

  system("pause");

  return 0;

}

  • 先观察代码
    可以得到一个类似结构得链表,如果在这里溢出修改pNext的话,因为fscanf结束后,还有pNode->pNext = pHead,会还原回去所以这里不行。

    for (int i = 0; i < 3; i++)
    
    {
    
      pNode = new struct tagNode;
    
      nRet = fscanf(fp, "%s", pNode->szName);
    
      pNode->pNext = pHead;
    
      pHead = pNode;
    
    }
    
    


    这句代码的作用就是输入,没用写入的机会,所以也没用

    for (pNode = pHead; pNode != NULL; pNode = pNode->pNext)
    
    {
    
      printf("%s\r\n", pNode->szName);
    
    }
    
    

    而这两句代码能够溢出数据,并且不会被写回,这里解释下为什么非要溢出改pNext,如果仅仅只是溢出数据,那么任何一个fscanf(fp, "%s", pNode->szName);这样的写法都能够随便溢出,但是我们缺少能够执行我们shellcode的机会。第一个fscanf修改我们要第二次要写入数据的位置。第二个fscanf
    会写入第二次数据,这次我们把数据写到哪里,能够有机会执行,又能够有写的权限?

    pNode = pHead;
    
    fscanf(fp, "%s", pNode->szName);
    
    pNode = pHead->pNext;
    
    fscanf(fp, "%s", pNode->szName);
    
    

    继续看,下面调用了两个函数,printffclose
    例如:printf里面会调用WriteFileReadFile等api
    fclose会调用CloseHandle等api,感兴趣的话可以OD自己跟进去看
    如果这些api通过IAT表调用的话,那么我们第二次写入的shellcode放入api在IAT表的地址,那么不就会执行到我们的shellcode吗?

    for (pNode = pHead; pNode != NULL; pNode = pNode->pNext)
    
    {
    
      printf("%s\r\n", pNode->szName);
    
    }
    
    if (fp)
    
    {
    
      fclose(fp);
    
      fp = NULL;
    
    }
    
    
  • 进入printf函数查看间接调用的API
    看到了WriteFile

    也可以用访问断点来查看是否调用

    发现有间接访问

    记录下
    00430250 >76C83ED3  kernel32.ReadFile
    
    
  • 编写读入的数据
    fscanf遇到\x0D\x0A\x0C....会被截断

    第一个循环构造的链表
    ![]
    接下来是我们定位的溢出位置的第一次执行,把ReadFileIAT地址给写进去

    crtl+g过去看发现是我们api地址

    写进去了但是崩溃了为什么呢?
    因为call 这个地址跳过去一个不对的地址肯定崩

    红框就是填写shllecode地址,正好是写入位置+4

    在这个地址下硬件执行断点,发现可以来一切正常

寻找Com组件的漏洞

  • 寻找com漏洞工具
  1. 查看所有的com组件 COM Explorer
  2. 漏洞自动挖掘工具 COMRaider
  • 使用工具挖掘
    点击statrt,然后点击Next
    打开文件夹,选择要分析的com组件。记得COM组件要注册


    生成脚本

    然后点击next
    再点击Fuzz
    跑完后就是这样的效果我们需要关注的就是这几个地方,有异常的就进去调试,判断是不是漏洞

    点击view设置我们的调试器

    右键选择Olly启动

    会自动填写参数,启动OD

    我们要知道我们是执行wscript这个exe调用脚本,然后调用COM组件
  • 寻找COM组件的位置

    在这个函数里面下断点
    在DispCallFunc函数一直“步过”,直到见到Call reg时,我们就来到了进入COM某个函数边缘,F7进入


    进入之后观察栈有没有溢出的情况,会很明显的

    当我走到这个call,栈变的一眼就看出来了,然后进去分析这个函数既可以了

    发现了溢出位置

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功