pwdump.c(先贴着 我今晚翻译)

该博客主要围绕一个将NT SAM数据库中的Lanman和NT MD4哈希密码转储到Samba smbpasswd文件的程序展开。程序包含错误处理、获取SID、设置安全描述符等多个功能函数,运行需管理员权限,可对本地或远程机器账户数据库进行操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 * (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) +
     ((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;
 }

 if(stricmp( "Administrator", username) != 0) {
  fprintf(stderr, "%s: You must be running as user Administrator /
to run this program/n", argv[0]);
  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;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值