全网首一份!你最必要的PPTP MS-CHAP V2 挑衅响应编程模拟计算教程!代码基
本文基于网络密码课上的实验本来想水一水就过去,代码就网上找找,不行就GPT写,但是!一份都找不到,找到的代码都是跑不了的,总会是就是乱七八糟。所以预备认真的写一份。
代码编译成功的前提是要预先装好openssl库!
本随笔主要有三个内容:
[*]编写程序,模拟计算NTResponse、AuthenticatorResponse,
[*]根据前期PPTP实验中捕捉的数据包中CHAP协议的挑衅响应认证数据,在未知用户口令情况下编程实现CHAP认证口令的破解
在单向数据条件下(仅能截获用户数据)实现CHAP认证口令的破解
首先放一个我自己抓的包,可以看到,这是chap协议挑衅响应的三次握手,
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518173734319-1518553077.png
那么我们继承举行,编程模拟,就要先搞清楚每个字段代表的什么,文档中第一个包的描述,给的是Authenticator challenge
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518173938913-1174350559.png
也就是我住的第一个包里的value
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174023712-1572202724.png
这是第二个包,16字节peer-challenge,8位的0,24位的NT-Response
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174045229-2048851115.png
value内的值,对应看
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174205094-1370179735.png
第三个包,内容是s=authticator-response
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174243870-1775828997.png
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174257536-8295139.png
接下来我们开始编程实现,每一个字段都是由对应的函数计算得出
一、编写程序,模拟计算NTResponse、AuthenticatorResponse
1.查阅RFC2759文档,找到描述的计算NTResponse的函数
NT-Response的值是由GenerateNTResponse()计算得出,看到该函数有四个输入,分别是AuthenticatorChallenge(16)、PeerChallenge(16)、UserName和Password,一个输出Response(24)
此外,有三个函数对输入进行处理:ChallengeHash:对两个挑战值hash,结果放到challenge中。NtPasswordHash:对password做hash,结果放到password中。ChallengeResponse:对challenge和passwordhash做运算,结果得到NT-Response。2.根据文档描述编写代码
GenerateNTResponse()函数
1 void GenerateNTResponse(const HCRYPTPROV hProv, const BYTE* auth_challenge, const BYTE* peer_challenge, const char* user_name, const wchar_t* password, BYTE* response)
2 {
3 BYTE challenge;
4 BYTE password_hash;
5
6 _ChallengeHash(hProv, peer_challenge, auth_challenge, user_name, challenge);
7 _NtPasswordHash(hProv, password, password_hash);
8 _ChallengeResponse(hProv, challenge, password_hash, response);
9 }_ChallengeHash()函数,对peer challenge、auth challenge、user name连接然后举行sha1哈希,结果放到challenge中返回
1 void _ChallengeHash(const HCRYPTPROV hProv, const BYTE* peer_challenge, const BYTE* auth_challenge, const char* user_name, BYTE* challenge)
2 {
3 HCRYPTHASH hHash = 0;
4 if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash))
5 throw "CryptCreateHash failed (SHA1)";
6 if (!CryptHashData(hHash, peer_challenge, 16, 0))
7 throw "CryptHashData failed (peer challenge)";
8 if (!CryptHashData(hHash, auth_challenge, 16, 0))
9 throw "CryptHashData failed (auth challenge)";
10 if (!CryptHashData(hHash, (const BYTE*)user_name,
11 (DWORD)strlen(user_name), 0))
12 throw "CryptHashData failed (user name)";
13 DWORD hash_len = SHA1LEN;
14 BYTE hash_buffer;
15 if (!CryptGetHashParam(hHash, HP_HASHVAL, hash_buffer,
16 &hash_len, 0))
17 throw "CryptGetHashParam failed (challenge hash)";
18 memcpy(challenge, hash_buffer, 8);
19
20 }_NtPasswordHash函数():将password做MD4哈希,然后返回password_hash中
1 void _NtPasswordHash(const HCRYPTPROV hProv, const wchar_t* password, BYTE* password_hash)
2 {
3 HCRYPTHASH hHash = 0;
4 if (!CryptCreateHash(hProv, CALG_MD4, 0, 0, &hHash))
5 throw "CryptCreateHash failed (MD4)";
6 if (!CryptHashData(hHash, (const BYTE*)password, lstrlenW(password) << 1, 0))
7 throw "CryptHashData failed (user password)";
8 DWORD hash_len = MD4LEN;
9 BYTE hash_buffer;
10 if (!CryptGetHashParam(hHash, HP_HASHVAL, hash_buffer, &hash_len, 0))
11 throw "CryptGetHashParam failed (NT password hash)";
12 memcpy(password_hash, hash_buffer, 16);
13 }至此,我们就算出来了NtResponse
2.计算AunthenticatorResponse
1 void _ChallengeResponse(const HCRYPTPROV hProv, const BYTE* challenge, const BYTE* password_hash, BYTE* response)
2 {
3 BYTE z_password_hash;
4 memset(z_password_hash, 0, 21);
5 memcpy(z_password_hash, password_hash, 16);
6
7 _DesEncrypt(hProv, challenge, z_password_hash, response);
8 _DesEncrypt(hProv, challenge, z_password_hash + 7, response + 8);
9 _DesEncrypt(hProv, challenge, z_password_hash + 14, response + 16);
10 } 1 typedef struct {
2 BLOBHEADER key_header;
3 DWORD key_length;
4 BYTE key_data;
5 } DESKey;
6
7 void EXPAND(BYTE* key);
8
9 void _DesEncrypt(const HCRYPTPROV hProv, const BYTE* data, const BYTE* key, BYTE* result)
10 {
11 // Fill CryptoAPI-required key structure
12 DESKey des_key;
13 des_key.key_header.bType = PLAINTEXTKEYBLOB;
14 des_key.key_header.bVersion = CUR_BLOB_VERSION;
15 des_key.key_header.reserved = 0;
16 des_key.key_header.aiKeyAlg = CALG_DES;
17 des_key.key_length = 8;
18 memcpy(des_key.key_data, key, 7);
19 EXPAND(des_key.key_data);
20
21 HCRYPTKEY hKey;
22 // import key BLOB
23 if (!CryptImportKey(hProv, (BYTE*)&des_key,
24 sizeof(des_key), 0, 0, &hKey))
25 throw "CryptImportKey failed";
26 // set ECB mode required by RFC
27 DWORD des_mode = CRYPT_MODE_ECB;
28 if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&des_mode, 0))
29 throw "CryptSetKeyParam failed (ECB mode)";
30 // set initialization vector
31 BYTE IV = { 0, 0, 0, 0, 0, 0, 0, 0 };
32 if (!CryptSetKeyParam(hKey, KP_IV, &IV, 0))
33 throw "CryptSetKeyParam failed (init vector)";
34 // encrypt
35 DWORD data_len = 8;
36 memcpy(result, data, 8); // encrypt in-place
37 if (!CryptEncrypt(hKey, 0, FALSE, 0, (BYTE*)&result, &data_len, 8))
38 throw "CryptEncrypt failed (DES)";
39 }
40
[*]该函数里面界说了长度16的PasswordHash和PasswordHashHash,长度为8的Challenge。首先,使用MD4算法对密码举行哈希处理,得到PasswordHash。
[*]然后,对PasswordHash举行再次哈希处理,得到PasswordHashHash。
[*]接着,使用SHA算法对PasswordHashHash、NT-Response和Magic1举行哈希处理,得到Digest。
[*]使用ChallengeHash函数对PeerChallenge、AuthenticatorChallenge和UserName举行哈希处理,得到Challenge。
[*]再次使用SHA算法对Digest、Challenge和Magic2举行哈希处理,得到终极的Digest
https://img2024.cnblogs.com/blog/1714636/202405/1714636-20240518174908871-951021695.png
下面是具体实现代码
</ol>
1 void GenerateAuthenticatorResponse(const HCRYPTPROV hProv, const wchar_t* password_unicode, const BYTE* NTResponse, const BYTE* PeerChalleng, const BYTE* AuthenticatorChallenge, const char* UserName) 2 { 3 BYTE Magic1 = { 0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76, 4 0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65, 5 0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67, 6 0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74 }; 7 BYTE Magic2 = { 0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B, 8 0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F, 9 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,10 0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,11 0x6E };12 BYTE Passwordhash;13 _NtPasswordHash(hProv, password_unicode, Passwordhash);14 BYTE PasswordHashhash;15 _NtPasswordHashHash(hProv, Passwordhash, PasswordHashhash);16 SHA_CTX Context;17 SHA1_Init(&Context);18 SHA1_Update(&Context, PasswordHashhash, 16);19 SHA1_Update(&Context, NTResponse, 24);20 SHA1_Update(&Context, Magic1, 39);21 unsigned char aa;22 SHA1_Final(aa, &Context);23 BYTE Challenge;24 _ChallengeHash(hProv, PeerChalleng, AuthenticatorChallenge, UserName, Challenge);25 SHA1_Init(&Context);26 SHA1_Update(&Context, aa, sizeof(aa));27 SHA1_Update(&Context, Challenge, 8);28 SHA1_Update(&Context, Magic2, 41);29 unsigned char bb;30 SHA1_Final(bb, &Context);31 cout
页:
[1]