在需要对计算机进行标识的场景下,我们一般会选择获取一些硬件信息。然而CPU序列号可能有重复、网卡MAC地址和计算机名又能被轻易地修改,所以其中最可靠的应该就是硬盘序列号了。Windows下硬盘序列号的获取本身并不复杂,而关键在于如何在无需权限提升的情况下获取到硬盘序列号。为了解决这个问题,我也查了很多资料,基本上各大博客中贴出的都是需要权限提升的代码。

最终,在DiskID32的源码中,我找到了不提权获取硬盘序列号的办法。不过其源码只能使用MBCS多字节字符集方式编译,而无法使用Unicode字符集编译,为此,我进行了一些修改,使之兼容两种方式。下面将经过我修改、测试后的代码贴出来,供大家参考。

其中,获取硬盘序列号的函数命名为GetHDSerial,该函数依赖flipAndCodeBytes函数。前者使用说明如下:

  • 函数名:GetHDSerial
    功能:用于获取指定编号的硬盘序列号,无需任何权限提升
  • 参数:

    • PCHAR pszIDBuff:传入的字符串缓冲区,用于接收硬盘序列号
    • int nBuffLen:传入的字符串缓冲区大小,当硬盘序列号大于该值时,只复制nBuffLen长度
    • int nDriveID:要获取的驱动器编号,从0开始,到15为止
  • 返回值:成功获取到的硬盘序列号长度,为0表示获取失败

#include <locale.h>
#include <tchar.h>
#include <windows.h>
#include <stdio.h>char * flipAndCodeBytes(const char * str,int pos,int flip,char * buf)
{int i;int j = 0;int k = 0;buf[0] = '\0';if (pos <= 0)return buf;if (!j){char p = 0;// First try to gather all characters representing hex digits only.j = 1;k = 0;buf[k] = 0;for (i = pos; j && str[i] != '\0'; ++i){char c = tolower(str[i]);if (isspace(c))c = '0';++p;buf[k] <<= 4;if (c >= '0' && c <= '9')buf[k] |= (unsigned char)(c - '0');else if (c >= 'a' && c <= 'f')buf[k] |= (unsigned char)(c - 'a' + 10);else{j = 0;break;}if (p == 2){if (buf[k] != '\0' && !isprint(buf[k])){j = 0;break;}++k;p = 0;buf[k] = 0;}}}if (!j){// There are non-digit characters, gather them as is.j = 1;k = 0;for (i = pos; j && str[i] != '\0'; ++i){char c = str[i];if (!isprint(c)){j = 0;break;}buf[k++] = c;}}if (!j){// The characters are not there or are not printable.k = 0;}buf[k] = '\0';if (flip)// Flip adjacent charactersfor (j = 0; j < k; j += 2){char t = buf[j];buf[j] = buf[j + 1];buf[j + 1] = t;}// Trim any beginning and end spacei = j = -1;for (k = 0; buf[k] != '\0'; ++k){if (!isspace(buf[k])){if (i < 0)i = k;j = k;}}if ((i >= 0) && (j >= 0)){for (k = i; (k <= j) && (buf[k] != '\0'); ++k)buf[k - i] = buf[k];buf[k - i] = '\0';}return buf;
}/************************************************************************
GetHDSerial:用于获取指定编号的硬盘序列号,无需任何权限提升
参数:
PCHAR pszIDBuff:传入的字符串缓冲区,用于接收硬盘序列号
int nBuffLen:传入的字符串缓冲区大小,当硬盘序列号大于该值时,只复制nBuffLen长度
int nDriveID:要获取的驱动器编号,从0开始,到15为止
返回值:
成功获取到的硬盘序列号长度,为0表示获取失败
作者:
famous214(blog.csdn.net/LPWSTR)
源码参考了diskid32(https://www.winsim.com/diskid32/diskid32.html)
版本历史:
20171226 第一版,从diskid32源码中提取
20171226 第二版,兼容Unicode编译方式
20171230 重构后发布第三版
************************************************************************/
ULONG GetHDSerial(PCHAR pszIDBuff, int nBuffLen, int nDriveID)
{HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;ULONG ulSerialLen = 0;__try{//  Try to get a handle to PhysicalDrive IOCTL, report failure//  and exit if can't.TCHAR szDriveName[32];wsprintf(szDriveName, TEXT("\\\\.\\PhysicalDrive%d"), nDriveID);//  Windows NT, Windows 2000, Windows XP - admin rights not requiredhPhysicalDrive = CreateFile(szDriveName, 0,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 0, NULL);if (hPhysicalDrive == INVALID_HANDLE_VALUE){__leave;}STORAGE_PROPERTY_QUERY query;DWORD cbBytesReturned = 0;static char local_buffer[10000];memset((void *)&query, 0, sizeof(query));query.PropertyId = StorageDeviceProperty;query.QueryType = PropertyStandardQuery;memset(local_buffer, 0, sizeof(local_buffer));if (DeviceIoControl(hPhysicalDrive, IOCTL_STORAGE_QUERY_PROPERTY,&query,sizeof(query),&local_buffer[0],sizeof(local_buffer),&cbBytesReturned, NULL)){STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *)& local_buffer;char serialNumber[1000];flipAndCodeBytes(local_buffer,descrip->SerialNumberOffset,1, serialNumber);if (isalnum(serialNumber[0])){ULONG ulSerialLenTemp = strnlen(serialNumber, nBuffLen - 1);memcpy(pszIDBuff, serialNumber, ulSerialLenTemp);pszIDBuff[ulSerialLenTemp] = NULL;ulSerialLen = ulSerialLenTemp;__leave;}}}__finally{if (hPhysicalDrive != INVALID_HANDLE_VALUE){CloseHandle(hPhysicalDrive);}return ulSerialLen;}
}void GetAllHDSerial(void)
{const int MAX_IDE_DRIVES = 16;static char szBuff[0x100];for (int nDriveNum = 0; nDriveNum < MAX_IDE_DRIVES; nDriveNum++){ULONG ulLen = GetHDSerial(szBuff, sizeof(szBuff), nDriveNum);if (ulLen > 0){_tprintf(TEXT("第%d块硬盘的序列号为:%hs\n"), nDriveNum + 1, szBuff);}}
}int main()
{setlocale(LC_ALL, "chs");GetAllHDSerial();system("pause");return 0;
}

Windows下使用C++(Win32SDK)编程无需提权读取硬盘序列号(XP、Win7和Win10都可用)相关推荐

  1. Windows权限提升—令牌窃取、UAC提权、进程注入等提权

    Windows权限提升-令牌窃取.UNC提权.进程注入等提权 1. 前言 2. at本地命令提权 2.1. 适用范围 2.2. 命令使用 2.3. 操作步骤 2.3.1. 模拟提权 2.3.2. at ...

  2. Windows系统安全风险-本地NTLM重放提权

    经我司安全部门研究分析,近期利用NTLM重放机制入侵Windows 系统事件增多,入侵者主要通过Potato程序攻击拥有SYSTEM权限的端口伪造网络身份认证过程,利用NTLM重放机制骗取SYSTEM ...

  3. Qt在Windows下的三种编程环境搭建

    未经验证,记录在此. 尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/17363165 从QT官网可以得 ...

  4. Windows核心编程_提权

    在Windows下编程有些涉及到硬件或者跨内存的API会发现失效了,原因是因为权限问题,这也是Windows出于安全的保护,但是事物都有两面性的,Windows又为我们提供了提权的API! 1.Adj ...

  5. Snmp在Windows下的实现----WinSNMP编程原理

    在Windows 下实现SNMP协议的编程,可以采用Winsock接口,在161,162端口通过udp传送信息.在Windows 2000中,Microsoft已经封装了SNMP协议的实现,提供了一套 ...

  6. Windows下C语言网络编程快速入门

    C语言的学习,一般的方式是,先学C,然后是C++,最好还要有汇编语言和微机原理基础,然后才是Visual C++.这样的方式,对学习者来说,要花费很多时间和耐力.而在学校教学中,也没有时间深入学习Wi ...

  7. Linux与Windows下的socket网络编程对比

    阅读前请看一下:我是一个热衷于记录的人,每次写博客会反复研读,尽量不断提升博客质量.文章设置为仅粉丝可见,是因为写博客确实花了不少精力.希望互相进步谢谢!! 文章目录 阅读前请看一下:我是一个热衷于记 ...

  8. windows下开发PHP扩展(无需Cygwin)

    第一步:准备 1.php源码包和windows下的二进制包,以及安装Visual C++,并把Microsoft Visual Studio/Common/MSDev98/Bin的绝对路径添加到win ...

  9. windows下如何进行linux编程,生产者-消费者问题编程简单实现--windows和linux下

    又是某课程的实验(感觉好烦啊啊...),这次终于不用编译内核了,但是但是,他让我们写多线程.好吧,那就写写写,但是等等..他要我们实现生产者-消费者同步问题,要用信号量解决同步问题..这几个都是什么鬼 ...

  10. Windows下对游戏杆编程

    我现在所知道的获取游戏杆输入的方法有4种,第4种才是我要说的正题. 1.用DDK通过USB接口直接访问游戏杆 2.通过汇编访问游戏杆 据说在NT下不能这么用了 3.用Direct Input 也许会很 ...

最新文章

  1. 在Win10下如何实现VS下工程代码的开机自启功能
  2. 我在兰亭这三年之第一个项目
  3. 这是一个沙雕题II(思维好题)
  4. redis的lrange_thinkphp5操作redis系列教程】列表类型之lRange,lGetRange
  5. 中国计算机学科建设,计算机学科建设战略研讨会暨“十四五”规划务虚会召开...
  6. 第13章 程序的动态加载和执行(二,用户代码)
  7. android语音识别开源代码,android语音识别,有没有相应的源码,教程可以推荐啊?
  8. Java8新特性总结 - 4.方法引用
  9. Python机器学习:评价分类结果008多分类问题中的混淆矩阵
  10. 【Spring】Spring 依赖注入之手动注入
  11. 我竟然用git send-mail通过QQ邮箱提交了push request
  12. springboot简单的整合swagger
  13. 小程序使用绑定手机号码接口显示失败
  14. 【Excel-2010】人口金字塔图
  15. 我要偷偷的学Python,然后惊呆所有人(第五天)
  16. 高等数学学习笔记——第七十六讲——直角坐标系下二重积分的计算
  17. 异步通信之IOCP详解
  18. 深入理解计算机大端与小端
  19. TCP的三次握手和四次握手详解
  20. 教你如何获取网站icon图标!!

热门文章

  1. stata15中文乱码_如何解决 Stata 14 的中文乱码问题?
  2. mac 程序员装机必备 一篇齐全
  3. uds协议之can总线程序升级
  4. 汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码
  5. 傅里叶变换与拉普拉斯变换
  6. 计算机保研夏令营预推免
  7. 软件观念革命-交互设计精髓
  8. mysql varbinary类型_mysql中varbinary、binary、char、varchar异同
  9. 【PSFTP】Windows从Linux获取文件或目录
  10. linux远程原来显示器,【LINUX】(Ubuntu)无显示器接入,使用虚拟显示器且远程控制...