使用内核驱动Rtl函数实现更为安全的字符串处理

Rtl开头函数(Ntddk.h 以及Ntstrsafe.h)

大量的系统安全问题是由于薄弱的缓冲处理以及由此产生的缓冲区溢出造成的,而薄弱的缓冲区处理常常与字符串操作相关。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
  • 函数名

    作用

    取代

    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
    _vsnwprint

1.判断从字符串开头到Len长度的子串是否存在

1.1以下是自己实现的普通R3代码(C字符串实现)

char* strinstr(const char *Str, int Len, const char *SubStr)
{
	if (Str == NULL || SubStr == NULL || Len == 0)
		return NULL;
	char *cp = (char*)Str;
	char *s1, *s2;
	int m = 0, n = 0;
	if (!*SubStr)
		return ((char*)Str);
	while (m < Len)
	{
		if (*cp == 0)
			break;
		s1 = cp;
		s2 = (char*)SubStr;
		n = 0;
		while (m + n < Len && *s1 && *s2)
		{
			char ch1 = *s1, ch2 = *s2;
			if ((*s1) >= 'A' && (*s1) <= 'Z')
				ch1 = (char)tolower(*s1);
			if ((*s2) >= 'A' && (*s2) <= 'Z')
				ch2 = (char)tolower(*s2);
			if (ch1 == ch2)
			{
				s1++;
				s2++;
				n++;
			}
			else
			{
				break;
			}
		}
		if (!*s2)
			return cp;
		cp++;
		m++;
	}
	return NULL;
}

WCHAR* wcsinstr(const WCHAR *Str, int Len, const WCHAR *SubStr)
{
	if (Str == NULL || SubStr == NULL || Len == 0)
		return NULL;
	WCHAR *cp = (WCHAR*)Str;
	WCHAR *s1, *s2;
	int m = 0, n = 0;
	if (!*SubStr)
		return ((WCHAR*)Str);
	while (m < Len)
	{
		if (*cp == 0)
			break;
		s1 = cp;
		s2 = (WCHAR*)SubStr;
		n = 0;
		while (m + n < Len && *s1 && *s2)
		{
			WCHAR ch1 = *s1, ch2 = *s2;
			if ((*s1) >= 'A' && (*s1) <= 'Z')
				ch1 = towlower(*s1);
			if ((*s2) >= 'A' && (*s2) <= 'Z')
				ch2 = towlower(*s2);
			if (ch1 == ch2)
			{
				s1++;
				s2++;
				n++;
			}
			else
			{
				break;
			}
		}
		if (!*s2)
			return cp;
		cp++;
		m++;
	}
	return NULL;
}

1.2 使用系统函数实现(StrStrIA、StrStrNIW)

//判断是否是子串
char* strinstr(const char *Str, int Len, const char *SubStr)
{
  int length = 0;
  char* res;
  if (Str == NULL || SubStr == NULL || Len == 0)
    return NULL;
  char* cp = const_cast<char*>(Str);
  res = StrStrIA(cp, SubStr);
  if ((int)(res - Str) > Len)
    return NULL;
  return res;

}
WCHAR* wcsinstr(const WCHAR *Str, int Len, const WCHAR *SubStr)
{
  if (Str == NULL || SubStr == NULL || Len == 0)
    return NULL;
  return StrStrNIW(Str,SubStr,len);
}

2.比较字符串

2.1使用C语言函数实现比较两个字符串

int strincmp(const char *Str1, int BufferSize, const char *Str2)
{
	if (Str1 == NULL || Str2 == NULL || BufferSize == 0)
		return 3;
	int i = 0;
	while (i < BufferSize)
	{
		if (Str1[i] == 0)
			break;
		i++;
	}
	int Len = min(i, BufferSize);
	for (i = 0; i < Len; i++)
	{
		if (Str1[i] == 0 && Str2[i] == 0)
			return 0;
		char ch1 = 0, ch2 = 0;
		if (Str1[i] >= 'A' && Str1[i] <= 'Z')
			ch1 = (char)Str1[i] + 'a' - 'A';
		else
			ch1 = (char)Str1[i];
		if (Str2[i] >= 'A' && Str2[i] <= 'Z')
			ch2 = (char)Str2[i] + 'a' - 'A';
		else
			ch2 = (char)Str2[i];
		if (ch1 > ch2)
		{
			return 1;
		}
		else if (ch1 < ch2)
		{
			return -1;
		}
	}
	if (Str2[i] != 0)
		return -1;
	return 0;
}

int wcsincmp(const WCHAR *Str1, int BufferSizeInCh, const WCHAR *Str2)
{
	if (Str1 == NULL || Str2 == NULL || BufferSizeInCh == 0)
		return 3;
	int i = 0;
	while (i < BufferSizeInCh)
	{
		if (Str1[i] == 0)
			break;
		i++;
	}
	int Len = min(i, BufferSizeInCh);
	for (i = 0; i < Len; i++)
	{
		if (Str1[i] == 0 && Str2[i] == 0)
			return 0;
		char ch1 = 0, ch2 = 0;
		if (Str1[i] >= 'A' && Str1[i] <= 'Z')
			ch1 = (char)Str1[i] + 'a' - 'A';
		else
			ch1 = (char)Str1[i];
		if (Str2[i] >= 'A' && Str2[i] <= 'Z')
			ch2 = (char)Str2[i] + 'a' - 'A';
		else
			ch2 = (char)Str2[i];
		if (ch1 > ch2)
		{
			return 1;
		}
		else if (ch1 < ch2)
		{
			return -1;
		}
	}
	if (Str2[i] != 0)
		return -1;
	return 0;
}

2.2 使用Rtl类型函数比较两个字符串(RtlCompareString和RtlCompareUnicodeString)

int strincmp(const char *Str1, int BufferSize, const char *Str2)
{
  if (Str1 == NULL || Str2 == NULL || BufferSize == 0)
    return 3;
  STRING s1 = { 0 };
  STRING s2 = { 0 };
  s1.Buffer = (char*)Str1;s1.Length = sizeof(s1);s1.MaximumLength = BufferSize;
  s2.Buffer = (char*)Str2;s2.Length = sizeof(s2);s2.MaximumLength = BufferSize;
  if (RtlCompareString(&s1, &s2, TRUE) == 0)
    return 0;
  else if (RtlCompareString(&s1, &s2, TRUE) > 0)
    return 1;
  else return -1;
}
int wcsincmp(PCWSTR Str1, int BufferSizeInCh, PCWSTR Str2)
{
  PUNICODE_STRING PS1;
  PUNICODE_STRING PS2;
  if (RtlUnicodeStringInit(PS1, Str1) == STATUS_SUCCESS && RtlUnicodeStringInit(PS2, Str2) == STATUS_SUCCESS)
  {
    if (RtlCompareUnicodeString(PS1, PS2, TRUE) == 0)
      return 0;
    else if (RtlCompareUnicodeString(PS1, PS2, TRUE) > 0)
      return 1;
    else return -1;
  }
  else 
  return 3;
}

3.计算字符串长度

3.1 普通实现

int strnlen_safe(const char *Str, int MaxLen)
{
	if (Str == NULL || MaxLen <= 0)
		return 0;
	int i = 0;
	while (i < MaxLen)
	{
		if (Str[i] == 0)
			break;
		i++;
	}
	return i;
}

int wcsnlen_safe(const WCHAR *Str, int MaxLen)
{
	if (Str == NULL || MaxLen <= 0)
		return 0;
	int i = 0;
	while (i < MaxLen)
	{
		if (Str[i] == 0)
			break;
		i++;
	}
	return i;
}

3.2 Rtl函数实现(RtlStringCchLengthA和RtlStringCchLengthW)

int strnlen_safe(const char *Str, int MaxLen)
{
  size_t reslen = 0;
  if (Str == NULL || MaxLen <= 0)
    return 0;
  if (MaxLen > NTSTRSAFE_MAX_CCH)
    return -1;
  RtlStringCchLengthA(Str, MaxLen, &reslen);
  return reslen;
}
int wcsnlen_safe(const WCHAR *Str, int MaxLen)
{
  size_t reslen;
  if (Str == NULL || MaxLen <= 0)
    return 0;
  if (MaxLen > NTSTRSAFE_MAX_CCH)
    return -1;
  RtlStringCchLengthW(Str, MaxLen, &reslen);
  return reslen;
}

4计算某个字符的个数

计算某个字符的个数,不涉及缓冲区大小 所以不存在安全问题,普通实现即可

//计算某个字符的个数,不涉及缓冲区大小 所以不存在安全问题,没找到Rtl类型函数
int wcsncount(const WCHAR *Str, int MaxLen, const WCHAR ch)
{
  if (Str == NULL || MaxLen == 0)
    return 0;
  int count = 0;
  int i = 0;
  while (i < MaxLen)
  {
    if (Str[i] == '\0')
      break;
    if(Str[i] == ch)
    count++;
    i++;
  }
  return count;
}

5.另外Rtl

### 回答1: RTL8111是Realtek半导体公司推出的一款以太网控制器芯片,适用于各种计算机硬件平台。该芯片在Linux系统中的驱动rtl8111linux驱动rtl8111linux驱动是一个开源项目,它由Linux社区的开发者开发和维护。这个驱动程序允许Linux系统与RTL8111以太网芯片进行正常通信和交互。 rtl8111linux驱动在Linux内核中已经集成,用户只需在Linux系统中安装相应的内核版本即可使用。安装好内核后,系统会自动加载并启动rtl8111linux驱动rtl8111linux驱动提供了一系列的函数和接口,用于控制和管理RTL8111芯片的各种功能和配置。用户可以通过命令行工具或图形界面工具进行驱动的配置和管理,例如设置网络连接参数、调整传输速率、启用或禁用某些功能等。 rtl8111linux驱动具有很好的稳定性和兼容性,可以与主流的Linux发行版(如Ubuntu、Fedora、Debian等)以及不同版本的内核无缝协作。同时,rtl8111linux驱动还能够支持最新的网络技术和协议,确保用户可以享受到最新的网络体验。 总而言之,rtl8111linux驱动是Linux系统中与RTL8111以太网芯片通信的关键组件,它保证了RTL8111在Linux系统中的正常工作和性能表现。这个驱动程序已经得到广泛的应用和验证,并且得到了Linux社区的持续关注和维护。 ### 回答2: RTL8111是一种网络控制器芯片,常用于以太网卡的驱动程序中。在Linux操作系统中,RTL8111的Linux驱动程序是指用于在Linux系统中支持和控制RTL8111芯片的软件。这个驱动程序能够使RTL8111芯片正常工作并与操作系统和网络进行通信。 RTL8111驱动程序是由Realtek公司开发和维护的,其主要功能包括控制RTL8111芯片的数据传输、网络通信和硬件管理等。它允许操作系统能够识别和使用RTL8111芯片,并提供了与网络相关的功能,如连接控制、MAC地址管理、数据包传输和流量控制等。 对于使用RTL8111芯片的计算机用户来说,在安装Linux操作系统后,需要安装RTL8111的Linux驱动程序以确保网络功能的正常运行。通常情况下,Linux系统会自动识别和加载适合的驱动程序。如果系统无法自动加载正确的驱动程序,用户可以手动安装、更新或配置RTL8111的Linux驱动程序。 RTL8111的Linux驱动程序通常以代码的形式提供,用户可以从Realtek公司的官方网站或其他开源软件库中获取驱动程序的源代码。然后,用户需要根据自己的操作系统版本和硬件设备的要求进行编译和安装。编译和安装RTL8111驱动程序可能需要一些基本的Linux知识和技巧。 总之,RTL8111的Linux驱动程序是用于支持和管理RTL8111芯片的软件,它是确保RTL8111网络控制器在Linux系统中正常工作的关键。用户可以通过安装、更新或配置RTL8111的Linux驱动程序来获得和提供稳定、高效的网络连接。 ### 回答3: rtl8111是Realtek公司生产的以太网芯片系列,用于支持台式机和笔记本电脑的有线以太网连接。而rtl8111的Linux驱动是用于在Linux操作系统上支持rtl8111网卡的。 rtl8111的Linux驱动可以在Realtek官方网站上获得。您可以通过下载和编译这个驱动来为您的Linux系统安装rtl8111网卡的驱动程序。安装驱动程序后,系统将能够正常识别和使用rtl8111网卡,以实现有线网络连接。 rtl8111的Linux驱动具有以下特点和功能: 1. 稳定性和兼容性:rtl8111的Linux驱动经过官方认证和测试,具有较高的稳定性和兼容性,可以在大多数常见的Linux发行版上正常运行。 2. 高性能:rtl8111的Linux驱动支持千兆以太网传输速率,能够提供较高的网络传输性能。 3. 简单易用:安装和配置rtl8111的Linux驱动相对简单,官方提供了详细的安装指南和使用手册,即使对Linux初学者来说也相对容易上手。 4. 更新和维护:官方会定期更新和维护rtl8111的Linux驱动,以解决已知的问题和提升驱动程序的性能。 总的来说,rtl8111的Linux驱动可以让您的Linux系统正常识别和使用rtl8111网卡,实现稳定、高性能的有线网络连接。使用官方提供的驱动程序,可以在Linux平台上享受到与rtl8111网卡相关的各种功能和特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值