zoukankan      html  css  js  c++  java
  • 驱动开发中使用安全字符串函数

    一、前言

           大量的系统安全问题是由于薄弱的缓冲处理以及由此产生的缓冲区溢出造成的,而薄弱的缓冲区处理常常与字符串操作相关。c/c++语言运行库提供的标准字符串操作函数(strcpy, strcat, sprintf等)不能阻止在超出字符串尾端的写入。

           基于Windows XP SP1以及随后的操作系统的Windows DDK版本提供了安全字符串函数(safe string functions)。这类函数被设计的目的是用来取代相同功能的c/c++标准函数和其它微软提供的库函数。这类函数具有以下特征:

    • 每个函数以目标缓冲区所占的字节大小作为其一个输入参数,因此可以保证在写入时不会超出缓冲区末端。
    • 每个函数的输出字符串均以NULL结尾(null-terminate),即使该函数可能会对正确的结果进行截断。
    • 所有函数均有返回值,类型为NTSTATUS,只有返回STATUS_SUCCESS时,操作结果才正确。
    • 每个函数均有两种类型的版本,按字节或者按字符数。例如,RtlStringCbCatWRtlStringCchCatW
    • 每个函数均有支持双字节的unicode字符(以W作为后缀)和单字节的ANSI字符(以A作为后缀)的版本。例如:RtlStringCbCatWRtlStringCbCatA
    • 大部分函数有提供扩展版本的函数(以Ex作为后缀),例如,RtlStringCbCatWRtlStringCbCatExW

    二、如何在内核驱动代码中引入安全字符串函数

        有两种方式可以引入安全字符串函数:

    l        以内联的方式引入,包含在ntstrsafe.h中

    l        在链接时以库的方式引入

    其中,如果代码需要在系统为Windows XP及以后版本运行时,可以使用内联的方式;如果代码需要运行在早于Windows XP时,则必须使用链接库的方式。

    以内联方式引入

    只需包含头文件即可

    #include <ntstrsafe.h>

    以链接库的方式

    1. 在包含头文件之前先定义宏

    #define NTSTRSAFE_LIB

    #include <ntstrsafe.h>

    1. 在项目的sources文件中,添加一TARGETLIBS条目如下: $(DDK_LIB_PATH) tstrsafe.lib.

    在默认情况下,当引入了安全字符串函数后,那些被取代的c/c++运行库函数将变得无效,编译是会报错,提示需要使用安全字符串函数。

        如果还希望继续使用c/c++运行库函数,即在使用安全字符串函数的时候,c/c++运行库函数还可以继续使用,则需要在包含ntstrsafe.h之前先定义宏NTSTRSAFE_NO_DEPRECATE

    #define NTSTRSAFE_NO_DEPRECATE

    The maximum number of characters that any ANSI or Unicode string can contain is STRSAFE_MAX_CCH. This constant is defined in ntstrsafe.h.

    字符串最长长度为STRSAFE_MAX_CCH,该宏在ntstrsafe.h中定义。另外,如果一个字符串需要被转换成UNICODE_STRING结构,则该字符串长度不能超过65535.

    三、内核模式安全字符串函数概述

        下表概述了可以在内核驱动中使用的安全字符串函数,并指明了它们用来何种类型的c/c++运行库函数。

    说明:

    函数名含有Cb的是以字节数为单位,含有Cch的是以字符数为单位。

    函数名

    作用

    取代

    RtlStringCbCat 
    RtlStringCbCatEx 
    RtlStringCchCat 
    RtlStringCchCatEx

    将源字符串连接到目的字符串的末尾

    strcat
    wcscat

    RtlStringCbCatN 
    RtlStringCbCatNEx 
    RtlStringCchCatN 
    RtlStringCchCatNEx

    将源字符串指定数目的字符连接到目的字符串的末尾

    strncat
    wcsncat

    RtlStringCbCopy 
    RtlStringCbCopyEx 
    RtlStringCchCopy 
    RtlStringCchCopyEx

    将源字符串拷贝到目的字符串

    strcpy
    wcscpy

    RtlStringCbCopyN 
    RtlStringCbCopyNEx 
    RtlStringCchCopyN 
    RtlStringCchCopyNEx

    将源字符串指定数目的字符拷贝到目的字符串

    strncpy
    wcsncpy

    RtlStringCbLength 
    RtlStringCchLength

    确定字符串的长度

    strlen
    wcslen

    RtlStringCbPrintf 
    RtlStringCbPrintfEx 
    RtlStringCchPrintf 
    RtlStringCchPrintfEx

    格式化输出

    sprintf
    swprintf
    _snprintf
    _snwprintf

    RtlStringCbVPrintf 
    RtlStringCbVPrintfEx 
    RtlStringCchVPrintf 
    RtlStringCchVPrintfEx

    可变格式化输出

    vsprintf
    vswprintf
    _vsnprintf
    _vsnwprintf

    各个函数的作用可以通过它所取代的c/c++函数可以大概看出,具体用法请查阅DDK帮助文档。

      

    驱动中使用的字符串操作函数 ,这里给出ANSI和UNICODE的对比

    操作

    ANSI串函数

    Unicode串函数

    Length

    Strlen

    wcslen

    Concatenate

    Strcat

    strncat

    Wcscat

    wcsncat

    RtlAppendUnicodeStringToString

    RtlAppendUnicodeToString

    Copy

    Strcpy

    strncpy

    RtlCopyString

    Wcscpy

    wcsncpy

    TrlCopyUnicodeString

    Reverse

    _strrev

    _wcsrev

    Compare

    Strcmp

    Strncmp

    _stricmp

    _strnicmp

    RtlCompareString

    RtlEqualString

    Wcscmp

    Wcsncmp

    _wcsicmp

    _wcsnicmp

    RtlCompareUnicodeString

    RtlEqualUnicodeString

    RtlPrefixUnicodeString

    Initialize

    _strset

    _strnset

    RtlInitAnsiString

    RtlInitString

    _wcsnset

    RtlInitUnicodeString

    Search

    Strchr

    strrchr

    strspn

    strstr

    Wcschr

    wcsrchr

    wcsspn

    wcsstr

    Upper/Lowercase

    _strlwr

    _strupr

    RtlUpperString,

    _wcslwr

    _wcsupr

    RtlUpcaseUnicodeString

    Character

    isdigit

    islower

    isprint

    isspace

    isupper

    isxdigit

    tolower

    toupper

    RtlUpperChar

    Towolower

    towupper

    RtlUpcaseUnicodeString

    Format

    Sprintf

    vsprintf

    _snprintf

    _vsnprintf

    Swprintf

    _snwprintf

    String Conversion

    Atoi

    Atoll

    _itoa

    _itow

    RtlIntegerToUnicodeString

    RtlUnicodeStringToInteger

    Type conversion

    RtlAnsiStringToUnicodeString

    RtlAnsiStringToUnicodeString

    RtlUnicodeStringToAnsiString

    Memory Release

    RtlFreeAnsiString

    RtlFreeUnicodeString

     Ansi转换Unicode

       RtlAnsiStringToUnicodeString

    Unicode转换Ansi

      RtlUnicodeStringToAnsiString

        以上两个函数第三个参数都为True时需要使用RtlFreeUnicodeString/RtlFreeAnsiString来释放空间。我设置过False 但是测试时候 第一次可以 第二次就蓝屏了。如果读者知道为什么 可以在下方评论留言给我。谢谢

    KdPrint输出unicode_string类型字符串使用 %wZ

     

    // convert the name to UNICODE_STRING
    wchar_t name[100];
    auto status =
    RtlStringCchPrintfW(name, RTL_NUMBER_OF(name), L"%S", export_name);
    if (!NT_SUCCESS(status)) {
    return true;
    }
    UNICODE_STRING name_u = {};
    RtlInitUnicodeString(&name_u, name);

  • 相关阅读:
    软件杯华为ModelArts平台
    软件杯第一阶段博客
    《系统架构》阅读笔记05
    第11周周博客
    测试面试题
    杭电2014 (第一次用vector ac题目)
    杭电 2013 猴子吃桃 递归解法&循环解法
    杭电2012 质数问题
    杭电2629 Identity Card
    杭电1170
  • 原文地址:https://www.cnblogs.com/kuangke/p/5508077.html
Copyright © 2011-2022 走看看