在需要对计算机进行标识的场景下,我们一般会选择获取一些硬件信息。然而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)编程无需提权读取硬盘序列号相关推荐

  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. 【TensorFlow2.0】(2) 创建tensor的方法
  2. vue-cli构建项目
  3. python 不执行函数_解决python调用自己文件函数/执行函数找不到包问题
  4. ASP.NET MVC区域
  5. 【Python】Matplotlib绘制百变椭圆
  6. 从Linux终端管理进程:10个你必须知道的命令
  7. C++之文件操作探究(二):读文件——文本文件
  8. 通过bginfo小工具让用户自己查看用户名与IP地址信息
  9. 华为进军美国受挫:竟被美运营商巨头临时放鸽子
  10. qt新建html5,QT Creator无法创建纯C++项目或HTML5项目(QT Creator直接关闭)
  11. Mac基础知识:在mac上怎么使用程序坞
  12. mysql查询父子关系树_根据数据的父子关系创建树形结构并实现遍历
  13. echarts关系图指向混乱
  14. python双星号什么运算_**(双星号/星号)和*(星号/星号)对参数有什么作用?...
  15. 使用电脑获取手机相册教程
  16. 动物派对怎么修改服务器,动物派对登录失败怎么办 Party Animals玩法进入游戏解决方法...
  17. 3级网络技术第一套题
  18. 老男孩教育 | 0基础学习三个月的心得分享!
  19. php网店系统与java网店系统的区别
  20. 2020年第二届网鼎杯,青龙队伍题目,共十八道

热门文章

  1. C语言编程乐高,ROBOLAB 2.9 编程指南第五章乐高机器人-基础小实验
  2. Appium使用教程
  3. Android 阿里云热修复
  4. android弹出窗背景透明,Android Dialog 弹框之外的区域 默认透明背景色修改
  5. idea创建svn分支
  6. 如何在Windows下像Mac一样优雅开发
  7. 《FLUENT 14流场分析自学手册》——1.3 附面层理论
  8. SI 9000 及阻抗匹配学习笔记(四)
  9. JSONArray.fromObject(str)
  10. 基于MFC的OpenDDS发布订阅例子(idl)