⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pwdump.c

📁 解NT密码的源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		   ((array[2]<<16)&0xff0000) +
		   ((array[3]<<24)&0xff000000));
}

/*
 * Convert a 7 byte array into an 8 byte des key with odd parity.
 */

void str_to_key(unsigned char *str,unsigned char *key)
{
	void des_set_odd_parity(des_cblock *);
	int i;

	key[0] = str[0]>>1;
	key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
	key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
	key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
	key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
	key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
	key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
	key[7] = str[6]&0x7F;
	for (i=0;i<8;i++) {
		key[i] = (key[i]<<1);
	}
	des_set_odd_parity((des_cblock *)key);
}

/*
 * Function to convert the RID to the first decrypt key.
 */

void sid_to_key1(unsigned long sid,unsigned char deskey[8])
{
	unsigned char s[7];

	s[0] = (unsigned char)(sid & 0xFF);
	s[1] = (unsigned char)((sid>>8) & 0xFF);
	s[2] = (unsigned char)((sid>>16) & 0xFF);
	s[3] = (unsigned char)((sid>>24) & 0xFF);
	s[4] = s[0];
	s[5] = s[1];
	s[6] = s[2];

	str_to_key(s,deskey);
}

/*
 * Function to convert the RID to the second decrypt key.
 */

void sid_to_key2(unsigned long sid,unsigned char deskey[8])
{
	unsigned char s[7];
	
	s[0] = (unsigned char)((sid>>24) & 0xFF);
	s[1] = (unsigned char)(sid & 0xFF);
	s[2] = (unsigned char)((sid>>8) & 0xFF);
	s[3] = (unsigned char)((sid>>16) & 0xFF);
	s[4] = s[0];
	s[5] = s[1];
	s[6] = s[2];

	str_to_key(s,deskey);
}

/*
 * Function to split a 'V' entry into a users name, passwords and comment.
 */

int check_vp(char *vp, int vp_size, char **username, char **fullname,
			 char **comment, char **homedir,
			 char *lanman,int *got_lanman,
			 char *md4,  int *got_md4,
			 DWORD rid
			 )
{
	des_key_schedule ks1, ks2;
	des_cblock deskey1, deskey2;
	int username_offset = get_int(vp + 0xC);
	int username_len = get_int(vp + 0x10); 
	int fullname_offset = get_int(vp + 0x18);
	int fullname_len = get_int(vp + 0x1c);
	int comment_offset = get_int(vp + 0x24);
	int comment_len = get_int(vp + 0x28);
	int homedir_offset = get_int(vp + 0x48);
	int homedir_len = get_int(vp + 0x4c);
	int pw_offset = get_int(vp + 0x9c);

	*username = 0;
	*fullname = 0;
	*comment = 0;
	*homedir = 0;
	*got_lanman = 0;
	*got_md4 = 0;

	if(username_len < 0 || username_offset < 0 || comment_len < 0 ||
			   fullname_len < 0 || homedir_offset < 0 ||
		       comment_offset < 0 || pw_offset < 0)
		return -1;
	username_offset += 0xCC;
	fullname_offset += 0xCC;
	comment_offset += 0xCC;
	homedir_offset += 0xCC;
	pw_offset += 0xCC;

	if((*username = (char *)malloc(username_len + 1)) == 0) {
		fprintf(stderr, "check_vp: malloc fail for username.\n");
		return -1;
	}
	if((*fullname = (char *)malloc(fullname_len + 1)) == 0) {
		fprintf(stderr, "check_vp: malloc fail for username.\n");
		free(*username);
		*username = 0;
		return -1;
	}
	if((*comment = (char *)malloc(comment_len + 1)) == 0) {
		fprintf(stderr, "check_vp: malloc fail for comment.\n");
		free(*username);
		*username = 0;
		free(*fullname);
		*fullname = 0;
		return -1;
	}
	if((*homedir = (char *)malloc(homedir_len + 1)) == 0) {
		fprintf(stderr, "check_vp: malloc fail for homedir.\n");
		free(*username);
		*username = 0;
		free(*fullname);
		*fullname = 0;
		free(*comment);
		*comment = 0;
		return -1;
	}
	wcstombs( *username, (wchar_t *)(vp + username_offset), username_len/sizeof(wchar_t));
	(*username)[username_len/sizeof(wchar_t)] = 0;
	wcstombs( *fullname, (wchar_t *)(vp + fullname_offset), fullname_len/sizeof(wchar_t));
	(*fullname)[fullname_len/sizeof(wchar_t)] = 0;
	wcstombs( *comment, (wchar_t *)(vp + comment_offset), comment_len/sizeof(wchar_t));
	(*comment)[comment_len/sizeof(wchar_t)] = 0;
	wcstombs( *homedir, (wchar_t *)(vp + homedir_offset), homedir_len/sizeof(wchar_t));
	(*homedir)[homedir_len/sizeof(wchar_t)] = 0;

	if(pw_offset >= vp_size) {
		/* No password */
		*got_lanman = 0;
		*got_md4 = 0;
		return 0;
	}

	/* Check that the password offset plus the size of the
	   lanman and md4 hashes fits within the V record. */
	if(pw_offset + 32 > vp_size) {
		/* Account disabled ? */
		*got_lanman = -1;
		*got_md4 = -1;
		return 0;
	}

	/* Get the two decrpt keys. */
	sid_to_key1(rid,(unsigned char *)deskey1);
	des_set_key((des_cblock *)deskey1,ks1);
	sid_to_key2(rid,(unsigned char *)deskey2);
	des_set_key((des_cblock *)deskey2,ks2);
	
	vp += pw_offset;
	/* Decrypt the lanman password hash as two 8 byte blocks. */
	des_ecb_encrypt((des_cblock *)vp,
					(des_cblock *)lanman, ks1, DES_DECRYPT);
	des_ecb_encrypt((des_cblock *)(vp + 8),
					(des_cblock *)&lanman[8], ks2, DES_DECRYPT);

	vp += 16;
	/* Decrypt the NT md4 password hash as two 8 byte blocks. */
	des_ecb_encrypt((des_cblock *)vp,
					(des_cblock *)md4, ks1, DES_DECRYPT);
	des_ecb_encrypt((des_cblock *)(vp + 8),
					(des_cblock *)&md4[8], ks2, DES_DECRYPT);

	*got_lanman = 1;
	*got_md4 = 1;
	return 0;
}

/*
 * Function to print out a 16 byte array as hex.
 */

void print_hexval(char *val)
{
	int i;
	for(i = 0; i < 16; i++)
		printf("%02X", (unsigned char)val[i]);
}

/* 
 * Function to strip out any ':' or '\n', '\r' from a text
 * string.
 */

void strip_text( char *txt )
{
	char *p;
	for( p = strchr(txt, ':'); p ; p = strchr( p + 1, ':'))
		*p = '_';
	for( p = strchr(txt, '\n'); p ; p = strchr(p + 1, '\n'))
		*p = '_';										   
	for( p = strchr(txt, '\r'); p ; p = strchr(p + 1, '\r'))
		*p = '_';
}

/*
 * Function to dump a users smbpasswd entry onto stdout.
 * Returns 0 on success, -1 on fail.
 */

int printout_smb_entry( HKEY user, DWORD rid )
{
 	DWORD err;
	DWORD type;
	DWORD size = 0;
	char *vp;
	char lanman[16];
	char md4_hash[16];
	char *username;
	char *fullname;
	char *comment;
	char *homedir;
	int got_lanman;
	int got_md4;

	/* Find out how much space we need for the 'V' value. */
	if((err = RegQueryValueEx( user, "V", 0, &type, 0, &size)) 
								!= ERROR_SUCCESS) {
		fprintf(stderr, "printout_smb_entry: Unable to determine size needed \
for user 'V' value. Error was %s.\n.", str_oserr(err));
		return -1;
	}
	if((vp = (char *)malloc(size)) == 0) {
		fprintf(stderr, "printout_smb_entry: malloc fail for user entry.\n");
		return -1;
	}
	if((err = RegQueryValueEx( user, "V", 0, &type, (LPBYTE)vp, &size)) 
								!= ERROR_SUCCESS) {
		fprintf(stderr, "printout_smb_entry: Unable to read user 'V' value. \
Error was %s.\n.", str_oserr(err));
		free(vp);
		return -1;
	}
	/* Check heuristics */
	if(check_vp(vp, size, &username, &fullname, &comment, 
						&homedir, lanman, &got_lanman, 
		               md4_hash, &got_md4, rid) != 0) {
		fprintf(stderr, "Failed to parse entry for RID %X\n", rid);
		free(vp);
		return 0;
	}
	/* Ensure username of comment don't have any nasty suprises
	   for us such as an embedded ':' or '\n' - see multiple UNIX
	   passwd field update security bugs for details... */
	strip_text( username );
	strip_text( fullname );
	strip_text( comment );
	/* If homedir contains a drive letter this mangles it - but it protects
	   the integrity of the smbpasswd file. */
	strip_text( homedir );

	printf("%s:%d:", username, rid);
	if(got_lanman) {
		if(got_lanman == -1) /* Disabled account ? */
			printf("********************************");
		else
			print_hexval(lanman);
	} else
		printf("NO PASSWORD*********************");
	printf(":");
	if(got_md4) {
		if(got_md4 == -1)  /* Disabled account ? */
			printf("********************************");
		else
			print_hexval(md4_hash);
	} else
		printf("NO PASSWORD*********************");
	printf(":");
	if(*fullname)
		printf("%s", fullname);
	if(*fullname && *comment)
		printf(",");
	if(*comment)
		printf("%s", comment);
	printf(":");
	if(*homedir)					   
		printf("%s", homedir);
	printf(":\n");

	free(username);
	free(comment);
	free(homedir);
	free(vp);
	return 0;
}

/*
 * Function to go through all the user SID's - dumping out
 * their SAM values. Returns 0 on success, -1 on fail.
 */

int enumerate_users( HKEY key)
{
	DWORD indx = 0;
	DWORD err;
	DWORD rid;
	char usersid[128];

	do {
		DWORD size;
		FILETIME ft;

		size = sizeof(usersid);
		err = RegEnumKeyEx(	key, indx, usersid, &size, 0, 0, 0, &ft);
		if(err == ERROR_SUCCESS) {
			HKEY subkey;

			indx++;
			if((err = RegOpenKeyEx( key, usersid, 0, KEY_QUERY_VALUE, &subkey)) !=
						ERROR_SUCCESS) {
				fprintf(stderr, "enumerate_users: Failed to open key %s to read value. \
Error was %s.\n",
						usersid, str_oserr(err));
				RegCloseKey(key);
				return -1;
			}
			rid = strtoul(usersid, 0, 16);
			/* Hack as we know there is a Names key here */
			if(rid != 0) {
				if(printout_smb_entry( subkey, rid ) != 0) {
					RegCloseKey(subkey);
					return -1;
				}
			}
			RegCloseKey(subkey);
		}
	} while(err == ERROR_SUCCESS);

	if(err != ERROR_NO_MORE_ITEMS) {
		RegCloseKey(key);
		return -1;
	}
	return 0;
}

/*
 * Print usage message and die.
 */
void usage(const char *arg0) {
	fprintf(stderr, "Usage: %s <\\\\machine>\n", arg0);
	exit(-1);
}

/*
 * usage: \\machine
 */

int main(int argc, char **argv)
{
	char username[128];
	DWORD size;
	HKEY start_key = HKEY_LOCAL_MACHINE;
	HKEY users_key;
	int err;

	if(argc > 2)
		usage(argv[0]);

	/*
	 * Ensure we are running as Administrator before
	 * we will run.
	 */
	size = sizeof(username);
	if(GetUserName(username, &size)== FALSE) {
		fprintf(stderr, "%s: GetUserName() failed. Error was %s.", 
			argv[0], str_oserr(GetLastError()));
		return -1;
	}

	
	/* 
	 * Open a connection to the remote machines registry.
	 */
	if(argc == 2) {
		if((err = RegConnectRegistry( argv[1], HKEY_LOCAL_MACHINE, &start_key)) !=
			ERROR_SUCCESS) {
			fprintf(stderr, "%s: Failed to connect to registry on remote computer %s.\
Error was %s.\n", argv[0], argv[1], str_oserr(err));
			return -1;
		}
	}

	/* 
	 * We need to get to HKEY_LOCAL_MACHINE\SECURITY\SAM\Domains\Account\Users.
	 * The security on this key normally doesn't allow Administrators
	 * to read - we need to add this.
	 */

	if((err = set_sam_tree_access( start_key, &users_key)) != 0) {
		if(err == -2)
			restore_sam_tree_access( start_key);
		return -1;
	}
	/* Print the users SAM entries in smbpasswd format onto stdout. */
	enumerate_users( users_key );
	RegCloseKey(users_key);
	/* reset the security on the SAM */
	restore_sam_tree_access( start_key );
	if(start_key != HKEY_LOCAL_MACHINE)
		RegCloseKey(start_key);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -