呼死你—时间 发表于 2016-4-23 23:19

申请ID:ISP、疯

申请ID:ISP、疯
申请邮箱:3096036667@qq.com 吾爱论坛大神在上,为龙飞雪而来


测试机器:nexus4       android版本:4.4   内核版本3.4.0
漏洞介绍:函数进行拷贝时没有对长度进行判断,导致用户可以修改内核栈中值。
漏洞利用:通过修改函数返回地址,来进行提权操作

1,首先找到官方的修补代码
修补代码地址:https://www.codeaurora.org/cgit/quic/la/platform/vendor/qcom-opensource/wlan/qcacld-2.0/diff/CORE/HDD/src/wlan_hdd_wext.c?id=a079d716b5481223f0166c644e9ec7c75a31b02c

@@ -9741,6 +9741,9 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest,

               hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d",
                         pRequest->paramsData.dataOffset, pRequest->paramsData.dataLength);
+                if ((sizeof(packetFilterSetReq.paramsData.compareData)) <
+                           (pRequest->paramsData.dataLength))
+                  return -EINVAL;

                memcpy(&packetFilterSetReq.paramsData.compareData,
                        pRequest->paramsData.compareData, pRequest->paramsData.dataLength);
                        
                memcpy(&packetFilterSetReq.paramsData.dataMask,
                        pRequest->paramsData.dataMask, pRequest->paramsData.dataLength);

2,推测漏洞的产生原理
从官方的修补来看,这里只是添加了一个拷贝长度的限制,那么漏洞产生的原因,应该是memcpy拷贝时数据越界有关。
为了证实我的推测,我们看看packetFilterSetReq , pRequest 两个结构体是从何而来。
int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest,
                            tANI_U8 sessionId)
{
    tSirRcvPktFilterCfgType    packetFilterSetReq = {0};
    tSirRcvFltPktClearParam    packetFilterClrReq = {0};
    int i=0;


从内核代码上看,packetFilterSetReq 是局部变量,而pRequest则是作为参数传入。
结合起来看,我推测,漏洞产生的原因应该是,memcpy拷贝时越界修改掉了栈的值,覆盖掉了函数的返回地址。


3,查找调用漏洞函数的过程
为了利用,以及验证我的推测,现在要找出从漏洞函数到入口函数的整条调用的线
首先从产生漏洞的函数wlan_hdd_set_filter;开始找
(wlan_hdd_set_filter在内核源码drivers\staging\prima\core\hdd\src\Wlan_hdd_wext.c文件中)
查看wlan_hdd_set_filter的调用,发现了两处,分别是同文件下的wlan_hdd_set_mc_addr_list 和 iw_set_packet_filter_params
首先看 wlan_hdd_set_mc_addr_list 函数


void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set)
{
    v_U8_t filterAction;
    tPacketFilterCfg request;
    v_U8_t i;
    hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);

    filterAction = set ? HDD_RCV_FILTER_SET : HDD_RCV_FILTER_CLEAR;

    /*set mulitcast addr list*/
    for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++)
    {
      memset(&request, 0, sizeof (tPacketFilterCfg));
      request.filterAction = filterAction;
      request.filterId = i;
      if (set)
      {
            request.numParams = 1;
            request.paramsData.protocolLayer = HDD_FILTER_PROTO_TYPE_MAC;
            request.paramsData.cmpFlag = HDD_FILTER_CMP_TYPE_EQUAL;   
            request.paramsData.dataOffset = WLAN_HDD_80211_FRM_DA_OFFSET;
            request.paramsData.dataLength = ETH_ALEN; //长度变成固定,不符合触发漏洞的要求
            memcpy(&(request.paramsData.compareData),
                  &(pAdapter->mc_addr_list.addr), ETH_ALEN);
            /*set mulitcast filters*/
            hddLog(VOS_TRACE_LEVEL_INFO,
                  "%s: %s multicast filter: addr ="
                  MAC_ADDRESS_STR,
                  __func__, set ? "setting" : "clearing",
                  MAC_ADDR_ARRAY(request.paramsData.compareData));
      }
      wlan_hdd_set_filter(pHddCtx, &request, pAdapter->sessionId);
    }
    pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE;
}
从代码上来看,再看看这个宏的值
#define ETH_ALEN    6
发现这个长度,根本无法达到产生漏洞的条件,因此可以判断出,这个函数不是我们所要找的目标函数。
回过头看另外一个函数iw_set_packet_filter_params


static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request_info *info,
      union iwreq_data *wrqu, char *extra)
{   
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    tpPacketFilterCfg pRequest = (tpPacketFilterCfg)wrqu->data.pointer;

return wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, pAdapter->sessionId)
}
发现这个pRequest的值是作为参数传入,那么继续找他的调用点,但是发现,却找不到调用点,那么这个函数应该是函数指针调用的,在文件中搜索函数名发现了一个结构体中保存了函数地址
static const iw_handler we_private[] = {
其中有这一项


static const iw_handler we_private[] = {

      = iw_setint_getnone,//set priv ioctl
      = iw_setnone_getint,//get priv ioctl
      = iw_setchar_getnone, //get priv ioctl
   = iw_set_three_ints_getnone,
   = iw_get_char_setnone,
      = iw_setnone_getnone, //action priv ioctl
      = iw_set_var_ints_getnone,
      = iw_add_tspec,
      = iw_del_tspec,
      = iw_get_tspec,
#ifdef FEATURE_OEM_DATA_SUPPORT
    = iw_set_oem_data_req, //oem data req Specifc
    = iw_get_oem_data_rsp, //oem data req Specifc
#endif

#ifdef FEATURE_WLAN_WAPI
   = iw_qcom_set_wapi_mode,
   = iw_qcom_get_wapi_mode,
   = iw_qcom_set_wapi_assoc_info,
   = iw_qcom_set_wapi_key,
   = iw_qcom_set_wapi_bkid,
   = iw_qcom_get_wapi_bkid,
#endif /* FEATURE_WLAN_WAPI */
#ifdef WLAN_FEATURE_VOWIFI_11R
      = iw_set_fties,
#endif
      = iw_set_host_offload,
      = iw_get_statistics,
      = iw_set_keepalive_params
#ifdef WLAN_FEATURE_PACKET_FILTERING
   ,
   = iw_set_packet_filter_params
#endif
#ifdef FEATURE_WLAN_SCAN_PNO
   ,
      = iw_set_pno_priv
#endif
   ,
      = iw_set_band_config,
      = iw_set_dynamic_mcbc_filter,
      = iw_clear_dynamic_mcbc_filter,
      = iw_set_power_params_priv,
      = iw_get_linkspeed,
};
那么在看看哪里使用 we_private


const struct iw_handler_def we_handler_def = {
   .num_standard   = sizeof(we_handler) / sizeof(we_handler),
   .num_private      = sizeof(we_private) / sizeof(we_private),
   .num_private_args = sizeof(we_private_args) / sizeof(we_private_args),

   .standard         = (iw_handler *)we_handler,
   .private          = (iw_handler *)we_private,
   .private_args   = we_private_args,
   .get_wireless_stats = get_wireless_stats,
};
发现最后赋值给了const struct iw_handler_def we_handler_def 中的 .private


int hdd_register_wext(struct net_device *dev)
    {
   ......
    if (!VOS_IS_STATUS_SUCCESS(vos_event_init(&pwextBuf->scanevent)))
    {
      VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD scan event init failed!!\n"));
      return eHAL_STATUS_FAILURE;
    }

    // Register as a wireless device
    dev->wireless_handlers = (struct iw_handler_def *)&we_handler_def;//搜索文件看哪里使用了dev->wireless_handlers

    EXIT();
    return 0;
}
到这步之后,再继续看调we_handler_def的调用点。
发现最后给了dev->wireless_handlers 这个成员变量。现在我们在使用lookup References功能 看看 哪些地方使用了 dev->wireless_handlers


发现,很多地方都使用了dev->wireless_handlers这个成员变量,那么现在来根据条件(看哪些地方是获取这个成员变量)来排除
最后发现,只有这一处是获取到了dev->wireless_handlers这个成员变量。

然后打开这个目录文件搜索(目录:net\wireless\Wext-core.c)

static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
{
/* Don't "optimise" the following variable, it will crash */
unsigned intindex;    /* *MUST* be unsigned */
const struct iw_handler_def *handlers = NULL;

#ifdef CONFIG_CFG80211_WEXT
if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy)
    handlers = dev->ieee80211_ptr->wiphy->wext;
#endif
#ifdef CONFIG_WIRELESS_EXT
if (dev->wireless_handlers)
handlers = dev->wireless_handlers;
#endif

if (!handlers)
    return NULL;

/* Try as a standard command */
index = IW_IOCTL_IDX(cmd);
if (index < handlers->num_standard)
    return handlers->standard;

#ifdef CONFIG_WEXT_PRIV
/* Try as a private command */
index = cmd - SIOCIWFIRSTPRIV;
if (index < handlers->num_private)
    return handlers->private;//获取了漏洞函数地址
#endif

/* Not found */
return NULL;
}
找到了get_handler这个函数,看他下面代码
index = cmd - SIOCIWFIRSTPRIV;
if (index < handlers->num_private)
    return handlers->private;//获取了漏洞函数地址
发现他是根据传入的CMD指令来获取函数地址,根据之前的 we_private 存放地址      = iw_set_packet_filter_params 得出了CMD值


static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
          unsigned int cmd,
          struct iw_request_info *info,
          wext_ioctl_func standard,
          wext_ioctl_func private)
{
struct iwreq *iwr = (struct iwreq *) ifr;
struct net_device *dev;
iw_handlerhandler;

      ......

/* Basic check */
if (!netif_device_present(dev))
    return -ENODEV;

/* New driver API : try to find the handler */
handler = get_handler(dev, cmd);   ////获取了漏洞函数地址
if (handler) {
    /* Standard and private are not the same */
    if (cmd < SIOCIWFIRSTPRIV)
      return standard(dev, iwr, cmd, info, handler);
    else if (private)
      return private(dev, iwr, cmd, info, handler);
}
/* Old driver API : call driver ioctl handler */
       .....
}
现在继续看get_handler 的调用点,
根据图片代码看到,将调用漏洞的函数地址作为参数,然后调用了standard or private 发现这两个函数都是作为参数传入进来的。
( iwr 就是漏洞产生的条件,struct iwreq *iwr = (struct iwreq *) ifr;    ifr则作为参数传入 )
那么再继续看上级调用。


static int wext_ioctl_dispatch(struct net *net, struct ifreq *ifr,
             unsigned int cmd, struct iw_request_info *info,
             wext_ioctl_func standard,
             wext_ioctl_func private)
{
int ret = wext_permission_check(cmd);

if (ret)
    return ret;

dev_load(net, ifr->ifr_name);
rtnl_lock();
ret = wireless_process_ioctl(net, ifr, cmd, info, standard, private);
rtnl_unlock();

return ret;
}
发现我们所感兴趣的值还是作为参数传入的,那么继续往上,


int wext_handle_ioctl(struct net *net, struct ifreq *ifr, unsigned int cmd,
          void __user *arg)
{
struct iw_request_info info = { .cmd = cmd, .flags = 0 };
int ret;

ret = wext_ioctl_dispatch(net, ifr, cmd, &info,
          ioctl_standard_call,
          ioctl_private_call);//ioctl_private_call 中调用了漏洞函数
if (ret >= 0 &&
      IW_IS_GET(cmd) &&
      copy_to_user(arg, ifr, sizeof(struct iwreq)))
    return -EFAULT;

return ret;
}
现在得到了这两个函数的地址。
查看ioctl_private_call的代码


int ioctl_private_call(struct net_device *dev, struct iwreq *iwr,
         unsigned int cmd, struct iw_request_info *info,
         iw_handler handler)
{
int extra_size = 0, ret = -EINVAL;
const struct iw_priv_args *descr;

extra_size = get_priv_descr_and_size(dev, cmd, &descr);

/* Check if we have a pointer to user space data or not. */
if (extra_size == 0) {
    /* No extra arguments. Trivial to handle */
    ret = handler(dev, info, &(iwr->u), (char *) &(iwr->u));//handler:漏洞函数,iwr->u:触发条件
} else {
    ret = ioctl_private_iw_point(&iwr->u.data, cmd, descr,
               handler, dev, info, extra_size);
}

/* Call commit handler if needed and defined */
if (ret == -EIWCOMMIT)
    ret = call_commit_handler(dev);

return ret;
}
可以看到这里调用了漏洞函数。 &(iwr->u) ,则是漏洞产生的条件


int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
{
struct ifreq ifr;
int ret;
char *colon;

/* One special case: SIOCGIFCONF takes ifconf argument
   and requires shared lock, because it sleeps writing
   to user space.
   */

if (cmd == SIOCGIFCONF) {
    rtnl_lock();
    ret = dev_ifconf(net, (char __user *) arg);
    rtnl_unlock();
    return ret;
}
if (cmd == SIOCGIFNAME)
    return dev_ifname(net, (struct ifreq __user *)arg);

if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))//给ifr结构体赋值
    return -EFAULT;

       ........

      ret = -EFAULT;
      return ret;
    }
    /* Take care of Wireless Extensions */
    if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
      return wext_handle_ioctl(net, &ifr, cmd, arg);
    return -ENOTTY;
}
现在继续看wext_handle_ioctl函数(注意:ifr参数就是漏洞的产生条件)继续看上级调用


int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
{
struct ifreq ifr;
int ret;
char *colon;

/* One special case: SIOCGIFCONF takes ifconf argument
   and requires shared lock, because it sleeps writing
   to user space.
   */

if (cmd == SIOCGIFCONF) {
    rtnl_lock();
    ret = dev_ifconf(net, (char __user *) arg);
    rtnl_unlock();
    return ret;
}
if (cmd == SIOCGIFNAME)
    return dev_ifname(net, (struct ifreq __user *)arg);

if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
    return -EFAULT;
看函数头
发现ifr的内容是拷贝的dev_ioctl中的arg参数


static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct socket *sock;
struct sock *sk;
void __user *argp = (void __user *)arg;
int pid, err;
struct net *net;

sock = file->private_data;
sk = sock->sk;
net = sock_net(sk);
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
    err = dev_ioctl(net, cmd, argp);
} else
到这里sock_ioctl没有发现上级调用,那么看哪些地方出现过这个函数


搜索sock_ioctl发现

static const struct file_operations socket_file_ops = {
.owner =THIS_MODULE,
.llseek =no_llseek,
.aio_read =sock_aio_read,
.aio_write =sock_aio_write,
.poll =    sock_poll,
.unlocked_ioctl = sock_ioctl,//保存在了 unlocked_ioctl 中
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap =    sock_mmap,
.open =    sock_no_open,/* special open code to disallow open via /proc */
.release =sock_close,
.fasync =sock_fasync,
.sendpage =sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read =sock_splice_read,
};
file_operations结构体中获取
linux大多都是使用ioctl系统调用来控制驱动设备的。所以我们跟踪ioctl函数


SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
struct file *filp;

int error = -EBADF;
int fput_needed;

filp = fget_light(fd, &fput_needed);
if (!filp)
    goto out;

error = security_file_ioctl(filp, cmd, arg);
if (error)
    goto out_fput;

error = do_vfs_ioctl(filp, fd, cmd, arg);
out_fput:
fput_light(filp, fput_needed);
out:
return error;
}

int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
       unsigned long arg)
{
int error = 0;
int __user *argp = (int __user *)arg;
struct inode *inode = filp->f_path.dentry->d_inode;

      .....

default:
    if (S_ISREG(inode->i_mode))
      error = file_ioctl(filp, cmd, arg);
    else
      error = vfs_ioctl(filp, cmd, arg);
    break;
}
do_vfs_ioctl 函数下找到 vfs_ioctl

static long vfs_ioctl(struct file *filp, unsigned int cmd,
          unsigned long arg)
{
int error = -ENOTTY;

if (!filp->f_op || !filp->f_op->unlocked_ioctl)
    goto out;

error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
if (error == -ENOIOCTLCMD)
    error = -ENOTTY;
out:
return error;
}
这样调用漏洞函数的过程就全部串联起来。


4,构建触发漏洞条件
首先看下 ioctl 有三个参数
param1首先打开网络驱动设备(linux大多数驱动都是以文件形式存在的,只有网络驱动例外。想了解详细的可以看下socket函数)

param2cmd,之前就已经找函数调用路径的时候我们就发现

#define SIOCIWFIRSTPRIV0x8BE0
#define WLAN_SET_PACKET_FILTER_PARAMS (SIOCIWFIRSTPRIV + 23)

param3
首先传入的时候


if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
然后


static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request_info *info,
      union iwreq_data *wrqu, char *extra)
{   
    hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
    tpPacketFilterCfg pRequest = (tpPacketFilterCfg)wrqu->data.pointer;

    return wlan_hdd_set_filter(WLAN_HDD_GET_CTX(pAdapter), pRequest, pAdapter->sessionId);
}
强制转换了下我们看下 iwreq 的成员


structiwreq
{
union
{
    charifrn_name;/* if name, e.g. "eth0" */
} ifr_ifrn;

/* Data part (defined just above) */
unioniwreq_datau;
};

unioniwreq_data
{
struct iw_pointdata;    /* Other large parameters */
};

structiw_point
{
void __user*pointer;/* Pointer to the data(in user space) */   
__u16    length;    /* number of fields or size in bytes */      
__u16    flags;    /* Optional params */               
};

看下tpPacketFilterCfg的结构体
typedef struct
{
    v_U8_t            filterAction;
    v_U8_t            filterId;
    v_U8_t            numParams;
    struct PacketFilterParamsCfg paramsData ;
}tPacketFilterCfg, *tpPacketFilterCfg;

struct PacketFilterParamsCfg
{
    v_U8_t            protocolLayer;
    v_U8_t            cmpFlag;
    v_U8_t            dataOffset;
    v_U8_t            dataLength;
    v_U8_t            compareData;
    v_U8_t            dataMask;
};

现在构造触发漏洞的结构体
int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest,
                            tANI_U8 sessionId)
{
    tSirRcvPktFilterCfgType    packetFilterSetReq = {0};
    tSirRcvFltPktClearParam    packetFilterClrReq = {0};
    int i=0;

    if (pHddCtx->cfg_ini->disablePacketFilter)
    {
      hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Packet Filtering Disabled. Returning ",
                __func__ );
      return 0;
    }
    if (pHddCtx->isLogpInProgress)
    {
       VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
                                  "%s:LOGP in Progress. Ignore!!!", __func__);
       return -EBUSY;
    }
    /* Debug display of request components. */
    hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Packet Filter Request : FA %d params %d",
            __func__, pRequest->filterAction, pRequest->numParams);

    switch (pRequest->filterAction) 进入条件
    {
      case HDD_RCV_FILTER_SET:
            hddLog(VOS_TRACE_LEVEL_INFO, "%s: Set Packet Filter Request for Id: %d",
                  __func__, pRequest->filterId);

            packetFilterSetReq.filterId = pRequest->filterId;
            if ( pRequest->numParams >= HDD_MAX_CMP_PER_PACKET_FILTER)
            {
                hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Number of Params exceed Max limit %d\n",
                        __func__, pRequest->numParams);
                return -EINVAL;
            }
            packetFilterSetReq.numFieldParams = pRequest->numParams;
            packetFilterSetReq.coalesceTime = 0;
            packetFilterSetReq.filterType = 1;
            for (i=0; i < pRequest->numParams; i++)//因为= pRequest->paramsData.dataLength 定义为unsigned char,覆盖长度无法触发漏洞,所以这里要设定pRequest->numParams的值,已确保能覆盖的地址能到达函数返回地址的长度
            {
                packetFilterSetReq.paramsData.protocolLayer = pRequest->paramsData.protocolLayer;
                packetFilterSetReq.paramsData.cmpFlag = pRequest->paramsData.cmpFlag;
                packetFilterSetReq.paramsData.dataOffset = pRequest->paramsData.dataOffset;
                packetFilterSetReq.paramsData.dataLength = pRequest->paramsData.dataLength;
               //这个成员变量定义为unsigned char,最大数字只能设置255个字节。
                packetFilterSetReq.paramsData.reserved = 0;

                hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d\n",
                        pRequest->paramsData.protocolLayer, pRequest->paramsData.cmpFlag,
                        packetFilterSetReq.filterType);

                hddLog(VOS_TRACE_LEVEL_INFO, "Data Offset %d Data Len %d\n",
                        pRequest->paramsData.dataOffset, pRequest->paramsData.dataLength);

                /*因为没有对长度进行判断,而packetFilterSetReq又属于局部变量,导致了我们可以设置适量的长度,覆盖掉wlan_hdd_set_filter的返回地址,让其跳转到自己所写函数的,进行提权操作.*/
                memcpy(&packetFilterSetReq.paramsData.compareData,
                        pRequest->paramsData.compareData, pRequest->paramsData.dataLength);
                memcpy(&packetFilterSetReq.paramsData.dataMask,
                        pRequest->paramsData.dataMask, pRequest->paramsData.dataLength);

                hddLog(VOS_TRACE_LEVEL_INFO, "CData %d CData %d CData %d CData %d CData %d CData %d\n",
                        pRequest->paramsData.compareData, pRequest->paramsData.compareData,
                        pRequest->paramsData.compareData, pRequest->paramsData.compareData,
                        pRequest->paramsData.compareData, pRequest->paramsData.compareData);

                hddLog(VOS_TRACE_LEVEL_INFO, "MData %d MData %d MData %d MData %d MData %d MData %d\n",
                        pRequest->paramsData.dataMask, pRequest->paramsData.dataMask,
                        pRequest->paramsData.dataMask, pRequest->paramsData.dataMask,
                        pRequest->paramsData.dataMask, pRequest->paramsData.dataMask);
            }

            if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, &packetFilterSetReq, sessionId))
            {
                hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Set Filter\n",
                        __func__);
                return -EINVAL;
            }

            break;

      case HDD_RCV_FILTER_CLEAR:

            hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Clear Packet Filter Request for Id: %d\n",
                  __func__, pRequest->filterId);
            packetFilterClrReq.filterId = pRequest->filterId;
            if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, &packetFilterClrReq, sessionId))
            {
                hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute Clear Filter\n",
                        __func__);
                return -EINVAL;
            }
            break;

      default :
            hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Packet Filter Request: Invalid %d\n",
                  __func__, pRequest->filterAction);
            return -EINVAL;
    }
    return 0;
}

iwreq.ifrn_name = 网络驱动名字
tpPacketFilterCfg.numParams = 4

PacketFilterParamsCfg.dataLength = 255
PacketFilterParamsCfg.compareData = my_fun_address

这样设置参数就能触发漏洞


5,函数返回崩溃问题
wlan_hdd_set_filter 因为返回地址被修改,所以调用完函数后,会导致内核崩溃,但是我们可以使用上级函数的地址来返回。这样就能避免内核崩溃.










Hmily 发表于 2016-4-25 17:27

http://bbs.pediy.com/showthread.php?p=1417207 看雪这个帖子是你发的,还是拿别人文章来申请的?
页: [1]
查看完整版本: 申请ID:ISP、疯