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

📄 pwdump.c

📁 解NT密码的源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * (C) Jeremy Allison 1997. All rights reserved.
 * 
 * This program is free for commercial and non-commercial use.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted.
 *
 * THIS SOFTWARE IS PROVIDED BY JEREMY ALLISON ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "des.h"

/*
 * Program to dump the Lanman and NT MD4 Hashed passwords from
 * an NT SAM database into a Samba smbpasswd file. Needs Administrator 
 * privillages to run.
 * Takes one arg - the name of the machine whose SAM database you
 * wish to dump, if this arg is not given it dumps the local machine
 * account database.
 */

/*
 * Convert system error to char. Returns 
 * memory allocated with LocalAlloc.
 */

char *error_to_string(DWORD error)
{
  char *msgbuf;
  
  if(FormatMessage(
       FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
       NULL,
       error,
       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
       (char *)&msgbuf,
       0,
       NULL
       ) == 0)
    return 0;
  return msgbuf;
}

/*
 * Return a pointer to a string describing an os error.
 * error_to_string returns a pointer to LocalAlloc'ed
 * memory. Cache it and release when the next one is
 * requested.
 */

char *str_oserr(DWORD err)
{
  static char *lastmsg = 0;

  if(lastmsg)
    LocalFree((HLOCAL)lastmsg);

  lastmsg = error_to_string(err);
  return lastmsg;
}

/*
 * Utility function to get allocate a SID from a name.
 * Looks on local machine. SID is allocated with LocalAlloc
 * and must be freed by the caller.
 * Returns TRUE on success, FALSE on fail.
 */

BOOL get_sid(const char *name, SID **ppsid)
{
  SID_NAME_USE sid_use;
  DWORD sid_size = 0;
  DWORD dom_size = 0;
  char *domain;

  *ppsid = 0;
  if(LookupAccountName(0, name, 0, &sid_size, 0, &dom_size, &sid_use) == 0) {
    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
      fprintf( stderr, "get_sid: LookupAccountName for size on name %s failed. Error was %s\n",
            name, str_oserr(GetLastError()));
      return FALSE;
    }
  }

  *ppsid = (SID *)LocalAlloc( LMEM_FIXED, sid_size);
  domain = (char *)LocalAlloc( LMEM_FIXED, dom_size);
  if( *ppsid == 0 || domain == 0) {
    fprintf( stderr, "get_sid: LocalAlloc failed. Error was %s\n",
                 str_oserr(GetLastError()));
    if(*ppsid)
      LocalFree((HLOCAL)*ppsid);
    if(domain)
      LocalFree((HLOCAL)domain);
    *ppsid = 0;
    return FALSE;
  }

  if(LookupAccountName(0, name, *ppsid, &sid_size, domain, &dom_size, &sid_use) == 0) {
    fprintf( stderr, 
         "get_sid: LookupAccountName failed for name %s. Error was %s\n",
         name, str_oserr(GetLastError()));
    LocalFree((HLOCAL)*ppsid);
    LocalFree((HLOCAL)domain);
    *ppsid = 0;
    return FALSE;
  }

  LocalFree((HLOCAL)domain);
  return TRUE;
}

/*
 * Utility function to setup a security descriptor
 * from a varargs list of char *name followed by a DWORD access
 * mask. The access control list is allocated with LocalAlloc
 * and must be freed by the caller.
 * returns TRUE on success, FALSE on fail.
 */

BOOL create_sd_from_list( SECURITY_DESCRIPTOR *sdout, int num, ...)
{
  va_list ap;
  SID **sids = 0;
  char *name;
  DWORD amask;
  DWORD acl_size;
  PACL pacl = 0;
  int i;

  if((sids = (SID **)calloc(1,sizeof(SID *)*num)) == 0) {
    fprintf(stderr, "create_sd_from_list: calloc fail.\n");
    return FALSE;
  }

  acl_size = num * (sizeof(ACL) +
             sizeof(ACCESS_ALLOWED_ACE) +
             sizeof(DWORD));

  /* Collect all the SID's */
  va_start( ap, num);
  for( i = 0; i < num; i++) {
    name = va_arg( ap, char *);
    amask = va_arg(ap, DWORD);
    if(get_sid( name, &sids[i]) == FALSE)
      goto cleanup;
    acl_size += GetLengthSid(sids[i]);
  }
  va_end(ap);
  if((pacl = (PACL)LocalAlloc( LMEM_FIXED, acl_size)) == 0) {
    fprintf( stderr, "create_sd_from_list: LocalAlloc fail. Error was %s\n",
            str_oserr(GetLastError()));
    goto cleanup;
  }

  if(InitializeSecurityDescriptor( sdout, SECURITY_DESCRIPTOR_REVISION) == FALSE) {
    fprintf( stderr, "create_sd_from_list: InitializeSecurityDescriptor fail. Error was %s\n",
                 str_oserr(GetLastError()));
    goto cleanup;
  }
  if(InitializeAcl( pacl, acl_size, ACL_REVISION) == FALSE) {
    fprintf( stderr, "create_sd_from_list: InitializeAcl fail. Error was %s\n",
                 str_oserr(GetLastError()));
    goto cleanup;
  }
  va_start(ap, num);
  for( i = 0; i < num; i++) {
    ACE_HEADER *ace_p;
    name = va_arg( ap, char *);
    amask = va_arg( ap, DWORD);
    if(AddAccessAllowedAce( pacl, ACL_REVISION, amask, sids[i]) == FALSE) {
      fprintf( stderr, "create_sd_from_list: AddAccessAllowedAce fail. Error was %s\n",
                 str_oserr(GetLastError()));
      goto cleanup;
    }
    /* Make sure the ACE is inheritable */
    if(GetAce( pacl, 0, (LPVOID *)&ace_p) == FALSE) {
      fprintf( stderr, "create_sd_from_list: GetAce fail. Error was %s\n",
                 str_oserr(GetLastError()));
      goto cleanup;
    }
    ace_p->AceFlags |= ( CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
  }

  /* Add the ACL into the sd. */
  if(SetSecurityDescriptorDacl( sdout, TRUE, pacl, FALSE) == FALSE) {
    fprintf( stderr, "create_sd_from_list: SetSecurityDescriptorDacl fail. Error was %s\n",
               str_oserr(GetLastError()));
    goto cleanup;
  }
  for( i = 0; i < num; i++)
    if(sids[i] != 0)
      LocalFree((HLOCAL)sids[i]);
  free(sids);

  return TRUE;

cleanup:

  if(sids != 0) {
    for( i = 0; i < num; i++)
      if(sids[i] != 0)
        LocalFree((HLOCAL)sids[i]);
    free(sids);
  }
  if(pacl != 0)
    LocalFree((HLOCAL)pacl);
  return FALSE;
}

/*
 * Function to go over all the users in the SAM and set an ACL
 * on them.
 */

int set_userkeys_security( HKEY start, const char *path, SECURITY_DESCRIPTOR *psd, 
						  HKEY *return_key)
{
	HKEY key;
	DWORD err;
	char usersid[128];
	DWORD indx = 0;
	
	/* Open the path and enum all the user keys - setting
	   the same security on them. */
	if((err = RegOpenKeyEx( start, path, 0, KEY_ENUMERATE_SUB_KEYS, &key)) !=
					ERROR_SUCCESS) {
		fprintf(stderr, "set_userkeys_security: Failed to open key %s to enumerate. \
Error was %s.\n",
				    path, str_oserr(err));
			return -1;
	}


	/* Now enumerate the subkeys, setting the security on them all. */
	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, WRITE_DAC, &subkey)) !=
						ERROR_SUCCESS) {
				fprintf(stderr, "set_userkeys_security: Failed to open key %s to set security. \
Error was %s.\n",
						usersid, str_oserr(err));
				RegCloseKey(key);
				return -1;
			}
			if((err = RegSetKeySecurity( subkey, DACL_SECURITY_INFORMATION,
										 psd)) != ERROR_SUCCESS) {
				fprintf(stderr, "set_userkeys_security: Failed to set security on key %s. \
Error was %s.\n",
						usersid, str_oserr(err));
				RegCloseKey(subkey);
				RegCloseKey(key);
				return -1;
			}
			RegCloseKey(subkey);
		}
	} while(err == ERROR_SUCCESS);

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

/*
 * Function to travel down the SAM security tree in the registry and restore
 * the correct ACL on them. Returns 0 on success. -1 on fail.
 */

int restore_sam_tree_access( HKEY start )
{
	char path[128];
	char *p;
	HKEY key;
	DWORD err;
	SECURITY_DESCRIPTOR sd;
	DWORD admin_mask;

	admin_mask = WRITE_DAC | READ_CONTROL;

	if(create_sd_from_list( &sd, 2, "SYSTEM", GENERIC_ALL,
							"Administrators", admin_mask) == FALSE)
		return -1;

	strcpy( path, "SECURITY\\SAM\\Domains\\Account\\Users");

	/* Remove the security on the user keys first. */
	if(set_userkeys_security( start, path, &sd, 0) != 0)
			return -1;

	/* now go up the path, restoring security */
	do {
		if((err = RegOpenKeyEx( start, path, 0, WRITE_DAC, &key)) !=
						ERROR_SUCCESS) {
			fprintf(stderr, "restore_sam_tree_access:Failed to open key %s to set \
security. Error was %s.\n",
					path, str_oserr(err));
			return -1;
		}
		if((err = RegSetKeySecurity( key, DACL_SECURITY_INFORMATION,
									 &sd)) != ERROR_SUCCESS) {
			fprintf(stderr, "restore_sam_tree_access: Failed to set security on key %s. \
Error was %s.\n",
					path, str_oserr(err));
			RegCloseKey(key);
			return  -1;
		}
		RegCloseKey(key);
		p = strrchr(path, '\\');
		if( p != 0) 
			*p = 0;
	} while( p != 0 );

	return 0;
}

/*
 * Function to travel the security tree and add Administrators
 * access as WRITE_DAC, READ_CONTROL and READ.
 * Returns 0 on success. -1 on fail if no security was changed,
 * -2 on fail if security was changed.
 */

int set_sam_tree_access( HKEY start, HKEY *return_key)
{
	char path[128];
	char *p;
	HKEY key;
	DWORD err;
	BOOL security_changed = FALSE;
	SECURITY_DESCRIPTOR sd;
	DWORD admin_mask;
	BOOL finished = FALSE;

	admin_mask = WRITE_DAC | READ_CONTROL | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS;

	if(create_sd_from_list( &sd, 2, "SYSTEM", GENERIC_ALL,
							"Administrators", admin_mask) == FALSE)
		return -1;

	strcpy( path, "SECURITY\\SAM\\Domains\\Account\\Users");
	p = strchr(path, '\\');

	do {
		if( p != 0) 
			*p = 0;
		else
			finished = TRUE;
		if((err = RegOpenKeyEx( start, path, 0, WRITE_DAC, &key)) !=
						ERROR_SUCCESS) {
			fprintf(stderr, "set_sam_tree_access:Failed to open key %s to set \
security. Error was %s.\n",
					path, str_oserr(err));
			return (security_changed ? -2: -1);
		}
		if((err = RegSetKeySecurity( key, DACL_SECURITY_INFORMATION,
									 &sd)) != ERROR_SUCCESS) {
			fprintf(stderr, "set_sam_tree_access: Failed to set security on key %s. \
Error was %s.\n",
					path, str_oserr(err));
			RegCloseKey(key);
			return (security_changed ? -2: -1);
		}
		security_changed = TRUE;
		RegCloseKey(key);
		if(p != 0) {
			*p++ = '\\';
			p = strchr(p, '\\');
		}
	} while( !finished );

	if(set_userkeys_security( start, path, &sd, &key) != 0)
		return -2;
	if(return_key == 0)
		RegCloseKey(key);
	else
		*return_key = key;
	return 0;
}

/* 
 * Function to get a little-endian int from an offset into
 * a byte array.
 */

int get_int( char *array )
{
	return ((array[0]&0xff) + ((array[1]<<8)&0xff00) +

⌨️ 快捷键说明

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