[原创]windows ntfs本地提权漏洞 cve-ag真人国际厅网站

io_status_block

ntfsqueryeauserealist(

    in pfile_full_ea_information currenteas,

    in pea_information eainformation,

    out pfile_full_ea_information eabuffer,

    in ulong userbufferlength,

    in pfile_get_ea_information userealist,

    in boolean returnsingleentry

 

/*

 

routine description:

 

    this routine is the work routine for querying eas given a list

    of ea's to search for.

 

arguments:

 

    currenteas - this is a pointer to the current eas for the file

 

    eainformation - this is a pointer to an ea information attribute.

 

    eabuffer - supplies the buffer to receive the full eas

 

    userbufferlength - supplies the length, in bytes, of the user buffer

 

    userealist - supplies the user specified ea name list

 

    returnsingleentry - indicates if we are to return a single entry or not

 

return value:

 

    io_status_block - receives the completion status for the operation

 

--*/

 

    io_status_block iosb;

 

    ulong geaoffset;

    ulong feaoffset;

    ulong offset;

 

    pfile_full_ea_information lastfullea;

    pfile_full_ea_information nextfullea;

 

    pfile_get_ea_information getea;

 

    boolean overflow;

    ulong preveapadding;

 

    paged_code();

 

    debugtrace( 1, dbg, ("ntfsqueryeauserealist:  entered\n"));

 

    //

    //  setup pointer in the output buffer so we can track the ea being

    //  written to it and the last ea written.

    //

 

    lastfullea = null;

 

    overflow = false;

 

    //

    //  initialize our next offset value.

    //

 

    geaoffset = 0;

    offset = 0;

    preveapadding = 0;

 

    //

    //  loop through all the entries in the user's ea list.

    //

 

    while (true) {

 

        string geaname;

        string outputeaname;

        ulong raweasize;

 

        //

        //  get the next entry in the user's list.

        //

 

        getea = (pfile_get_ea_information)add2ptr(userealist, geaoffset);

 

        //

        //  make a string reference to the name and see if we can locate

        //  the ea by name.

        //

 

        geaname.maximumlength = geaname.length = getea->eanamelength;

        geaname.buffer = &getea->eaname[0];

 

        //

        //  upcase the name so we can do a case-insensitive compare.

        //

 

        ntfsupcaseeaname(&geaname, &geaname);

 

        //

        //

 

        if (!ntfsiseanamevalid(geaname)) {

 

            debugtrace(-1, dbg, ("ntfsqueryeauserealist:  invalid ea name\n"));

 

            iosb.information = geaoffset;

            iosb.status = status_invalid_ea_name;

            return iosb;

        }

 

        geaoffset = getea->nextentryoffset;

 

        //

        //  if this is a duplicate name, then step over this entry.

        //

 

        if (ntfsisduplicategeaname(getea, userealist)) {

 

            //

            //  if we've exhausted the entries in the get ea list, then we are

            //  done.

            //

 

            if (getea->nextentryoffset == 0) {

                break;

            }

            else {

                continue;

            }

        }

 

        //

        //  generate a pointer in the ea buffer.

        //

 

        nextfullea = (pfile_full_ea_information)add2ptr(eabuffer, offset preveapadding);

 

        //

        //  try to find a matching ea.

        //  if we couldn't, let's dummy up an ea to give to the user.

        //

 

        if (!ntfslocateeabyname(currenteas,

            eainformation->unpackedeasize,

            &geaname,

            &feaoffset)) {

 

            //

            //  we were not able to locate the name therefore we must

            //  dummy up a entry for the query.  the needed ea size is

            //  the size of the name 4 (next entry offset) 1 (flags)

            //  1 (name length) 2 (value length) the name length

            //  1 (null byte).

            //

 

            raweasize = 4 1 1 2 getea->eanamelength 1;

 

            if ((raweasize preveapadding) > userbufferlength) {

 

                overflow = true;

                break;

            }

 

            //

            //  everything is going to work fine, so copy over the name,

            //  set the name length and zero out the rest of the ea.

            //

 

            nextfullea->nextentryoffset = 0;

            nextfullea->flags = 0;

            nextfullea->eanamelength = getea->eanamelength;

            nextfullea->eavaluelength = 0;

            rtlcopymemory(&nextfullea->eaname[0],

                &getea->eaname[0],

                getea->eanamelength);

 

            //

            //  upcase the name in the buffer.

            //

 

            outputeaname.maximumlength = outputeaname.length = geaname.length;

            outputeaname.buffer = nextfullea->eaname;

 

            ntfsupcaseeaname(&outputeaname, &outputeaname);

 

            nextfullea->eaname[getea->eanamelength] = 0;

 

            //

            //  otherwise return the ea we found back to the user.

            //

 

        }

        else {

 

            pfile_full_ea_information thisea;

 

            //

            //  reference this ea.

            //

 

            thisea = (pfile_full_ea_information)add2ptr(currenteas, feaoffset);

 

            //

            //  check if this ea can fit in the user's buffer.

            //

 

            raweasize = rawunpackedeasize(thisea);

 

            if (raweasize > (userbufferlength - preveapadding)) {

 

                overflow = true;

                break;

            }

 

            //

            //  copy this ea to the user's buffer.

            //

 

            rtlcopymemory(nextfullea,

                thisea,

                raweasize);

 

            nextfullea->nextentryoffset = 0;

        }

 

        //

        //  compute the next offset in the user's buffer.

        //

 

        offset = (raweasize preveapadding);

 

        //

        //  if we were to return a single entry then break out of our loop

        //  now

        //

 

        if (returnsingleentry) {

 

            break;

        }

 

        //

        //  if we have a new ea entry, go back and update the offset field

        //  of the previous ea entry.

        //

 

        if (lastfullea != null) {

 

            lastfullea->nextentryoffset = ptroffset(lastfullea, nextfullea);

        }

 

        //

        //  if we've exhausted the entries in the get ea list, then we are

        //  done.

        //

 

        if (getea->nextentryoffset == 0) {

 

            break;

        }

 

        //

        //  remember this as the previous ea value.  also update the buffer

        //  length values and the buffer offset values.

        //

 

        lastfullea = nextfullea;

        userbufferlength -= (raweasize preveapadding);

 

        //

        //  now remember the padding bytes needed for this call.

        //

 

        preveapadding = longalign(raweasize) - raweasize;

    }

 

    //

    //  if the ea information won't fit in the user's buffer, then return

    //  an overflow status.

    //

 

    if (overflow) {

 

        iosb.information = 0;

        iosb.status = status_buffer_overflow;

 

        //

        //  otherwise return the length of the data returned.

        //

 

    }

    else {

 

        //

        //  return the length of the buffer filled and a success

        //  status.

        //

 

        iosb.information = offset;

        iosb.status = status_success;

    }

 

    debugtrace(0, dbg, ("status        -> lx\n", iosb.status));

    debugtrace(0, dbg, ("information   -> lx\n", iosb.information));

    debugtrace(-1, dbg, ("ntfsqueryeauserealist:  exit\n"));

 

    return iosb;

原文链接:https://bbs.kanxue.com/thread-277812.htm

网络摘文,本文作者:15h,如若转载,请注明出处:https://www.15cov.cn/2023/08/27/原创windows-ntfs本地提权漏洞-cve-2021-31956/

发表评论

邮箱地址不会被公开。 必填项已用*标注

网站地图