NTLM Encryption

I am trying to convert a given string into an LM hash. Since there are no libraries (that I could find anyway) i went on wikipedia and am in the process of using:


The LM hash is computed as follows:[1][2]

1. The user’s ASCII password is converted to uppercase.
2. This password is null-padded to 14 bytes.[Notes 1][3]
3. The “fixed-length” password is split into two 7-byte halves.
4. These values are used to create two DES keys, one from each 7-byte half, by converting the seven bytes into a bit stream, and inserting a null bit after every seven bits (so 1010100 becomes 01010100). This generates the 64 bits needed for the DES key.
5. Each of these keys is used to DES-encrypt the constant ASCII string “KGS!@#$%”, resulting in two 8-byte ciphertext values. The DES CipherMode should Set to ECB, and PaddingMode should set to NONE.
6. These two ciphertext values are concatenated to form a 16-byte value, which is the LM hash.


I can convert the string to uppercase, then null pad it to 14 bytes (I am assuming this means adding whitespace to the end...please correct me if I am wrong), then i was able to split it but I cannot make it into a DES hash (I am using the openSSL library for this). I cannot figure out how to get the format right here is the code:

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <openssl/des.h>
 
using namespace std;

char *
Encrypt( char *Key, char *Msg, int size)
{
 
        static char*    Res;
        int             n=0;
        DES_cblock      Key2;
        DES_key_schedule schedule;
 
        Res = ( char * ) malloc( size );
 
        /* Prepare the key for use with DES_cfb64_encrypt */
        memcpy( Key2, Key,8);
        DES_set_odd_parity( &Key2 );
        DES_set_key_checked( &Key2, &schedule );
 
        /* Encryption occurs here */
        DES_cfb64_encrypt( ( unsigned char * ) Msg, ( unsigned char * ) Res,
                           size, &schedule, &Key2, &n, DES_ENCRYPT );
 
         return (Res);
}

int main() {      
	char crypto;  //declare all variables
	char crypto2;
	char *encrypted;
	char *encrypted2;
	char key[]="KGS!@#$%";
	int leng;
	string finpass; 
	string finpass2;
	string pass;

	cout <<"Password to encrypt: " << endl; //cin phrase to encrypt
	cin >> pass;

	if(pass.length() < 14){                 //get pass length
		leng = 14 - pass.length();
		}
	for (int a=0; a<pass.length(); a++){    //convert to uppercase
		pass[a]=toupper(pass[a]);
		}
	for (int a=0; a<leng; a++){             //add whitespace at the end till it is 14 characters
		pass += " ";
		}
	finpass = pass.substr(0,7);             //split into two seven character strings
	finpass2 = pass.substr(7,13); 

	cout << finpass << "."<< endl;          //test for a succesful split
	cout << finpass2 << "." <<endl;

	encrypted=(char*)malloc(sizeof(finpass));//encrypt the passwords
	encrypted2=(char*)malloc(sizeof(finpass2));

	printf("Clear text\t : %s \n",finpass);
	memcpy(encrypted,Encrypt(key,finpass,sizeof(finpass)), sizeof(finpass));
	printf("Encrypted text\t : %s \n",finpass);
	 
	printf("Clear text\t : %s \n",finpass2);
	memcpy(encrypted2,Encrypt(key,finpass2,sizeof(finpass2)), sizeof(finpass2));
	printf("Encrypted text\t : %s \n",encrypted2);
	
	return (0);
}


My error i get is:


DES-Example.cpp: In function ‘int main()’:
DES-Example.cpp:64: warning: cannot pass objects of non-POD type ‘struct std::string’ through ‘...’; call will abort at runtime
DES-Example.cpp:64: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘int’
DES-Example.cpp:65: error: cannot convert ‘std::string’ to ‘char*’ for argument ‘2’ to ‘char* Encrypt(char*, char*, int)’
DES-Example.cpp:66: warning: cannot pass objects of non-POD type ‘struct std::string’ through ‘...’; call will abort at runtime
DES-Example.cpp:66: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘int’
DES-Example.cpp:68: warning: cannot pass objects of non-POD type ‘struct std::string’ through ‘...’; call will abort at runtime
DES-Example.cpp:68: warning: format ‘%s’ expects type ‘char*’, but argument 2 has type ‘int’
DES-Example.cpp:69: error: cannot convert ‘std::string’ to ‘char*’ for argument ‘2’ to ‘char* Encrypt(char*, char*, int)’


This was compiled using g++ on Ubuntu.

Thanks.
For NULL padding I think you have to append zeros:

 
pass.append(leng, '\0');


Function printf() is expecting char arrays, not std::strings so you need to convert it:

 
printf("Clear text\t : %s \n",finpass.c_str());


But its better to use the C++ io rather than the old C io:

 
std::cout << "Clear text\t : " << finpass << '\n';
Thank you for the fast reply!

Those worked, however I still get an error with the line:

 
memcpy(encrypted,Encrypt(key,finpass,sizeof(finpass)), sizeof(finpass));


how do I deal with this?
finpass is a string and the function wants a char*, I would guess. I would just use the c_str() function, but I think the function needs to take const char* if you want to do that.
I'm unfamiliar with the API your using but sizeof() won't give you the length of the string.

Try this:

 
memcpy(encrypted, Encrypt(key, finpass.c_str(), finpass.length()), finpass.length());
how would I go about converting a string to a const char*?
1
2
3
std::string mystring;

mystring.c_str(); // this is a const char* 
 
	memcpy(encrypted,Encrypt(key,finpass.c_str(),sizeof(finpass.c_str())), sizeof(finpass.c_str()));


This still generates an error.
as does this:

 
        memcpy(encrypted, Encrypt(key, finpass.c_str(), finpass.length()), finpass.length());


The error is as follows:


DES-Example.cpp:65: error: invalid conversion from ‘const char*’ to ‘char*’
DES-Example.cpp:65: error: initializing argument 2 of ‘char* Encrypt(char*, char*, int)’
As I said, the Encypt() function would need to take const char* in order to pass in c_str(). It probably should be taking those anyway since I don't see it modifying them.
You are missing quite a bit when preparing the hash.
I was going to write up something for you, but I have to go now.
In the mean time, you might want to check out some of the links at the bottom of the Wikipedia page, such as this one:
http://forums.sun.com/thread.jspa?threadID=742735&tstart=2056

Good luck!
So I looked around and found a great perl script (thank you Duoas) for this how would I implement this in the rest of my C++ program?
Or would it be better to start from scratch in perl?
If its important then use whatever language works for you. If its a learning exercise then use whatever language you are trying to learn ;o)
yea i wrote it from scratch really easy too...
not sure why there is nothing like that in c++ hahaha..
thanks for the help
Doesn't Samba have a library for this?
yes thats what I used for the perl script
Topic archived. No new replies allowed.