0%

在内核驱动中验证签名算法(1)

简介

这里在内核中验证签名含有两层意义,一个是验证PE文件的数字签名,另一个是验证当前正在跟驱动
通讯的进程,是否是被允许的进程,这就需要我们自定义一段信息,嵌入到PE文件中作为验证信息

自定义签名

自定义签名实际操作,就是在应用程序中增加一个数据段,存储对PE文件做的签名校验码和标志等,
这些信息使用RSA算法的私钥进行加密,最后在驱动中使用对应公钥进行解密校验。

一般常见的 CryptoAPI 函数并不能在驱动中使用,所以我们使用 bcrypt.h 包含的BCrypt* 系列
功能,在应用层使用 bcrypt.lib 库,在驱动层使用 ksecdd.lib 库,调用的API名称都相同。

使用SHA1计算信息的hash值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bcrypt.h>
#define SHA1_HASH_SIZE 20
BOOLEAN HashDataSHA1(
IN PUCHAR InBuffer, IN ULONG InSize,
OUT PUCHAR OutBuffer, IN ULONG OutSize)
{
NTSTATUS Status;
UCHAR HashResult[SHA1_HASH_SIZE];
BCRYPT_ALG_HANDLE AlgHandle;
BCRYPT_HASH_HANDLE HashHandle;
// 可以使用BCryptGetProperty(BCRYPT_HASH_LENGTH)获取算法结果的长度
if (!InBuffer || !InSize || !OutBuffer || (OutSize < SHA1_HASH_SIZE)) return FALSE;
// 使用SHA1算法
Status = BCryptOpenAlgorithmProvider(&AlgHandle, BCRYPT_SHA1_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(Status)) return FALSE;
// 创建HASH句柄
Status = BCryptCreateHash(AlgHandle, &HashHandle, NULL, 0, NULL, 0, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 开始HASH数据
Status = BCryptHashData(HashHandle, InBuffer, InSize, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyHash(HashHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 得到HASH结果
Status = BCryptFinishHash(HashHandle, HashResult, SHA1_HASH_SIZE, 0);
BCryptDestroyHash(HashHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
if (!BCRYPT_SUCCESS(Status)) return FALSE;
// 复制到输出
memmove(OutBuffer, HashResult, SHA1_HASH_SIZE);
return TRUE;
}
生成RSA的512位密钥对

注意RSA公钥和私钥的长度并不相等,出于安全考虑应该使用2048位的,这里只用于例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#define RSA512_SIGN_SIZE 64
BOOLEAN MakeKeyRSA512(
OUT PUCHAR PublicBuffer, IN ULONG PublicSize, OUT PULONG PublicReal,
OUT PUCHAR PrivateBuffer, IN ULONG PrivateSize, OUT PULONG PrivateReal)
{
NTSTATUS Status;
BCRYPT_ALG_HANDLE AlgHandle;
BCRYPT_KEY_HANDLE KeyHandle;
// 检查参数的有效性
if (!PublicBuffer || (PublicSize < 91) || !PublicReal ||
!PrivateBuffer || (PrivateSize < 155) || !PrivateReal) return FALSE;
// 使用RSA算法
Status = BCryptOpenAlgorithmProvider(&AlgHandle, BCRYPT_RSA_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(Status)) return FALSE;
// 创建空的密钥对
Status = BCryptGenerateKeyPair(AlgHandle, &KeyHandle, RSA512_SIGN_SIZE * 8, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 生成密钥对
Status = BCryptFinalizeKeyPair(KeyHandle, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 导出公钥
Status = BCryptExportKey(KeyHandle, NULL,
BCRYPT_RSAPUBLIC_BLOB, PublicBuffer, PublicSize, PublicReal, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 导出私钥
Status = BCryptExportKey(KeyHandle, NULL,
BCRYPT_RSAPRIVATE_BLOB, PrivateBuffer, PrivateSize, PrivateReal, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return TRUE;
}
使用私钥给hash签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
BOOLEAN SignHashRSA512(
IN PUCHAR PrivateBuffer, IN ULONG PrivateSize,
IN PUCHAR HashBuffer, IN ULONG HashSize,
OUT PUCHAR SignBuffer, IN ULONG SignSize)
{
NTSTATUS Status;
ULONG ResultSize;
BCRYPT_ALG_HANDLE AlgHandle;
BCRYPT_KEY_HANDLE KeyHandle;
BCRYPT_PKCS1_PADDING_INFO PadInfo;
// 检查参数的有效性
if (!HashBuffer || !HashSize || (HashSize > (RSA512_SIGN_SIZE - 12)) ||
!SignBuffer || (SignSize < RSA512_SIGN_SIZE)) return FALSE;
// 使用RSA算法
Status = BCryptOpenAlgorithmProvider(&AlgHandle, BCRYPT_RSA_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(Status)) return FALSE;
// 导入RSA私钥
Status = BCryptImportKeyPair(AlgHandle, NULL,
BCRYPT_RSAPRIVATE_BLOB, &KeyHandle, PrivateBuffer, PrivateSize, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 获取计算的结果
PadInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
Status = BCryptSignHash(KeyHandle, &PadInfo,
HashBuffer, HashSize, SignBuffer, SignSize, &ResultSize, BCRYPT_PAD_PKCS1);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return TRUE;
}
使用公钥验证hash的签名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
BOOLEAN VerifyHashRSA512(
IN PUCHAR PublicBuffer, IN ULONG PublicSize,
IN PUCHAR HashBuffer, IN ULONG HashSize,
IN PUCHAR SignBuffer, IN ULONG SignSize)
{
NTSTATUS Status;
BCRYPT_ALG_HANDLE AlgHandle;
BCRYPT_KEY_HANDLE KeyHandle;
BCRYPT_PKCS1_PADDING_INFO PadInfo;
// 检查参数的有效性
if (!HashBuffer || !HashSize || (HashSize > (RSA512_SIGN_SIZE - 12)) ||
!SignBuffer || (SignSize != RSA512_SIGN_SIZE)) return FALSE;
// 使用RSA算法
Status = BCryptOpenAlgorithmProvider(&AlgHandle, BCRYPT_RSA_ALGORITHM, NULL, 0);
if (!BCRYPT_SUCCESS(Status)) return FALSE;
// 导入RSA公钥
Status = BCryptImportKeyPair(AlgHandle, NULL,
BCRYPT_RSAPUBLIC_BLOB, &KeyHandle, PublicBuffer, PublicSize, 0);
if (!BCRYPT_SUCCESS(Status))
{
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
// 验证信息是否正确
PadInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM;
Status = BCryptVerifySignature(KeyHandle, &PadInfo,
HashBuffer, HashSize, SignBuffer, SignSize, BCRYPT_PAD_PKCS1);
if (!BCRYPT_SUCCESS(Status))
{
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return FALSE;
}
BCryptDestroyKey(KeyHandle);
BCryptCloseAlgorithmProvider(AlgHandle, 0);
return TRUE;
}
调用示例main函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
UCHAR PublicKey[256] = { 0 };
UCHAR PrivateKey[256] = { 0 };
UCHAR DataBuffer[] = "Hello World";
UCHAR HashBuffer[SHA1_HASH_SIZE] = { 0 };
UCHAR SignBuffer[RSA512_SIGN_SIZE] = { 0 };
ULONG SignReal = 0;
ULONG PublicReal = 0;
ULONG PrivateReal = 0;
MakeKeyRSA512(PublicKey, 256, &PublicReal, PrivateKey, 256, &PrivateReal);
HashDataSHA1(DataBuffer, sizeof(DataBuffer), HashBuffer, SHA1_HASH_SIZE);
SignHashRSA512(PrivateKey, PrivateReal, HashBuffer, SHA1_HASH_SIZE, SignBuffer, RSA512_SIGN_SIZE);
VerifyHashRSA512(PublicKey, PublicReal, HashBuffer, SHA1_HASH_SIZE, SignBuffer, RSA512_SIGN_SIZE);
return 0;
}