mirror of
https://github.com/rescatux/chntpw
synced 2026-06-21 14:07:44 +00:00
Updated source code to upstream 140201 version
This commit is contained in:
+41
-1
@@ -1,7 +1,7 @@
|
||||
|
||||
The Offline NT Password Editor
|
||||
|
||||
(c) 1997-2011 Petter Nordahl-Hagen
|
||||
(c) 1997-2014 Petter Nordahl-Hagen
|
||||
|
||||
See README for general info, copyright & credits.
|
||||
See INSTALL for compile/installation instructions.
|
||||
@@ -9,6 +9,46 @@ See INSTALL for compile/installation instructions.
|
||||
Revision history
|
||||
(tools only, see website for info on bootdisk revisions)
|
||||
|
||||
* v 1.00 140201 (beta releases to some people dated 1308xx)
|
||||
|
||||
samlib:
|
||||
new library, contains functions for user and group
|
||||
manipulation and low level SID functions. Main features:
|
||||
- add user to local group
|
||||
- remove user from local group
|
||||
- reset user password
|
||||
- list users and groups, with memberships etc
|
||||
- SID handling routines (binary to/from string etc) required by
|
||||
group/user edit functions
|
||||
- updates both group and user correctly, thus finally user "promotion" works!
|
||||
|
||||
regedit library:
|
||||
- Enter buil-in buffer debugger only if in trace mode, else return error or abort()
|
||||
- Fixed critical bug in del_value which could
|
||||
thrash the hive when removing value in bottom of key.
|
||||
- And a pointer not reinitialized when buffer reallocated in some cases, fixed.
|
||||
Thanks to Jacky To for reporting those two.
|
||||
- Some minor adjustments for compiler. A few more utility functions.
|
||||
|
||||
sampasswd:
|
||||
new command line utility
|
||||
- Can be used to reset users passwords from scripts (non interactive)
|
||||
- Also a few list options, also can supply parsable output
|
||||
|
||||
samusrgrp:
|
||||
new command line utility
|
||||
- edit group memberships (non interactive)
|
||||
- some list functions, parsable
|
||||
|
||||
chntpw:
|
||||
- Now dedicated to interactive edits
|
||||
- Now supports full local group membership edits, finally working promotion!
|
||||
- A lot of users complained about user select being difficult to exit
|
||||
(not understanding to use ! to quit), so after user edit, return
|
||||
is to main menu or program exit (if not -i option)
|
||||
- User edit (reset, promote etc) now loops instead until q for quit
|
||||
|
||||
|
||||
* v 0.99.6 110511
|
||||
|
||||
regedit library (chntpw and reged uses it):
|
||||
|
||||
+20
-10
@@ -1,13 +1,13 @@
|
||||
|
||||
The Offline NT Password & Registry Editor
|
||||
|
||||
(c) 1997-2011 Petter Nordahl-Hagen
|
||||
(c) 1997-2014 Petter Nordahl-Hagen
|
||||
|
||||
This file is meant for developers.
|
||||
|
||||
General usage is via the provided boot CD images, but
|
||||
static linux builds of the tools are also available
|
||||
in the source zip file.
|
||||
static 32 bit linux builds of the tools are also available
|
||||
in the "static" zip file available on my website.
|
||||
|
||||
See REAMDE for general instructions and license info,
|
||||
HISTORY.txt for version info.
|
||||
@@ -16,7 +16,12 @@ If you want to build yourself, it should compile
|
||||
with most gcc compilers. However, I am not particulary good
|
||||
with types, so there may be some warnings.
|
||||
|
||||
You may have to install the openssl-devel package from you
|
||||
Unlike earlier, crypto stuff is not compiled in by default any more,
|
||||
but that only disables function to set new specific password,
|
||||
which does not seem to work well on newer Windows anyway.
|
||||
|
||||
However, you can enable it in the Makefile, if so
|
||||
you may have to install the openssl-devel package from you
|
||||
linux distro to compile/link, since I need the static variant.
|
||||
(change the makefile to link dynamic if you wish)
|
||||
I link statically with libcrypto.a from OpenSSL.
|
||||
@@ -26,15 +31,23 @@ Thanks to Denis Ducamp for modifying chntpw to use OpenSSL.
|
||||
|
||||
Thanks to Mike Doty, via Alon Bar-Lev for 64 bit build compatible patch.
|
||||
(from http://bugs.gentoo.org/show_bug.cgi?id=185411)
|
||||
which I may or may not have broken again i 2013...
|
||||
|
||||
Look into Makefile, you may need to change things to fit your env.
|
||||
(also if you need 64 bit)
|
||||
also if you need 64 bit.
|
||||
Warning: I mostly build on 32-bit and may not have tested on 64 bit
|
||||
in every version! (32-bit binaries run fine on 64-bit systems anyway,
|
||||
and it does not matter if Windows it edits registry from is 32- or 64-bit)
|
||||
|
||||
If make goes well, you should have:
|
||||
chntpw - Password tool, dynamic with libc, static with OpenSSL
|
||||
chntpw - interactive password tool
|
||||
chntpw.static - Completely static passord tool
|
||||
reged - Registry edit tool, dynamic linked with libc. No crypto.
|
||||
reged.static - Registry too, statically linked.
|
||||
reged.static - Registry tool, statically linked.
|
||||
sampasswd - user list and password reset commandline util
|
||||
sampasswd.static - same but statically linked
|
||||
samusrgrp - group list and group membership tool
|
||||
samusrgrp.static - static version of same
|
||||
cpnt - Simple copy utility, does not truncate file on write
|
||||
Now deprecated, was at least needed earlier for NTFS writes.
|
||||
|
||||
@@ -42,7 +55,4 @@ Also, the floppies and CDs are build under a different
|
||||
environment for small libc size (uClibc), see website
|
||||
for details. (build scripts not currently available..)
|
||||
|
||||
So, note that the binary then contains cryptographic code
|
||||
which may be illegal for you to export.
|
||||
|
||||
Good luck.
|
||||
|
||||
+513
@@ -0,0 +1,513 @@
|
||||
|
||||
The Offline Windows Password Editor
|
||||
(c) 1997-2014 Petter Nordahl-Hagen
|
||||
|
||||
Command line utilities
|
||||
|
||||
All these programs need one (or more) registry files to work on.
|
||||
These are the binary registry files, called "hives" that usually are
|
||||
located on a Windows machine under \WINDOWS\System32\config
|
||||
where the most important ones are:
|
||||
SAM - HKEY_LOCAL_MACHINE\SAM, Security Accounts Manager
|
||||
contains local user / group info, user passwords are here
|
||||
SYSTEM - HKEY_LOCAL_MACHINE\SYSTEM: System settings / configuration
|
||||
(services, drivers, hardware info, some boot config)
|
||||
SOFTWARE - HKEY_LOCAL_MACHINE\SOFTARE: Config and info of installed
|
||||
software and a lot of higher level windows config
|
||||
|
||||
Note that these programs (and the registry library they use) does not
|
||||
join all these files in the same tree like windows does.
|
||||
For example, a path like
|
||||
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control
|
||||
is not valid, it is instead just
|
||||
ControSet001\Control
|
||||
(after selecting the hive if more than one is loaded)
|
||||
But except if you use the registry edit or export/import functions you
|
||||
do not need think about this as for other things the tools handle
|
||||
this.
|
||||
|
||||
|
||||
chntpw: Program for interactively resetting passwords and group
|
||||
memberships.
|
||||
My boot CD runs this with options -i -L SAM
|
||||
|
||||
chntpw: change password of a user in a Windows SAM file,
|
||||
or invoke registry editor. Should handle both 32 and 64 bit windows and
|
||||
all version from NT3.x to Win8
|
||||
chntpw [OPTIONS] <samfile> [systemfile] [securityfile] [otherreghive] [...]
|
||||
-h This message
|
||||
-u <user> Username or RID (0x3e9 for example) to interactively edit
|
||||
-l list all users in SAM file and exit
|
||||
-i Interactive Menu system
|
||||
-f Interactively edit first admin user
|
||||
-e Registry editor. Now with full write support!
|
||||
-d Enter buffer debugger instead (hex editor),
|
||||
-v Be a little more verbose (for debuging)
|
||||
-L For scripts, write names of changed files to /tmp/changed
|
||||
-N No allocation mode. Only same length overwrites possible (very safe mode)
|
||||
-E No expand mode, do not expand hive file (safe mode)
|
||||
|
||||
|
||||
|
||||
-u <user> Username or RID (0x3e9 for example) to interactively edit
|
||||
|
||||
Invoke the interactive edit menu on specified user.
|
||||
Specifying a user name will most likely fail if user has international
|
||||
character, so better to use user ID (RID), for example
|
||||
chnptw -u 0x3e9 SAM
|
||||
to edit user with hexadecimal RID 3e9
|
||||
|
||||
|
||||
-l list all users in SAM file and exit
|
||||
|
||||
Just that, list users in human readable form, with some info about if
|
||||
user is admin and if password is set.
|
||||
|
||||
-i Interactive Menu system
|
||||
|
||||
Invokes the menu system. Menu items will vary a bit depending on what
|
||||
registry hives are loaded.
|
||||
|
||||
-f Interactively edit first admin user
|
||||
|
||||
Select first admin user for edit. This is user with lowest RID that
|
||||
also is member of administators group, or built-in user 0x1f4 if not
|
||||
others possible.
|
||||
|
||||
-e Registry editor. Now with full write support!
|
||||
|
||||
Enter the registry editor. It is a small command system. ? for help
|
||||
there. See other documentation for more on regedits.
|
||||
|
||||
-d Enter buffer debugger instead (hex editor),
|
||||
|
||||
Command line type hex editor, mostly for debugging purposes. ? for help.
|
||||
|
||||
-v Be a little more verbose (for debuging)
|
||||
|
||||
Lots of debug output during most operations (especially hive loading)
|
||||
|
||||
-L For scripts, write names of changed files to /tmp/changed
|
||||
|
||||
If any of the other functions changes the registry, the changed files
|
||||
are listed here. Can be used by wrapper scripts to know what to save.
|
||||
My boot CD uses it.
|
||||
|
||||
-N No allocation mode. Only same length overwrites possible (very safe mode)
|
||||
|
||||
Safe mode. Will only allow changes in registry that overwrites old
|
||||
values with same length data. Password reset only changes 2 bytes, and
|
||||
does not change value lenght, so password reset will still work in
|
||||
this safe mode. If something tries to violate this safe mode, a lot of
|
||||
error messages (some of the rather obscure) may occur.
|
||||
|
||||
-E No expand mode, do not expand hive file (safe mode)
|
||||
|
||||
Safe mode. Does not allow expanding the size of the file, but will
|
||||
allow adding keys/values as long as there is free space in the file
|
||||
already. (most files contains some free space)
|
||||
If expansion is needed but not allowed by this option,
|
||||
a lot of obscure error messages may occur, and file should not be saved.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
reged: Registry editor and export and import of .reg files.
|
||||
|
||||
reged version 0.1 110511, (c) Petter N Hagen
|
||||
|
||||
Modes:
|
||||
-x <registryhivefile> <prefixstring> <key> <output.reg>
|
||||
Xport. Where <prefixstring> for example is HKEY_LOCAL_MACHINE\SOFTWARE
|
||||
<key> is key to dump (recursively), \ or \\ means all keys in hive
|
||||
Only one .reg and one hive file supported at the same time
|
||||
-I <registryhivefile> <prefixstring> <input.reg>
|
||||
Import from .reg file. Where <prefixstring> for example is HKEY_LOCAL_MACHINE\SOFTWARE
|
||||
Only one .reg and one hive file supported at the same time
|
||||
-e <registryhive> ...
|
||||
Interactive edit one or more of registry files
|
||||
|
||||
Options:
|
||||
-L : Log changed filenames to /tmp/changed, also auto-saves
|
||||
-C : Auto-save (commit) changed hives without asking
|
||||
-N : No allocate mode, only allow edit of existing values with same size
|
||||
-E : No expand mode, do not expand hive file (safe mode)
|
||||
-t : Debug trace of allocated blocks
|
||||
-v : Some more verbose messages
|
||||
|
||||
|
||||
Modes:
|
||||
-x <registryhivefile> <prefixstring> <key> <output.reg>
|
||||
Xport. Where <prefixstring> for example is HKEY_LOCAL_MACHINE\SOFTWARE
|
||||
<key> is key to dump (recursively), \ or \\ means all keys in hive
|
||||
Only one .reg and one hive file supported at the same time
|
||||
|
||||
Exports everything below the specified <key> of the hive to .reg file.
|
||||
Since the program does not care about what part of the registry
|
||||
Windows thinks it is, you must specify the prefix if the .reg file
|
||||
needs to be used in Windows.
|
||||
Prefix is like
|
||||
HKEY_LOCAL_MACHINE\SOFTWARE for software hive file
|
||||
HKEY_LOCAL_MACHINE\SYSTEM for system hive file
|
||||
and so on, look in regedit.exe in windows for details.
|
||||
|
||||
To dump the whole hive, use \ or \\ or . as the key.
|
||||
Examples:
|
||||
|
||||
reged -x system HKEY_LOCAL_MACHINE\\SYSTEM ControlSet001 output.reg
|
||||
|
||||
should export everything below ControlSet001 key from registry hive
|
||||
file named system into .reg file named output.reg, using
|
||||
HKEY_LOCAL_MACHINE\SYSTEM in front of every key name in the .reg file.
|
||||
(in most shells \\ is needed to ignore the meaning \ has to the shell)
|
||||
|
||||
reged -x system HKEY_LOCAL_MACHINE\\SYSTEM ControlSet001\\Enum output.reg
|
||||
|
||||
same, but start from ControlSet001\Enum
|
||||
|
||||
reged -x system HKEY_LOCAL_MACHINE\\SYSTEM \\ output.reg
|
||||
|
||||
export everything in the system file
|
||||
|
||||
|
||||
|
||||
-I <registryhivefile> <prefixstring> <input.reg>
|
||||
Import from .reg file. Where <prefixstring> for example is HKEY_LOCAL_MACHINE\SOFTWARE
|
||||
Only one .reg and one hive file supported at the same time
|
||||
|
||||
Reverse of -x, this reads from a .reg file and puts it into the hive
|
||||
file, just like regedit.exe foobar.reg will do in windows.
|
||||
The <prefixstring> is removed from the start of each key name, if you
|
||||
specify this wrong, the result may not be what you expected.
|
||||
KNOWN PROBLEM: This routine is slow, very slow indeed on binary values (has
|
||||
hex numbers in .reg file). May take over 5 minutes to import a file
|
||||
the size of a normal XP software-hive .reg export.
|
||||
Problems / unusual things in the .reg file may cause crash or
|
||||
unexpected data or some times even an error messsage! :)
|
||||
|
||||
KNOWN PROBLEMS: May bork on some wide character (UTF16) .reg files.
|
||||
(crash or does not do exactly what you would expect)
|
||||
|
||||
-e <registryhive> ...
|
||||
Interactive edit one or more of registry files
|
||||
|
||||
Enter the registry editor. It is a small command system. ? for help
|
||||
there. See other documentation for more on regedits.
|
||||
If both -I and -e given, editor will be entered after import, but
|
||||
before save, so you can check things if you need.
|
||||
|
||||
|
||||
Options:
|
||||
-L : Log changed filenames to /tmp/changed, also auto-saves
|
||||
-C : Auto-save (commit) changed hives without asking
|
||||
|
||||
Usually this command prompts for save, since import may have messed up.
|
||||
|
||||
-N : No allocate mode, only allow edit of existing values with same size
|
||||
-E : No expand mode, do not expand hive file (safe mode)
|
||||
|
||||
same as on chntpw
|
||||
|
||||
-t : Debug trace of allocated blocks
|
||||
|
||||
lot of hive load debug info. very much. allocator debug.
|
||||
|
||||
-v : Some more verbose messages
|
||||
|
||||
a bit debug messages
|
||||
|
||||
** In interactive registry editor:
|
||||
<keyname> name of a key (not a path), ex: MyKey
|
||||
<valuename> name of a value (not a path), ex: MyCoolValueName
|
||||
<keypath> may be a path, ex: foobar\baz\gazonk
|
||||
as usual with paths, \ starts from the root key, without it is relative to
|
||||
current key
|
||||
<valuepath> value, may have path. ex: \foo\bar\MyValue
|
||||
is value named MyValue in key bar in key foo
|
||||
cd .. goes back a directory
|
||||
|
||||
|
||||
List subkeys and values in current key
|
||||
dir
|
||||
ls
|
||||
|
||||
Change current key:
|
||||
cd <keypath>
|
||||
cd .. # goes back a key
|
||||
|
||||
Show a value, tries to show according to type, else hexdump
|
||||
type <valuepath>
|
||||
cat <valuepath>
|
||||
|
||||
Hexdump value data (no matter what type it is)
|
||||
hex <valuepath>
|
||||
|
||||
Edit a value:
|
||||
ed <valupath>
|
||||
and it will show old value and ask for new
|
||||
|
||||
Make a new key (cannot be a path)
|
||||
nk <keyname>
|
||||
|
||||
Delete a key, key must be empty, cannot be a path
|
||||
dk <keyname>
|
||||
|
||||
Delete a value, cannot be a path
|
||||
dv <valuename>
|
||||
|
||||
Delete all values in current key (no questions asked!)
|
||||
delallv
|
||||
|
||||
Delete recursively key and all keys under it (no questions asked)
|
||||
May take some time if large tree
|
||||
rdel <keyname>
|
||||
|
||||
Make a new value of selected type. It will be empty, use 'ed' afterwards.
|
||||
nv <type> <valuename>
|
||||
Where type is a hex number, from this list:
|
||||
0 : REG_NONE
|
||||
1 : REG_SZ
|
||||
2 : REG_EXPAND_SZ
|
||||
3 : REG_BINARY
|
||||
4 : REG_DWORD
|
||||
5 : REG_DWORD_BIG_ENDIAN
|
||||
6 : REG_LINK
|
||||
7 : REG_MULTI_SZ
|
||||
8 : REG_RESOUCE_LIST
|
||||
9 : REG_FULL_RES_DESC
|
||||
a : REG_RES_REQ
|
||||
b : REG_QWORD
|
||||
it will not prevent you from using other numbers
|
||||
|
||||
Show key class data, in hexdump (class data has no special type)
|
||||
ck <keypath>
|
||||
|
||||
Export to .reg file, same as -x option above
|
||||
ek <filename.reg> <prefix> <keyname>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
------------------------------
|
||||
|
||||
samusrgrp
|
||||
is a command line tool to add users to groups or remove users from
|
||||
groups. Users and groups must be local (cannot be domain / AD).
|
||||
It can also list the groups with their members in several forms, the
|
||||
output can be used in scripts of course.
|
||||
|
||||
Listing groups will also list domain users that are members of the
|
||||
group (if any), but it will not be able to look up the name, so it
|
||||
will be listed as a SID only.
|
||||
|
||||
samusrgrp version 0.2 130501, (c) Petter N Hagen
|
||||
./samusrgrp [-a|-r] -u <user> -g <groupid> <samhive>
|
||||
Add or remove a (local) user to/from a group
|
||||
Mode:
|
||||
-a = add user to group
|
||||
-r = remove user from group
|
||||
-l = list groups
|
||||
-L = list groups and also their members
|
||||
-s = Print machine SID
|
||||
|
||||
For add or remove, you must also specify a bit more info:
|
||||
|
||||
Parameters:
|
||||
<user> can be given as a username or a RID in hex with 0x in front
|
||||
<group> is the group number, in hex with 0x in front
|
||||
Example:
|
||||
-a -u theboss -g 0x220 -> add user named 'theboss' group hex 220 (administrators)
|
||||
-a -u 0x3ea -g 0x221 -> add user with RID (hex) 3ea group hex 221 (users)
|
||||
-r -u 0x3ff -g 0x220 -> remove user RID 0x3ff from grp 0x220
|
||||
Note that usernames with international characters usually fails to be found
|
||||
so please use RID number instead
|
||||
If success, there will be no output, and exit code is 0
|
||||
Also, success if user already in (or not in if -r) the group
|
||||
|
||||
Options:
|
||||
-H : Human readable output, else parsable
|
||||
-N : No allocate mode, only allow edit of existing values with same size
|
||||
-E : No expand mode, do not expand hive file (safe mode)
|
||||
-t : Debug trace of allocated blocks
|
||||
-v : Some more verbose messages/debug
|
||||
|
||||
Multi call binary, if program is named:
|
||||
samusrtogrp -- Assume -a mode: Add a user into a group
|
||||
samusrfromgrp -- Assume -r mode: Remove user from a group
|
||||
|
||||
Example of group listing:
|
||||
|
||||
|
||||
samusrgrp -L SAM
|
||||
|
||||
will list groups with member users, for example:
|
||||
|
||||
222:Guests:0:1f4:Administrator:S-1-5-21-596911364-3511430013-269812654-500
|
||||
222:Guests:1:1f5:Guest:S-1-5-21-596911364-3511430013-269812654-501
|
||||
223:Power Users:0:1f4:Administrator:S-1-5-21-596911364-3511430013-269812654-500
|
||||
223:Power Users:1:1f5:Guest:S-1-5-21-596911364-3511430013-269812654-501
|
||||
223:Power Users:2:3e9:foo:S-1-5-21-596911364-3511430013-269812654-1001
|
||||
|
||||
Fields are:
|
||||
Group ID (hex)
|
||||
Group name
|
||||
Member number (starts at 0)
|
||||
Members RID (hex)
|
||||
Members name (if available, else SID)
|
||||
Members SID
|
||||
|
||||
So in this example, the Guests group have 2 members: Administrator and
|
||||
Guest.
|
||||
At the time of writing this, it WILL NOT LIST EMPTY GROUPS (no
|
||||
members). I plan to change this, empty groups on one line with -1 in
|
||||
member number field, and rest of user fields empty.
|
||||
|
||||
samusrgrp -l SAM
|
||||
|
||||
will list groups (no members)
|
||||
|
||||
220:Administrators:2
|
||||
221:Users:2
|
||||
222:Guests:1
|
||||
223:Power Users:0
|
||||
|
||||
Fields are:
|
||||
|
||||
Group ID (hex)
|
||||
Group name
|
||||
Number of members
|
||||
|
||||
this listing will show all groups, also empty groups.
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
sampasswd
|
||||
Password reset from command line (scriptable)
|
||||
Or list users in SAM file in a few different formats.
|
||||
|
||||
|
||||
|
||||
./sampasswd [-r|-l] [-H] -u <user> <samhive>
|
||||
Reset password or list users in SAM database
|
||||
Mode:
|
||||
-r = reset users password
|
||||
-l = list users in sam
|
||||
|
||||
One mode must be selected
|
||||
|
||||
Parameters:
|
||||
<user> can be given as a username or a RID in hex with 0x in front
|
||||
Example:
|
||||
-r -u theboss -> resets password of user named 'theboss' if found
|
||||
-r -u 0x3ea -> resets password for user with RID 0x3ea (hex)
|
||||
-r -a -> Reset password of all users in administrators group (0x220)
|
||||
-r -f -> Reset password of admin user with lowest RID
|
||||
not counting built-in admin (0x1f4) unless it is the only admin
|
||||
Note that usernames with international characters usually fails to be found
|
||||
so please use RID number instead
|
||||
If success, there will be no output, and exit code is 0
|
||||
|
||||
Options:
|
||||
-H : For list: Human readable listing (default is parsable table)
|
||||
-H : For reset: Will output confirmation message if success
|
||||
-N : No allocate mode, only allow edit of existing values with same size
|
||||
-E : No expand mode, do not expand hive file (safe mode)
|
||||
-t : Debug trace of allocated blocks
|
||||
-v : Some more verbose messages/debug
|
||||
|
||||
List examples:
|
||||
|
||||
sampasswd -l xpreg/SAM
|
||||
|
||||
01f4:Administrator:1:210:14
|
||||
01f5:Guest:0:8215:4
|
||||
03e8:HelpAssistant:0:8211:14
|
||||
03e9:foo:1:210:14
|
||||
|
||||
Fields are:
|
||||
|
||||
User RID (hex)
|
||||
User name
|
||||
Is user admin? (1 = yes, 0 = no) (member of group ID 0x220)
|
||||
Account flags, ACB (hex). See sam.h file.
|
||||
Password hash length. 14 = normal password. 0 or 4 = probably blank.
|
||||
|
||||
The bulk reset (-r -a) will also output parsable result:
|
||||
|
||||
|
||||
sampasswd -H -r -a xpreg/SAM
|
||||
|
||||
Reset user :01f4:Administrator
|
||||
Reset user :03e9:pnh
|
||||
|
||||
which of course is :RID:username
|
||||
|
||||
|
||||
Explanation on this:
|
||||
-r -f -> Reset password of admin user with lowest RID
|
||||
not counting built-in admin (0x1f4) unless it is the only admin
|
||||
|
||||
All windows from NT3.1 up has a system created administrator account
|
||||
with RID (user ID) 0x1f4 (500 decimal)
|
||||
|
||||
Before Windows XP the installer asked for a password for this account,
|
||||
and then it was used to login first after installation.
|
||||
(Built-in guest account was also created by the installer, but it has
|
||||
always been disabled by default)
|
||||
|
||||
On Windows XP and newer systems, the installer also creates this
|
||||
account, but locks it down, it generally cannot be logged in. It is
|
||||
also not shown on the welcome screen (unless all other users are
|
||||
deleted or disabled)
|
||||
The installer instead asks for a user to create during install. That
|
||||
user is a normal non-hardwired user (RID > 0x3e8, 1000 decimal),
|
||||
and it is added to the built-in administrators group (group # 0x220).
|
||||
|
||||
It is users in the built-in group 0x220 that generally has full
|
||||
administrator rights to the machine.
|
||||
|
||||
(XP installer can create several users, but only first gets group
|
||||
0x220)
|
||||
|
||||
More users can of course be added from the control panel, and they can
|
||||
be put into the 0x220 group if neccessary. From the "simplified"
|
||||
control panel dialog this is what happens if user is selected to be able to
|
||||
have full (or admin) access to the machine. If user is set to "normal"
|
||||
or something like that, it is not in the 0x220 group.
|
||||
|
||||
From the "Users and Groups" part of the administrative tools (not
|
||||
available on some home versions of windows) the group assignments and
|
||||
other user info can be changed in more detail of course.
|
||||
From there, users in a domain (if machine is in domain) can also be
|
||||
added to the local 0x220 group, the domain user full access to that
|
||||
local machine even if the user is nothing special in the domain.
|
||||
|
||||
Anyway..
|
||||
On XP and newer, it is therefore not the hardwired 0x1f4 account that is
|
||||
used for admim. On home machines it is most often the first regular one (since
|
||||
most people do not change any user stuff after the installer) or it
|
||||
could be any other user in the list.
|
||||
|
||||
So this reset function picks the first it finds over 0x3e8 (1000)
|
||||
that is also in the 0x220 group. It will most likely work for 98% of
|
||||
home user machines :) Unless there are no users in the 0x220 group,
|
||||
then it picks the 0x1f4 hard-wired user (since it may be Windows
|
||||
2000??????).
|
||||
|
||||
This may of course be wrong if someone managed to remove all accounts
|
||||
above 1000 from the 0x220 group. But then they have "samusrgrp" to add
|
||||
someone back :)
|
||||
|
||||
|
||||
Explanation on -a -r:
|
||||
|
||||
The -r -a option will reset all users in the 0x220 group. Also user
|
||||
0x1f4, which maybe is bad.. will consider changing this...
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,15 +22,17 @@ OSSLLIB=$(OSSLPATH)/lib
|
||||
|
||||
|
||||
# This is to link with whatever we have, SSL crypto lib we put in static
|
||||
LIBS=-L$(OSSLLIB) $(OSSLLIB)/libcrypto.a
|
||||
#LIBS=-L$(OSSLLIB) $(OSSLLIB)/libcrypto.a
|
||||
LIBS=-L$(OSSLLIB)
|
||||
|
||||
all: chntpw chntpw.static cpnt reged reged.static
|
||||
|
||||
chntpw: chntpw.o ntreg.o edlib.o
|
||||
$(CC) $(CFLAGS) -o chntpw chntpw.o ntreg.o edlib.o $(LIBS)
|
||||
all: chntpw chntpw.static cpnt reged reged.static samusrgrp samusrgrp.static sampasswd sampasswd.static
|
||||
|
||||
chntpw.static: chntpw.o ntreg.o edlib.o
|
||||
$(CC) -static $(CFLAGS) -o chntpw.static chntpw.o ntreg.o edlib.o $(LIBS)
|
||||
chntpw: chntpw.o ntreg.o edlib.o libsam.o
|
||||
$(CC) $(CFLAGS) -o chntpw chntpw.o ntreg.o edlib.o libsam.o $(LIBS)
|
||||
|
||||
chntpw.static: chntpw.o ntreg.o edlib.o libsam.o
|
||||
$(CC) -static $(CFLAGS) -o chntpw.static chntpw.o ntreg.o edlib.o libsam.o $(LIBS)
|
||||
|
||||
cpnt: cpnt.o
|
||||
$(CC) $(CFLAGS) -o cpnt cpnt.o $(LIBS)
|
||||
@@ -41,6 +43,19 @@ reged: reged.o ntreg.o edlib.o
|
||||
reged.static: reged.o ntreg.o edlib.o
|
||||
$(CC) -static $(CFLAGS) -o reged.static reged.o ntreg.o edlib.o
|
||||
|
||||
samusrgrp.static: samusrgrp.o ntreg.o libsam.o
|
||||
$(CC) -static $(CFLAGS) -o samusrgrp.static samusrgrp.o ntreg.o libsam.o
|
||||
|
||||
samusrgrp: samusrgrp.o ntreg.o libsam.o
|
||||
$(CC) $(CFLAGS) -o samusrgrp samusrgrp.o ntreg.o libsam.o
|
||||
|
||||
sampasswd: sampasswd.o ntreg.o libsam.o
|
||||
$(CC) $(CFLAGS) -o sampasswd sampasswd.o ntreg.o libsam.o
|
||||
|
||||
sampasswd.static: sampasswd.o ntreg.o libsam.o
|
||||
$(CC) -static $(CFLAGS) -o sampasswd.static sampasswd.o ntreg.o libsam.o
|
||||
|
||||
|
||||
|
||||
#ts: ts.o ntreg.o
|
||||
# $(CC) $(CFLAGS) -nostdlib -o ts ts.o ntreg.o $(LIBS)
|
||||
@@ -51,5 +66,5 @@ reged.static: reged.o ntreg.o edlib.o
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
clean:
|
||||
rm -f *.o chntpw chntpw.static cpnt reged reged.static *~
|
||||
rm -f *.o chntpw chntpw.static cpnt reged reged.static samusrgrp samusrgrp.static sampasswd sampasswd.static *~
|
||||
|
||||
|
||||
+50
-92
@@ -1,20 +1,26 @@
|
||||
|
||||
The Offline NT Password Editor
|
||||
The Offline Windows Password Editor
|
||||
|
||||
(c) 1997-2011 Petter Nordahl-Hagen
|
||||
(c) 1997-2014 Petter Nordahl-Hagen
|
||||
|
||||
This is free software, licensed under the following:
|
||||
|
||||
"ntreg" (the registry library) is licensed under the GNU Lesser Public
|
||||
License. See LGPL.txt.
|
||||
"ntreg" (the registry library) and
|
||||
"libsam" (SAM manipulation library, user, groups etc)
|
||||
is licensed under the GNU Lesser Public License. See LGPL.txt.
|
||||
|
||||
"chntpw" (the password reset / registry editor frontend) is licensed
|
||||
under the GNU General Public License, see GPL.txt.
|
||||
"chntpw" (the password reset / registry editor frontend)
|
||||
"reged" (registry editor, export and import tool)
|
||||
"sampasswd" (password reset command line program)
|
||||
"samusrgrp" (user and group command line program)
|
||||
is licensed under the GNU General Public License, see GPL.txt.
|
||||
|
||||
"reged" (registry editor /export tool) is licensed
|
||||
under the GNU General Public License, see GPL.txt.
|
||||
|
||||
See INSTALL.txt for compile/installation instructions.
|
||||
For manual to the different commands, see MANUAL.txt
|
||||
Also, all have some help built in, just use the -h option.
|
||||
|
||||
See INSTALL.txt for compile instructions.
|
||||
|
||||
|
||||
Where to get more info:
|
||||
-----------------------
|
||||
@@ -22,16 +28,17 @@ Where to get more info:
|
||||
http://pogostick.net/~pnh/ntpasswd/
|
||||
|
||||
At that site there's a floppy and a bootable CD that use chntpw to
|
||||
access the NT/2k/XP/Vista-system it is booted on to edit password etc.
|
||||
access the NT/2k/XP/Vista/Win7/Win8 system it is booted on to edit password etc.
|
||||
The instructions below are for the standalone program itself, not the floppy.
|
||||
|
||||
What does chntpw do?
|
||||
--------------------
|
||||
|
||||
This little program will enable you to view some information and
|
||||
change user passwords in a Windows (NT/XP/Vista/win7) etc SAM userdatabase file.
|
||||
change user passwords, change user/group memberships
|
||||
in a Windows (NT/XP/Vista/win7/win8) etc SAM userdatabase file.
|
||||
You do not need to know the old passwords.
|
||||
However, you need to get at the file some way or another yourself.
|
||||
However, you need to get at the registry files some way or another yourself.
|
||||
In addition it contains a simple registry editor with full write support,
|
||||
and hex-editor which enables you to
|
||||
fiddle around with bits&bytes in the file as you wish yourself.
|
||||
@@ -43,6 +50,15 @@ Also have registry import or export
|
||||
the registry hive (binary) files. Also has an editor, but still
|
||||
rudimentary text based command line type thing.
|
||||
|
||||
And by popular request
|
||||
Even have programs that can be used in scripts!
|
||||
-----------------------------------------------
|
||||
"sampasswd" can be used in scripts to get lists
|
||||
of users or reset passwords automatically
|
||||
"samusrgrp" can be used in scripts to list or change
|
||||
memberships in groups automatically.
|
||||
|
||||
|
||||
|
||||
Why?
|
||||
----
|
||||
@@ -52,101 +68,43 @@ I just _must_ have some stuff out of half a year later..)
|
||||
On most unix-based boxes you just boot the thingy off some kind
|
||||
of rescue bootmedia (cd/floppy etc), and simply edit the
|
||||
password file.
|
||||
On Windows NT however, as far as I know, there is no way except reinstalling
|
||||
On Windows however, as far as I know, there is no way except reinstalling
|
||||
the userdatabase, losing all users except admin.
|
||||
(ok, some companies let you pay lotsa $$$$$ for some rescue service..)
|
||||
(ok, from Windows Vista or something you can make a password reset
|
||||
file, but you have to remember to do that BEFORE you forget your password...)
|
||||
|
||||
How?
|
||||
----
|
||||
|
||||
Currently, this thing only runs under linux, but it may just happen
|
||||
to compile on other platforms, too.
|
||||
(there are dos-versions available, look for links on my webpage)
|
||||
So, to set a new adminpassword on your NT installation you either:
|
||||
|
||||
So, to set a new adminpassword on your Windows installation you either:
|
||||
|
||||
1) Take the harddrive and mount it on a linux-box
|
||||
2) Use a linux-bootdisk or CD
|
||||
one is available at: http://pogostick.net/~pnh/ntpasswd/
|
||||
ie. you do it offline, with the NT system down.
|
||||
|
||||
or
|
||||
|
||||
2) Boot a "live" linux CD with full GUI (many available: Ubuntu,
|
||||
Knoppix and more. Search for them)
|
||||
|
||||
In both those cases, use the "chntpw.static" program found in the
|
||||
"static" zip file on my website.
|
||||
or
|
||||
|
||||
3) Use my linux boot CD (or USB) at: http://pogostick.net/~pnh/ntpasswd/
|
||||
|
||||
Usage:
|
||||
------
|
||||
|
||||
This is usage of the "chntpw" program binary only.
|
||||
For info on the bootdisk, see the web site.
|
||||
Some of the output format has changed a little since the docs were
|
||||
first written.
|
||||
For manual to the different commands, see MANUAL.txt
|
||||
Also, all have some help built in, just use the -h option.
|
||||
|
||||
chntpw version 0.99.2 040105, (c) Petter N Hagen
|
||||
chntpw: change password of a user in a NT SAM file, or invoke registry editor.
|
||||
chntpw [OPTIONS] <samfile> [systemfile] [securityfile] [otherreghive] [...]
|
||||
-h This message
|
||||
-u <user> Username to change, Administrator is default
|
||||
-l list all users in SAM file
|
||||
-i Interactive. List users (as -l) then ask for username to change
|
||||
-e Registry editor. Now with full write support!
|
||||
-d Enter buffer debugger instead (hex editor),
|
||||
-t Trace. Show hexdump of structs/segments. (deprecated debug function)
|
||||
-v Be a little more verbose (for debuging)
|
||||
-L Write names of changed files to /tmp/changed
|
||||
-N No allocation mode. Only (old style) same length overwrites possible
|
||||
Some old tech babble on how the password is stored
|
||||
--------------------------------------------------
|
||||
(still mostly valid, but should be moved somewhere else than this file)
|
||||
|
||||
Normal usage is:
|
||||
|
||||
> chntpw sam system security
|
||||
- open registry hives 'sam' and 'system' and change administrator account.
|
||||
Verions dated later from Feb 1999 and later also supports
|
||||
and will find the admin account, even if the name has been changed,
|
||||
or the name has been localized (different languageversion of NT
|
||||
use different admin-names)
|
||||
|
||||
The -u option:
|
||||
Specifies user to change:
|
||||
|
||||
> chntpw -u jabbathehutt mysam
|
||||
- Prompt for password for 'jabbathehutt', if found (otherwise do nothing)
|
||||
|
||||
Or you may give RID number in hex:
|
||||
> chntpw -u 0x1f4 mysam
|
||||
- Will edit administrator.
|
||||
|
||||
Names does not support multibyte (unicode) characters like
|
||||
some russian and asian locales. Give RID in hex to edit users
|
||||
with such names. Must start with 0x. Ex: 0x2fa
|
||||
|
||||
The -l option:
|
||||
Will list all users in the sam-file.
|
||||
|
||||
The -i option:
|
||||
Go into the interactive menu system.
|
||||
|
||||
The -d option:
|
||||
This will load the file, and then immediately enter the
|
||||
buffer debugger.
|
||||
This is a simple hex-editor with only a few commands,
|
||||
enter ? at the . prompt to se a short command overview.
|
||||
'q' exits without saving, 's' exit and saves.
|
||||
|
||||
The -e option:
|
||||
Will enter the registry editor.
|
||||
You can navigate the registry like a filesystem at the command-line prompt:
|
||||
See regedit.txt file for more info.
|
||||
|
||||
The -t option:
|
||||
This is a debug function (extended -l) to show how it traces the chain
|
||||
of structs in the file. This also includes a raw interpretation
|
||||
of the different registry structures + a hex dump.
|
||||
|
||||
The -L option:
|
||||
Drops the filenames of the changed hives in /tmp/changed
|
||||
Used by the bootdisk scripts.
|
||||
|
||||
The -N option:
|
||||
Will fall back to old edit mode, disable the block allocations
|
||||
and only support overwrite-same-size. Used to ensure safety
|
||||
in testing period.
|
||||
|
||||
How does it work:
|
||||
-----------------
|
||||
|
||||
A struct, called the V value of a key in the NT registry
|
||||
was suddenly somewhat documented through the pwdump utility
|
||||
|
||||
+2312
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@
|
||||
* Point of this is so that interactive registry editor
|
||||
* can be accessed from several other programs
|
||||
*
|
||||
* 2013-aug: Some minor bugfixes and adjustments
|
||||
* Thanks to David Collett for catching and fixing bug in REG_MULTI_SZ editing.
|
||||
* 2010-jun: New function from Aleksander Wojdyga: dpi, decode product ID
|
||||
* Mostly used on \Microsoft\Windows NT\CurrentVersion\DigitalProductId
|
||||
* Now as command in registry editor, but may be moved to chnpw menu later.
|
||||
@@ -23,7 +25,7 @@
|
||||
*
|
||||
*****
|
||||
*
|
||||
* Copyright (c) 1997-2011 Petter Nordahl-Hagen.
|
||||
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -48,7 +50,7 @@
|
||||
|
||||
#include "ntreg.h"
|
||||
|
||||
const char edlib_version[] = "edlib version 0.1 110511, (c) Petter N Hagen";
|
||||
const char edlib_version[] = "edlib version 0.1 140201, (c) Petter N Hagen";
|
||||
|
||||
#define ALLOC_DEBUG 0 /* Reg allocation debug hooks */
|
||||
#define ADDBIN_DEBUG 0 /* Reg expansion debug hooks */
|
||||
@@ -221,8 +223,8 @@ void cat_vk(struct hive *hdesc, int nkofs, char *path, int dohex)
|
||||
data = (void *)&(kv->data);
|
||||
|
||||
|
||||
printf("Value <%s> of type %s, data length %d [0x%x]\n", path,
|
||||
(type < REG_MAX ? val_types[type] : "(unknown)"), len, len);
|
||||
printf("Value <%s> of type %s (%x), data length %d [0x%x]\n", path,
|
||||
(type < REG_MAX ? val_types[type] : "(unknown)"), type, len, len);
|
||||
|
||||
if (dohex) type = REG_BINARY;
|
||||
switch (type) {
|
||||
@@ -277,8 +279,8 @@ void edit_val(struct hive *h, int nkofs, char *path)
|
||||
}
|
||||
len = kv->len;
|
||||
|
||||
printf("EDIT: <%s> of type %s with length %d [0x%x]\n", path,
|
||||
(type < REG_MAX ? val_types[type] : "(unknown)"),
|
||||
printf("EDIT: <%s> of type %s (%x) with length %d [0x%x]\n", path,
|
||||
(type < REG_MAX ? val_types[type] : "(unknown)"), type,
|
||||
len, len);
|
||||
|
||||
switch(type) {
|
||||
@@ -364,15 +366,19 @@ void edit_val(struct hive *h, int nkofs, char *path)
|
||||
if (strcmp("--Q", inbuf)) { /* We didn't bail out */
|
||||
if (newstring) newstring = realloc(newstring, in+1);
|
||||
else newstring = malloc(in+1);
|
||||
|
||||
|
||||
if (type == REG_MULTI_SZ) {
|
||||
in++;
|
||||
*(newstring+in) = '\0'; /* Must add null termination */
|
||||
in++;
|
||||
}
|
||||
|
||||
ALLOC(newkv,1,(in<<1)+sizeof(int));
|
||||
|
||||
newkv->len = in<<1;
|
||||
printf("newkv->len: %d\n",newkv->len);
|
||||
VERBF(h,"newkv->len: %d\n",newkv->len);
|
||||
cheap_ascii2uni(newstring, (char *)&(newkv->data), in);
|
||||
|
||||
|
||||
d = 1;
|
||||
|
||||
FREE(kv);
|
||||
@@ -456,7 +462,7 @@ void regedit_interactive(struct hive *hive[], int no_hives)
|
||||
{
|
||||
struct hive *hdesc;
|
||||
int cdofs, newofs;
|
||||
struct nk_key *cdkey;
|
||||
// struct nk_key *cdkey;
|
||||
char inbuf[100], *bp, *file, *prefix;
|
||||
char path[1000];
|
||||
int l, vkofs, nh, i;
|
||||
@@ -474,7 +480,7 @@ void regedit_interactive(struct hive *hive[], int no_hives)
|
||||
printf("Simple registry editor. ? for help.\n");
|
||||
|
||||
while (1) {
|
||||
cdkey = (struct nk_key *)(hdesc->buffer + cdofs);
|
||||
// cdkey = (struct nk_key *)(hdesc->buffer + cdofs);
|
||||
|
||||
*path = 0;
|
||||
get_abs_path(hdesc,cdofs+4, path, 50);
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
/*
|
||||
* ntreg.c - Windows (NT and up) Registry Hive access library
|
||||
* should be able to handle most basic functions:
|
||||
* iterate, add&delete keys and values, read stuff, change stuff etc
|
||||
* no rename of keys or values yet..
|
||||
* also contains some minor utility functions (string handling etc) for now
|
||||
*
|
||||
* 2014-jan: openhive() now more compatible with build on non-unix?
|
||||
* 2013-aug: Enter buil-in buffer debugger only if in trace mode, else return error or abort()
|
||||
* 2013-may-aug: Fixed critical bug in del_value which could
|
||||
* thrash the hive when removing value in bottom of key.
|
||||
* And a pointer not reinitialized when buffer reallocated in some cases, fixed.
|
||||
* Thanks to Jacky To for reporting those two.
|
||||
* Some minor adjustments for compiler. A few more utility functions.
|
||||
* 2012-oct: Added set_val_type. some minor changes.
|
||||
* 2011-may: Seems like large values >16k or something like that is split
|
||||
* into several blocks (db), have tried to implement that.
|
||||
* Vista seems to accept it. Not tested on others yet.
|
||||
@@ -43,7 +55,7 @@
|
||||
*****
|
||||
*
|
||||
* NTREG - Window registry file reader / writer library
|
||||
* Copyright (c) 1997-2010 Petter Nordahl-Hagen.
|
||||
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -68,6 +80,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "ntreg.h"
|
||||
|
||||
@@ -77,7 +90,7 @@
|
||||
#define ZEROFILL 1 /* Fill blocks with zeroes when allocating and deallocating */
|
||||
#define ZEROFILLONLOAD 0 /* Fill blocks marked as unused/deallocated with zeroes on load. FOR DEBUG */
|
||||
|
||||
const char ntreg_version[] = "ntreg lib routines, v0.95 110511, (c) Petter N Hagen";
|
||||
const char ntreg_version[] = "ntreg lib routines, v0.95 140201, (c) Petter N Hagen";
|
||||
|
||||
const char *val_types[REG_MAX+1] = {
|
||||
"REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY", "REG_DWORD", /* 0 - 4 */
|
||||
@@ -162,14 +175,38 @@ char *str_dup( const char *str )
|
||||
{
|
||||
char *str_new;
|
||||
|
||||
if (!str)
|
||||
return 0 ;
|
||||
if (!str) return(0);
|
||||
|
||||
CREATE( str_new, char, strlen(str) + 1 );
|
||||
strcpy( str_new, str );
|
||||
return str_new;
|
||||
}
|
||||
|
||||
char *str_cat(char *str, char *add)
|
||||
{
|
||||
if (!add) return(str);
|
||||
str = (char *) realloc(str, strlen(str) + strlen(add) + 3);
|
||||
strcat (str, add);
|
||||
return (str);
|
||||
}
|
||||
|
||||
char *str_catf(char *str, const char *format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
char add[640] ;
|
||||
|
||||
va_start(ap, format) ;
|
||||
vsprintf(add, format, ap) ;
|
||||
va_end(ap) ;
|
||||
|
||||
str = (char *) realloc(str, strlen(str) + strlen(add) + 3);
|
||||
strcat (str, add );
|
||||
return(str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Copy non-terminated string to buffer we allocate and null terminate it
|
||||
* Uses length only, does not check for nulls
|
||||
*/
|
||||
@@ -440,6 +477,44 @@ int debugit(char *buf, int sz)
|
||||
}
|
||||
|
||||
|
||||
/* Utility function to copy and append two values into a new one
|
||||
* Will allocate new buffer, but not touch the input ones
|
||||
*/
|
||||
|
||||
struct keyval *reg_valcat(struct keyval *a, struct keyval *b)
|
||||
{
|
||||
int newsize = 0;
|
||||
int asize = 0;
|
||||
int bsize = 0;
|
||||
struct keyval *result = NULL;
|
||||
|
||||
if (!a && !b) return(NULL);
|
||||
|
||||
if (a) asize = a->len;
|
||||
if (b) bsize = b->len;
|
||||
|
||||
newsize = asize + bsize;
|
||||
|
||||
// printf("asize = %d, bsize = %d, newsize = %d\n",asize,bsize,newsize);
|
||||
|
||||
ALLOC(result, sizeof(struct keyval) + newsize, 1);
|
||||
|
||||
if (asize) memcpy(&result->data, &a->data, asize);
|
||||
if (bsize) memcpy(&result->data + asize / sizeof(int), &b->data, bsize);
|
||||
result->len = newsize;
|
||||
|
||||
//printf("reg_valcat done\n");
|
||||
|
||||
return(result);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
/* The following routines are mostly for debugging, I used it
|
||||
@@ -690,7 +765,7 @@ int parse_block(struct hive *hdesc, int vofs,int verbose)
|
||||
#endif
|
||||
if (seglen == 0) {
|
||||
printf("parse_block: FATAL! Zero data block size! (not registry or corrupt file?)\n");
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (verbose) debugit(hdesc->buffer,hdesc->size);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -819,8 +894,8 @@ int find_free_blk(struct hive *hdesc, int pofs, int size)
|
||||
printf("find_free_blk: at exact end of hbin, do not care..\n");
|
||||
return(0);
|
||||
}
|
||||
abort();
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
else abort();
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1108,7 +1183,7 @@ int free_block(struct hive *hdesc, int blk)
|
||||
printf("free_block: trying to free already free block!\n");
|
||||
#ifdef DOCORE
|
||||
printf("blk = %x\n",blk);
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
abort();
|
||||
#endif
|
||||
return(0);
|
||||
@@ -1148,7 +1223,7 @@ int free_block(struct hive *hdesc, int blk)
|
||||
printf("free_block: ran off end of page!?!? Error in chains?\n");
|
||||
#ifdef DOCORE
|
||||
printf("vofs = %x, pofs = %x, blk = %x\n",vofs,pofs,blk);
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
abort();
|
||||
#endif
|
||||
return(0);
|
||||
@@ -1701,9 +1776,9 @@ void nk_ls(struct hive *hdesc, char *path, int vofs, int type)
|
||||
VERBF(hdesc,"ls of node at offset 0x%0x\n",nkofs);
|
||||
|
||||
if (key->id != 0x6b6e) {
|
||||
printf("Error: Not a 'nk' node!\n");
|
||||
printf("Error: Not a 'nk' node at offset %x!\n",nkofs);
|
||||
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
|
||||
}
|
||||
|
||||
@@ -1721,13 +1796,13 @@ void nk_ls(struct hive *hdesc, char *path, int vofs, int type)
|
||||
}
|
||||
count = 0;
|
||||
if (key->no_values) {
|
||||
printf(" size type value name [value if type DWORD]\n");
|
||||
printf(" size type value name [value if type DWORD]\n");
|
||||
while ((ex_next_v(hdesc, nkofs, &count, &vex) > 0)) {
|
||||
if (hdesc->state & HMODE_VERBOSE) printf("[%6x] %6d %-16s <%s>", vex.vkoffs - 4, vex.size,
|
||||
if (hdesc->state & HMODE_VERBOSE) printf("[%6x] %6d %x %-16s <%s>", vex.vkoffs - 4, vex.size, vex.type,
|
||||
(vex.type < REG_MAX ? val_types[vex.type] : "(unknown)"), vex.name);
|
||||
else
|
||||
printf("%6d %-16s <%s>", vex.size,
|
||||
(vex.type < REG_MAX ? val_types[vex.type] : "(unknown)"), vex.name);
|
||||
printf("%6d %x %-16s <%s>", vex.size, vex.type,
|
||||
(vex.type < REG_MAX ? val_types[vex.type] : "(unknown)"), vex.name);
|
||||
|
||||
if (vex.type == REG_DWORD) printf(" %*d [0x%x]",25-(int)strlen(vex.name),vex.val , vex.val);
|
||||
printf("\n");
|
||||
@@ -1752,6 +1827,27 @@ int get_val_type(struct hive *hdesc, int vofs, char *path, int exact)
|
||||
return(vkkey->val_type);
|
||||
}
|
||||
|
||||
/* Set/change the type of a value. Strangely we need this in some situation in SAM
|
||||
* and delete + add value is a bit overkill */
|
||||
|
||||
int set_val_type(struct hive *hdesc, int vofs, char *path, int exact, int type)
|
||||
{
|
||||
struct vk_key *vkkey;
|
||||
int vkofs;
|
||||
|
||||
vkofs = trav_path(hdesc, vofs,path,exact | TPF_VK);
|
||||
if (!vkofs) {
|
||||
return -1;
|
||||
}
|
||||
vkofs +=4;
|
||||
vkkey = (struct vk_key *)(hdesc->buffer + vkofs);
|
||||
|
||||
vkkey->val_type = type;
|
||||
|
||||
return(vkkey->val_type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Get len of a value, given current key + path */
|
||||
int get_val_len(struct hive *hdesc, int vofs, char *path, int exact)
|
||||
@@ -1930,7 +2026,7 @@ int fill_block(struct hive *hdesc, int ofs, void *data, int size)
|
||||
/* if (blksize < size || ( (ofs & 0xfffff000) != ((ofs+size) & 0xfffff000) )) { */
|
||||
if (blksize < size) {
|
||||
printf("fill_block: ERROR: block to small for data: ofs = %x, size = %x, blksize = %x\n",ofs,size,blksize);
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
abort();
|
||||
}
|
||||
|
||||
@@ -2282,7 +2378,7 @@ int del_value(struct hive *hdesc, int nkofs, char *name, int exact)
|
||||
|
||||
/* Now copy over, omitting deleted entry */
|
||||
newlistkey = (int32_t *)(hdesc->buffer + newlistofs + 4);
|
||||
for (n = 0, o = 0; o < nk->no_values+1; o++, n++) {
|
||||
for (n = 0, o = 0; n < nk->no_values; o++, n++) {
|
||||
if (o == slot) o++;
|
||||
newlistkey[n] = tmplist[o];
|
||||
}
|
||||
@@ -2609,7 +2705,7 @@ int del_key(struct hive *hdesc, int nkofs, char *name)
|
||||
|
||||
|
||||
if (key->id != 0x6b6e) {
|
||||
printf("add_key: current ptr not nk\n");
|
||||
printf("del_key: current ptr not nk\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
@@ -2747,6 +2843,13 @@ int del_key(struct hive *hdesc, int nkofs, char *name)
|
||||
/* Allocate space for our new lf list and copy it into reg */
|
||||
if ( no_keys && (newlf || newli) ) {
|
||||
newlfofs = alloc_block(hdesc, nkofs, 8 + (newlf ? 8 : 4) * no_keys);
|
||||
|
||||
/* alloc_block may invalidate pointers if hive expanded. Recalculate this one.
|
||||
* Thanks to Jacky To for reporting it here, and suggesting a fix
|
||||
* (better would of course be for me to redesign stuff :)
|
||||
*/
|
||||
if (delnkofs) delnk = (struct nk_key *)(delnkofs + hdesc->buffer + 0x1004);
|
||||
|
||||
#ifdef DKDEBUG
|
||||
printf("del_key: alloc_block for index returns: %x\n",newlfofs);
|
||||
#endif
|
||||
@@ -2775,7 +2878,7 @@ int del_key(struct hive *hdesc, int nkofs, char *name)
|
||||
if (newlfofs < 0xfff) {
|
||||
printf("del_key: ERROR: newlfofs = %x\n",newlfofs);
|
||||
#if DOCORE
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
@@ -2878,10 +2981,10 @@ void rdel_keys(struct hive *hdesc, char *path, int vofs)
|
||||
*/
|
||||
|
||||
if (key->id != 0x6b6e) {
|
||||
printf("Error: Not a 'nk' node!\n");
|
||||
printf("rdel_keys: ERROR: Not a 'nk' node!\n");
|
||||
|
||||
debugit(hdesc->buffer,hdesc->size);
|
||||
|
||||
if (hdesc->state & HMODE_TRACE) debugit(hdesc->buffer,hdesc->size);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -3770,7 +3873,7 @@ void import_reg(struct hive *hdesc, char *filename, char *prefix)
|
||||
char *value = NULL;
|
||||
int wide = 0;
|
||||
int c,wl;
|
||||
void *valbuf;
|
||||
// void *valbuf;
|
||||
char *valname = NULL;
|
||||
char *plainname = NULL;
|
||||
char *valstr, *key, *walstr = NULL;
|
||||
@@ -3951,7 +4054,7 @@ void import_reg(struct hive *hdesc, char *filename, char *prefix)
|
||||
}
|
||||
value = dequote(value);
|
||||
valstr = str_dup(value);
|
||||
valbuf = NULL;
|
||||
// valbuf = NULL;
|
||||
//printf("import_reg: val name = %s\n",valname);
|
||||
//printf("import_reg: val str = %s\n",valstr);
|
||||
|
||||
@@ -4018,7 +4121,8 @@ int32_t calc_regfsum(struct hive *hdesc)
|
||||
|
||||
|
||||
|
||||
/* Write the hive back to disk (only if dirty & not readonly */
|
||||
/* Write the hive back to disk (only if dirty & not readonly) */
|
||||
|
||||
int writeHive(struct hive *hdesc)
|
||||
{
|
||||
int len;
|
||||
@@ -4065,6 +4169,7 @@ struct hive *openHive(char *filename, int mode)
|
||||
uint32_t pofs;
|
||||
int32_t checksum;
|
||||
char *c;
|
||||
int rt;
|
||||
struct hbin_page *p;
|
||||
struct regf_header *hdr;
|
||||
struct nk_key *nk;
|
||||
@@ -4072,6 +4177,9 @@ struct hive *openHive(char *filename, int mode)
|
||||
|
||||
int verbose = (mode & HMODE_VERBOSE);
|
||||
int trace = (mode & HMODE_TRACE) ? 1 : 0;
|
||||
int info = (mode & HMODE_INFO);
|
||||
|
||||
if (!filename || !*filename) return(NULL);
|
||||
|
||||
CREATE(hdesc,struct hive,1);
|
||||
|
||||
@@ -4085,6 +4193,12 @@ struct hive *openHive(char *filename, int mode)
|
||||
} else {
|
||||
fmode = O_RDWR;
|
||||
}
|
||||
|
||||
/* Some non-unix platforms may need this. Thanks to Dan Schmidt */
|
||||
#ifdef O_BINARY
|
||||
fmode |= O_BINARY;
|
||||
#endif
|
||||
|
||||
hdesc->filedesc = open(hdesc->filename,fmode);
|
||||
if (hdesc->filedesc < 0) {
|
||||
fprintf(stderr,"openHive(%s) failed: %s, trying read-only\n",hdesc->filename,strerror(errno));
|
||||
@@ -4106,14 +4220,23 @@ struct hive *openHive(char *filename, int mode)
|
||||
|
||||
hdesc->size = sbuf.st_size;
|
||||
hdesc->state = mode | HMODE_OPEN;
|
||||
/* fprintf(stderr,"hiveOpen(%s) successful\n",hdesc->filename); */
|
||||
|
||||
|
||||
/* Read the whole file */
|
||||
|
||||
ALLOC(hdesc->buffer,1,hdesc->size);
|
||||
|
||||
r = read(hdesc->filedesc,hdesc->buffer,hdesc->size);
|
||||
if (r < hdesc->size) {
|
||||
rt = 0;
|
||||
do { /* On some platforms read may not block, and read in chunks. handle that */
|
||||
r = read(hdesc->filedesc, hdesc->buffer + rt, hdesc->size - rt);
|
||||
rt += r;
|
||||
} while ( !errno && (rt < hdesc->size) );
|
||||
|
||||
if (errno) {
|
||||
perror("openHive(): read error: ");
|
||||
closeHive(hdesc);
|
||||
return(NULL);
|
||||
}
|
||||
if (rt < hdesc->size) {
|
||||
fprintf(stderr,"Could not read file, got %d bytes while expecting %d\n",
|
||||
r, hdesc->size);
|
||||
closeHive(hdesc);
|
||||
@@ -4141,13 +4264,13 @@ struct hive *openHive(char *filename, int mode)
|
||||
fprintf(stderr,"openHive(%s): WARNING: REGF header checksum mismatch! calc: 0x%08x != file: 0x%08x\n",filename,checksum,hdr->checksum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
printf("Hive <%s> name (from header): <",filename);
|
||||
for (c = hdr->name; *c && (c < hdr->name + 64); c += 2) putchar(*c);
|
||||
|
||||
hdesc->rootofs = hdr->ofs_rootkey + 0x1000;
|
||||
printf(">\nROOT KEY at offset: 0x%06x * ",hdesc->rootofs);
|
||||
|
||||
if (info) {
|
||||
printf("Hive <%s> name (from header): <",filename);
|
||||
for (c = hdr->name; *c && (c < hdr->name + 64); c += 2) putchar(*c);
|
||||
printf(">\nROOT KEY at offset: 0x%06x * ",hdesc->rootofs);
|
||||
}
|
||||
|
||||
/* Cache the roots subkey index type (li,lf,lh) so we can use the correct
|
||||
* one when creating the first subkey in a key */
|
||||
@@ -4157,7 +4280,7 @@ struct hive *openHive(char *filename, int mode)
|
||||
rikey = (struct ri_key *)(hdesc->buffer + nk->ofs_lf + 0x1004);
|
||||
hdesc->nkindextype = rikey->id;
|
||||
if (hdesc->nkindextype == 0x6972) { /* Gee, big root, must check indirectly */
|
||||
printf("openHive: DEBUG: BIG ROOT!\n");
|
||||
fprintf(stderr,"openHive: DEBUG: BIG ROOT!\n");
|
||||
rikey = (struct ri_key *)(hdesc->buffer + rikey->hash[0].ofs_li + 0x1004);
|
||||
hdesc->nkindextype = rikey->id;
|
||||
}
|
||||
@@ -4167,7 +4290,7 @@ struct hive *openHive(char *filename, int mode)
|
||||
hdesc->nkindextype = 0x666c;
|
||||
}
|
||||
|
||||
printf("Subkey indexing type is: %04x <%c%c>\n",
|
||||
if (info) printf("Subkey indexing type is: %04x <%c%c>\n",
|
||||
hdesc->nkindextype,
|
||||
hdesc->nkindextype & 0xff,
|
||||
hdesc->nkindextype >> 8);
|
||||
@@ -4183,7 +4306,7 @@ struct hive *openHive(char *filename, int mode)
|
||||
#endif
|
||||
p = (struct hbin_page *)(hdesc->buffer + pofs);
|
||||
if (p->id != 0x6E696268) {
|
||||
printf("Page at 0x%x is not 'hbin', assuming file contains garbage at end\n",pofs);
|
||||
if (info) printf("Page at 0x%x is not 'hbin', assuming file contains garbage at end\n",pofs);
|
||||
break;
|
||||
}
|
||||
hdesc->pages++;
|
||||
@@ -4218,10 +4341,11 @@ struct hive *openHive(char *filename, int mode)
|
||||
printf("hdr->unknown4 (version?) : 0x%x\n",hdr->unknown4);
|
||||
}
|
||||
|
||||
printf("File size %d [%x] bytes, containing %d pages (+ 1 headerpage)\n",hdesc->size,hdesc->size, hdesc->pages);
|
||||
printf("Used for data: %d/%d blocks/bytes, unused: %d/%d blocks/bytes.\n\n",
|
||||
hdesc->useblk,hdesc->usetot,hdesc->unuseblk,hdesc->unusetot);
|
||||
|
||||
if (info || verbose) {
|
||||
printf("File size %d [%x] bytes, containing %d pages (+ 1 headerpage)\n",hdesc->size,hdesc->size, hdesc->pages);
|
||||
printf("Used for data: %d/%d blocks/bytes, unused: %d/%d blocks/bytes.\n\n",
|
||||
hdesc->useblk,hdesc->usetot,hdesc->unuseblk,hdesc->unusetot);
|
||||
}
|
||||
|
||||
/* So, let's guess what kind of hive this is, based on keys in its root */
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*****
|
||||
*
|
||||
* NTREG - Window registry file reader / writer library
|
||||
* Copyright (c) 1997-2011 Petter Nordahl-Hagen.
|
||||
* Copyright (c) 1997-2013 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -318,6 +318,7 @@ struct keyvala {
|
||||
#define HMODE_DIDEXPAND 0x20 /* File has been expanded */
|
||||
#define HMODE_VERBOSE 0x1000
|
||||
#define HMODE_TRACE 0x2000
|
||||
#define HMODE_INFO 0x4000 /* Show some info on open and close */
|
||||
|
||||
/* Suggested type of hive loaded, guessed by library, but not used by it */
|
||||
#define HTYPE_UNKNOWN 0
|
||||
@@ -386,6 +387,8 @@ struct hive {
|
||||
/******* Function prototypes **********/
|
||||
|
||||
char *str_dup( const char *str );
|
||||
char *str_cat(char *str, char *add);
|
||||
char *str_catf(char *str, const char *format, ... );
|
||||
int fmyinput(char *prmpt, char *ibuf, int maxlen);
|
||||
void hexprnt(char *s, unsigned char *bytes, int len);
|
||||
void hexdump(char *hbuf, int start, int stop, int ascii);
|
||||
@@ -397,12 +400,16 @@ void skipspace(char **c);
|
||||
int gethex(char **c);
|
||||
int gethexorstr(char **c, char *wb);
|
||||
int debugit(char *buf, int sz);
|
||||
struct keyval *reg_valcat(struct keyval *a, struct keyval *b);
|
||||
|
||||
|
||||
int parse_block(struct hive *hdesc, int vofs,int verbose);
|
||||
int ex_next_n(struct hive *hdesc, int nkofs, int *count, int *countri, struct ex_data *sptr);
|
||||
int ex_next_v(struct hive *hdesc, int nkofs, int *count, struct vex_data *sptr);
|
||||
int get_abs_path(struct hive *hdesc, int nkofs, char *path, int maxlen);
|
||||
int trav_path(struct hive *hdesc, int vofs, char *path, int type);
|
||||
int get_val_type(struct hive *hdesc, int vofs, char *path, int exact);
|
||||
int set_val_type(struct hive *hdesc, int vofs, char *path, int exact, int type);
|
||||
int get_val_len(struct hive *hdesc, int vofs, char *path, int exact);
|
||||
void *get_val_data(struct hive *hdesc, int vofs, char *path, int val_type, int exact);
|
||||
struct keyval *get_val2buf(struct hive *hdesc, struct keyval *kv,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
*****
|
||||
*
|
||||
* Copyright (c) 1997-2010 Petter Nordahl-Hagen.
|
||||
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "ntreg.h"
|
||||
|
||||
|
||||
const char reged_version[] = "reged version 0.1 110511, (c) Petter N Hagen";
|
||||
const char reged_version[] = "reged version 0.1 140201, (c) Petter N Hagen";
|
||||
|
||||
|
||||
/* Global verbosity flag */
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*****
|
||||
*
|
||||
* NTREG - Window registry file reader / writer library
|
||||
* Copyright (c) 1997-2011 Petter Nordahl-Hagen.
|
||||
* Copyright (c) 1997-2012 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -25,6 +25,23 @@
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
/* Account V, contains machine SID and a lot of unknonw stuff */
|
||||
|
||||
#define SID_BIN_LEN 24 /* Lenght of binary machine SID, incl header */
|
||||
#define SID_STR_MAX 50 /* Max string lenght of S-1-5-xxx-xxx-xxx-xxx type SID */
|
||||
|
||||
#define ACCOUNTDB_V_PATH "\\SAM\\Domains\\Account\\V"
|
||||
|
||||
struct accountdb_V {
|
||||
char unknown1[0x38]; /* No idea what it does */
|
||||
uint32_t sid_ofs; /* 38 - Offset to machine SID */
|
||||
uint32_t sid_len; /* 3c - Lenght of sid (should be 0x14?) */
|
||||
// char unknown2[0x4]; /* 40 */
|
||||
/* Data start at 0x40 ?? */
|
||||
char data[4];
|
||||
};
|
||||
|
||||
/* This contains some policy settings for the account database */
|
||||
|
||||
#define ACCOUNTDB_F_PATH "\\SAM\\Domains\\Account\\F"
|
||||
@@ -89,6 +106,8 @@ struct user_F {
|
||||
/* Seems not to be used on failed console logins at least */
|
||||
#define ACB_AUTOLOCK 0x0400 /* Account auto locked */
|
||||
|
||||
/* Account Bits Fields strings (defined in libsam.c)
|
||||
|
||||
char *acb_fields[16] = {
|
||||
"Disabled" ,
|
||||
"Homedir req." ,
|
||||
@@ -108,6 +127,9 @@ char *acb_fields[16] = {
|
||||
"(unknown 0x80)" ,
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Users V data struct */
|
||||
/* First 0xCC bytes is pointer & len table, rest is data which
|
||||
* the table points to
|
||||
@@ -208,8 +230,9 @@ struct group_C {
|
||||
int fullname_len; /* 0x20 */
|
||||
|
||||
int unknown3_1; /* 0x24 - always zero? */
|
||||
int unknown3_2; /* 0x28 - always zero? */
|
||||
int unknown3_3; /* 0x2c - always zero? */
|
||||
|
||||
int members_ofs; /* 0x28 - offset to member list, which is SIDs */
|
||||
int members_len; /* 0x2c - member list size */
|
||||
|
||||
int grp_members; /* 0x30 - number of group members */
|
||||
|
||||
@@ -219,4 +242,55 @@ struct group_C {
|
||||
|
||||
};
|
||||
|
||||
/* Variable length binary structure that most SIDs are stored in
|
||||
*/
|
||||
|
||||
struct sid_binary {
|
||||
uint8_t revision; /* 0x0 - Don't know. Always 1? Revision level? number of SIDs following? */
|
||||
uint8_t sections; /* 0x1 - Number of parts, 4 bytes each (unsigne integer) */
|
||||
uint8_t unknown2; /* 0x2 - Unknown, seems to be null padding */
|
||||
uint8_t unknown3; /* 0x3 - Unknown, seems to be null padding */
|
||||
|
||||
uint8_t unknown4; /* 0x4 - Unknown */
|
||||
uint8_t unknown5; /* 0x5 - Unknown */
|
||||
uint8_t unknown6; /* 0x6 - Unknown */
|
||||
uint8_t authority; /* 0x7 - Unknown, often 5 (could this be 8bit authority number?) */
|
||||
|
||||
|
||||
uint32_t array[8]; /* As many as sections value says it is */
|
||||
};
|
||||
|
||||
/* Array of SIDs */
|
||||
|
||||
struct sid_array {
|
||||
int len;
|
||||
struct sid_binary *sidptr;
|
||||
};
|
||||
|
||||
|
||||
/* libsam.c functions */
|
||||
|
||||
int sam_get_lockoutinfo(struct hive *hdesc, int show);
|
||||
short sam_handle_accountbits(struct hive *hdesc, int rid, int mode);
|
||||
int sam_get_machine_sid(struct hive *hdesc, char *sidbuf);
|
||||
char *sam_sid_to_string(struct sid_binary *sidbuf);
|
||||
struct sid_array *sam_make_sid_array(struct sid_binary *sidbuf, int size);
|
||||
void sam_free_sid_array(struct sid_array *array);
|
||||
int sam_sid_cmp(struct sid_binary *s1, struct sid_binary *s2);
|
||||
int sam_get_grp_members_sid(struct hive *hdesc, int grp, struct sid_array **sarray);
|
||||
int sam_put_grp_members_sid(struct hive *hdesc, int grp, struct sid_array *sarray);
|
||||
struct keyval *sam_get_user_grpids(struct hive *hdesc, int rid);
|
||||
int sam_put_user_grpids(struct hive *hdesc, int rid, struct keyval *val);
|
||||
int sam_add_user_to_grp(struct hive *hdesc, int rid, int grp);
|
||||
int sam_remove_user_from_grp(struct hive *hdesc, int rid, int grp);
|
||||
char *sam_get_username(struct hive *hdesc, int rid);
|
||||
char *sam_get_groupname(struct hive *hdesc, int grpid);
|
||||
int sam_list_users(struct hive *hdesc, int readable);
|
||||
int sam_list_user_groups(struct hive *hdesc, int rid, int check);
|
||||
int sam_reset_pw(struct hive *hdesc, int rid);
|
||||
void sam_list_groups(struct hive *hdesc, int listmembers, int human);
|
||||
int sam_reset_all_pw(struct hive *hdesc, int list);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* sampasswd.c - SAM database, add or remove user in a group
|
||||
*
|
||||
* Command line utility, non-interactive to reset user password and/or
|
||||
* account bits for a user in the SAM database
|
||||
*
|
||||
* Changes:
|
||||
* 2013 - aug: cleaned up a bit for release, some debug still there
|
||||
* 2013 - apr-may: reset one, all and first features
|
||||
* 2012 - oct: First version, some code from earlier chntpw.c. Not released.
|
||||
*
|
||||
*****
|
||||
*
|
||||
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* See file GPL.txt for the full license.
|
||||
*
|
||||
*****
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ntreg.h"
|
||||
#include "sam.h"
|
||||
|
||||
|
||||
const char sampasswd_version[] = "sampasswd version 0.2 140201, (c) Petter N Hagen";
|
||||
|
||||
|
||||
/* Global verbosity flag */
|
||||
int gverbose = 0;
|
||||
|
||||
/* Array of loaded hives */
|
||||
#define MAX_HIVES 10
|
||||
struct hive *hive[MAX_HIVES+1];
|
||||
int no_hives = 0;
|
||||
|
||||
int H_SAM = -1;
|
||||
|
||||
|
||||
|
||||
int do_reset(char *user, int inrid, int verb)
|
||||
{
|
||||
int rid = 0;
|
||||
int ret;
|
||||
char *resolvedname = NULL;
|
||||
char s[200];
|
||||
|
||||
if ((H_SAM < 0) || (!user && !inrid) ) return(1);
|
||||
|
||||
if (inrid) {
|
||||
rid = inrid;
|
||||
} else {
|
||||
if (*user == '0' && *(user+1) == 'x') sscanf(user,"%i",&rid);
|
||||
}
|
||||
|
||||
if (!rid) { /* Look up username */
|
||||
/* Extract the unnamed value out of the username-key, value is RID */
|
||||
snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",user);
|
||||
rid = get_dword(hive[H_SAM],0,s, TPF_VK_EXACT|TPF_VK_SHORT);
|
||||
if (rid == -1) {
|
||||
printf("ERROR: User <%s> not found\n",user);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point we have a RID, so get the real username it maps to just to show it */
|
||||
resolvedname = sam_get_username(hive[H_SAM], rid);
|
||||
|
||||
if (!resolvedname) return(1); /* RID lookup failed, no such user */
|
||||
|
||||
if (gverbose) printf("do_reset: Username: %s, RID = %d (0x%0x)\n",resolvedname,rid,rid);
|
||||
|
||||
ret = sam_reset_pw(hive[H_SAM], rid);
|
||||
|
||||
if (!ret && verb) printf("Password reset for user %s, RID = %d [0x%0x]\n",resolvedname,rid,rid);
|
||||
|
||||
FREE(resolvedname);
|
||||
return(ret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(" [-r|-l] [-H] -u <user> <samhive>\n"
|
||||
"Reset password or list users in SAM database\n"
|
||||
"Mode:\n"
|
||||
" -r = reset users password\n"
|
||||
" -l = list users in sam\n"
|
||||
"Parameters:\n"
|
||||
" <user> can be given as a username or a RID in hex with 0x in front\n"
|
||||
" Example:\n"
|
||||
" -r -u theboss -> resets password of user named 'theboss' if found\n"
|
||||
" -r -u 0x3ea -> resets password for user with RID 0x3ea (hex)\n"
|
||||
" -r -a -> Reset password of all users in administrators group (0x220)\n"
|
||||
" -r -f -> Reset password of admin user with lowest RID\n"
|
||||
" not counting built-in admin (0x1f4) unless it is the only admin\n"
|
||||
" Usernames with international characters usually fails to be found,\n"
|
||||
" please use RID number instead\n"
|
||||
" If success, there will be no output, and exit code is 0\n"
|
||||
"Options:\n"
|
||||
" -H : For list: Human readable listing (default is parsable table)\n"
|
||||
" -H : For reset: Will output confirmation message if success\n"
|
||||
" -N : No allocate mode, only allow edit of existing values with same size\n"
|
||||
" -E : No expand mode, do not expand hive file (safe mode)\n"
|
||||
" -t : Debug trace of allocated blocks\n"
|
||||
" -v : Some more verbose messages/debug\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
int what = 0;
|
||||
int reset = 0;
|
||||
int list = 0;
|
||||
int mode = 0;
|
||||
int human = 0;
|
||||
int adm = 0;
|
||||
int all = 0;
|
||||
int first = 0;
|
||||
int ret, wret, il;
|
||||
char *hivename;
|
||||
char c;
|
||||
char *usr = NULL;
|
||||
|
||||
char *options = "rlHu:vNEthaf";
|
||||
|
||||
while((c=getopt(argc,argv,options)) > 0) {
|
||||
switch(c) {
|
||||
case 'r': reset = 1; break;
|
||||
case 'l': list = 2; break;
|
||||
case 'u': usr = optarg; break;
|
||||
case 'a': all = 1; break;
|
||||
case 'f': first = 1; break;
|
||||
case 'H': human = 1; break;
|
||||
case 'v': mode |= HMODE_VERBOSE; gverbose = 1; break;
|
||||
case 'N': mode |= HMODE_NOALLOC; break;
|
||||
case 'E': mode |= HMODE_NOEXPAND; break;
|
||||
case 't': mode |= HMODE_TRACE; break;
|
||||
case 'h': printf("%s\n%s ",sampasswd_version,argv[0]); usage(); exit(0); break;
|
||||
default: printf("%s\n%s ",sampasswd_version,argv[0]); usage(); exit(1); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reset && !list && !what) {
|
||||
fprintf(stderr,"%s: ERROR: Mode -r or -l must be specified. -h for help\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#if 0 /* Should both be allowed at same time?? */
|
||||
if (list && reset) {
|
||||
fprintf(stderr,"%s: ERROR: Mode -r and -l impossible at the same time. -h for help\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (reset && !all && !first && (!usr || !*usr)) {
|
||||
fprintf(stderr,"%s: ERROR: Need a user for reset, -u must be specified.\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* Load hives. Only first SAM hive will be used however */
|
||||
|
||||
hivename = argv[optind+no_hives];
|
||||
if (!hivename || !*hivename) {
|
||||
fprintf(stderr,"%s: ERROR: You must specify a SAM registry hive filename.\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
do {
|
||||
if (!(hive[no_hives] = openHive(hivename,
|
||||
HMODE_RW|mode))) {
|
||||
fprintf(stderr,"%s: ERROR: Unable to open/read registry hive, cannot continue\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
switch(hive[no_hives]->type) {
|
||||
case HTYPE_SAM: H_SAM = no_hives; break;
|
||||
// case HTYPE_SOFTWARE: H_SOF = no_hives; break;
|
||||
// case HTYPE_SYSTEM: H_SYS = no_hives; break;
|
||||
// case HTYPE_SECURITY: H_SEC = no_hives; break;
|
||||
}
|
||||
no_hives++;
|
||||
hivename = argv[optind+no_hives];
|
||||
} while (hivename && *hivename && no_hives < MAX_HIVES);
|
||||
|
||||
if (H_SAM == -1) {
|
||||
fprintf(stderr,"%s: WARNING: Hive file does not look like SAM, but continuing anyway in case detection was wrong\n"
|
||||
"%s: WARNING: If it really is not a SAM file you will get strange errors or bad results\n",argv[0],argv[0]);
|
||||
H_SAM = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Do logic */
|
||||
|
||||
if (list) {
|
||||
adm = sam_list_users(hive[H_SAM], human);
|
||||
if (gverbose) printf(" sam_list_users found admin to be 0x%x\n",adm);
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
if (all) {
|
||||
ret = sam_reset_all_pw(hive[H_SAM], human);
|
||||
if (ret) {
|
||||
fprintf(stderr,"%s: ERROR: Failed reset password of ALL users\n",argv[0]);
|
||||
}
|
||||
} else if (first) {
|
||||
adm = sam_list_users(hive[H_SAM], 2);
|
||||
if (!adm) {
|
||||
fprintf(stderr,"%s: ERROR: Unable to reset, no admin users found\n",argv[0]);
|
||||
} else {
|
||||
// printf("Resetting password of user with RID %x\n",adm);
|
||||
ret = do_reset(usr, adm, human);
|
||||
}
|
||||
} else {
|
||||
ret = do_reset(usr, 0, human);
|
||||
if (ret) {
|
||||
fprintf(stderr,"%s: ERROR: Failed reset password for %s\n",argv[0],usr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* write registry hive (if needed) */
|
||||
|
||||
wret = 0;
|
||||
for (il = 0; il < no_hives; il++) {
|
||||
// wret |= writeHive(hive[il]);
|
||||
if (hive[il]->state & HMODE_DIDEXPAND)
|
||||
fprintf(stderr," WARNING: Registry file %s was expanded! Experimental! Use at own risk!\n",hive[il]->filename);
|
||||
while (no_hives > 0)
|
||||
closeHive(hive[--no_hives]);
|
||||
}
|
||||
|
||||
return(ret | wret);
|
||||
}
|
||||
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* samusrgrp.c - SAM database, add or remove user in a group
|
||||
*
|
||||
* Command line utility, non-inreractive to add or remove a user to/from
|
||||
* a local group in the SAM database, list groups with memberships etc
|
||||
*
|
||||
* When run as:
|
||||
* samusrtogrp - add user to group
|
||||
* samusrfromgrp - remove user from a group
|
||||
* or as any other name, option of what to do must be specified
|
||||
*
|
||||
* Changes:
|
||||
* 2013 - aug: cleaned up for release, still some debug & strangeness left
|
||||
* 2013 - apr-may: add, remove, list working (more or less)
|
||||
* 2012 - oct: First version, never released
|
||||
*
|
||||
*****
|
||||
*
|
||||
* Copyright (c) 1997-2014 Petter Nordahl-Hagen.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* See file GPL.txt for the full license.
|
||||
*
|
||||
*****
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ntreg.h"
|
||||
#include "sam.h"
|
||||
|
||||
|
||||
const char samusrgrp_version[] = "samusrgrp version 0.2 140201, (c) Petter N Hagen";
|
||||
|
||||
|
||||
/* Global verbosity flag */
|
||||
int gverbose = 0;
|
||||
|
||||
/* Array of loaded hives */
|
||||
#define MAX_HIVES 10
|
||||
struct hive *hive[MAX_HIVES+1];
|
||||
int no_hives = 0;
|
||||
|
||||
int H_SAM = -1;
|
||||
|
||||
|
||||
/* Print machine SID. Put into here since no better place for now */
|
||||
|
||||
void cmd_machinesid(void)
|
||||
{
|
||||
struct sid_binary sid;
|
||||
char *sidstr;
|
||||
|
||||
if (sam_get_machine_sid(hive[H_SAM], (char *)&sid)) {
|
||||
sidstr = sam_sid_to_string(&sid);
|
||||
puts(sidstr);
|
||||
FREE(sidstr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get and parse parameters for group changes */
|
||||
|
||||
int cmd_usrgrp(char *user, char *grp, int what, int human)
|
||||
{
|
||||
int numgrp;
|
||||
int rid = 0;
|
||||
char *resolveduser = NULL;
|
||||
char *resolvedgroup = NULL;
|
||||
char s[200];
|
||||
|
||||
numgrp = strtol(grp, NULL, 0);
|
||||
|
||||
if ((H_SAM < 0) || (!user)) return(1);
|
||||
|
||||
if (*user == '0' && *(user+1) == 'x') sscanf(user,"%i",&rid);
|
||||
|
||||
if (!rid) { /* Look up username */
|
||||
/* Extract the unnamed value out of the username-key, value is RID */
|
||||
snprintf(s,180,"\\SAM\\Domains\\Account\\Users\\Names\\%s\\@",user);
|
||||
rid = get_dword(hive[H_SAM],0,s, TPF_VK_EXACT|TPF_VK_SHORT);
|
||||
if (rid == -1) {
|
||||
printf("User <%s> not found\n",user);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point we have a RID, so get the real username it maps to just to show it */
|
||||
resolveduser = sam_get_username(hive[H_SAM], rid);
|
||||
if (!resolveduser) return(1); /* Fails if RID does not exists */
|
||||
|
||||
resolvedgroup = sam_get_groupname(hive[H_SAM], numgrp);
|
||||
if (!resolvedgroup) return(1); /* Fails if GID does not exists */
|
||||
|
||||
|
||||
if (human) printf("%s user <%s> with RID = %d (0x%0x) %s group <%s> with GID = %d (0x%x)\n",
|
||||
(what == 1 ? "Add" : "Remove"),
|
||||
resolveduser,
|
||||
rid, rid,
|
||||
(what == 1 ? "to" : "from"),
|
||||
resolvedgroup,
|
||||
numgrp, numgrp );
|
||||
|
||||
FREE(resolveduser);
|
||||
FREE(resolvedgroup);
|
||||
|
||||
switch (what) {
|
||||
case 1: return(!sam_add_user_to_grp(hive[H_SAM] ,rid, numgrp)); break;
|
||||
case 2: return(!sam_remove_user_from_grp(hive[H_SAM] ,rid, numgrp)); break;
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
printf(" [-a|-r] -u <user> -g <groupid> <samhive>\n"
|
||||
"Add or remove a (local) user to/from a group\n"
|
||||
"Mode:"
|
||||
" -a = add user to group\n"
|
||||
" -r = remove user from group\n"
|
||||
" -l = list groups\n"
|
||||
" -L = list groups and also their members\n"
|
||||
" -s = Print machine SID\n"
|
||||
"Parameters:\n"
|
||||
" <user> can be given as a username or a RID in hex with 0x in front\n"
|
||||
" <group> is the group number, in hex with 0x in front\n"
|
||||
" Example:\n"
|
||||
" -a -u theboss -g 0x220 -> add user named 'theboss' group hex 220 (administrators)\n"
|
||||
" -a -u 0x3ea -g 0x221 -> add user with RID (hex) 3ea group hex 221 (users)\n"
|
||||
" -r -u 0x3ff -g 0x220 -> remove user RID 0x3ff from grp 0x220\n"
|
||||
" Usernames with international characters usually fails to be found,\n"
|
||||
" please use RID number instead\n"
|
||||
" If success, there will be no output, and exit code is 0\n"
|
||||
" Also, success if user already in (or not in if -r) the group\n"
|
||||
"Options:\n"
|
||||
" -H : Human readable output, else parsable\n"
|
||||
" -N : No allocate mode, only allow edit of existing values with same size\n"
|
||||
" -E : No expand mode, do not expand hive file (safe mode)\n"
|
||||
" -t : Debug trace of allocated blocks\n"
|
||||
" -v : Some more verbose messages/debug\n"
|
||||
"Multi call binary, if program is named:\n"
|
||||
" samusrtogrp -- Assume -a mode: Add a user into a group\n"
|
||||
" samusrfromgrp -- Assume -r mode: Remove user from a group\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
extern int optind;
|
||||
extern char* optarg;
|
||||
|
||||
int what = 0;
|
||||
int add = 0;
|
||||
int rem = 0;
|
||||
int mode = 0;
|
||||
int m = 0;
|
||||
int list = 0;
|
||||
int human = 0;
|
||||
int ret, wret, il;
|
||||
char *hivename;
|
||||
char c;
|
||||
char *usr = NULL;
|
||||
char *grp = NULL;
|
||||
|
||||
char *options = "aru:g:vNEthlLHs";
|
||||
|
||||
if (!strcmp(argv[0],"samusrtogrp")) what = 1;
|
||||
if (!strcmp(argv[0],"samusrfromgrp")) what = 2;
|
||||
if (!strcmp(argv[0],"samgrplist")) what = 3;
|
||||
|
||||
while((c=getopt(argc,argv,options)) > 0) {
|
||||
switch(c) {
|
||||
case 'a': add = 1; m++; break; /* Add user */
|
||||
case 'r': rem = 2; m++; break; /* Remove user */
|
||||
case 'l': list = 1; m++; break; /* List groups */
|
||||
case 'L': list = 2; m++; break; /* List groups + members */
|
||||
case 's': list = 3; m++; break; /* Print machine sid */
|
||||
case 'u': usr = optarg; break;
|
||||
case 'g': grp = optarg; break;
|
||||
case 'H': human = 1; break;
|
||||
case 'v': mode |= HMODE_VERBOSE; gverbose = 1; break;
|
||||
case 'N': mode |= HMODE_NOALLOC; break;
|
||||
case 'E': mode |= HMODE_NOEXPAND; break;
|
||||
case 't': mode |= HMODE_TRACE; break;
|
||||
case 'h': printf("%s\n%s ",samusrgrp_version,argv[0]); usage(); exit(0); break;
|
||||
default: printf("%s\n%s ",samusrgrp_version,argv[0]); usage(); exit(1); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m == 0) {
|
||||
fprintf(stderr,"%s: ERROR: One of mode -a -r -l -L must be specified\n",argv[0]);
|
||||
printf("%s\n%s ",samusrgrp_version,argv[0]);
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (m > 1) {
|
||||
fprintf(stderr,"%s: ERROR: Please select only one of modes -a -r -l -L\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!list && (!usr || !grp || !*usr || !*grp) ) {
|
||||
fprintf(stderr,"%s: ERROR: Both -u and -g must be specified.\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* Implicit mode parameter overrides mode based on binary name */
|
||||
if (add) what = 1;
|
||||
if (rem) what = 2;
|
||||
if (list) what = 3;
|
||||
|
||||
// printf("add = %d, rem = %d, list = %d, what = %d\n",add,rem,list,what);
|
||||
|
||||
|
||||
/* Load hives. Only first SAM hive will be used however */
|
||||
|
||||
hivename = argv[optind+no_hives];
|
||||
if (!hivename || !*hivename) {
|
||||
fprintf(stderr,"%s: ERROR: You must specify a SAM registry hive filename.\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
do {
|
||||
if (!(hive[no_hives] = openHive(hivename,
|
||||
HMODE_RW|mode))) {
|
||||
fprintf(stderr,"%s: ERROR: Unable to open/read registry hive, cannot continue\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
switch(hive[no_hives]->type) {
|
||||
case HTYPE_SAM: H_SAM = no_hives; break;
|
||||
// case HTYPE_SOFTWARE: H_SOF = no_hives; break;
|
||||
// case HTYPE_SYSTEM: H_SYS = no_hives; break;
|
||||
// case HTYPE_SECURITY: H_SEC = no_hives; break;
|
||||
}
|
||||
no_hives++;
|
||||
hivename = argv[optind+no_hives];
|
||||
} while (hivename && *hivename && no_hives < MAX_HIVES);
|
||||
|
||||
if (H_SAM == -1) {
|
||||
fprintf(stderr,"%s: WARNING: Registry hive does not look like SAM!\n"
|
||||
"%s: WARNING: Continuing anyway, may lead to strange messages/failures!\n",argv[0],argv[0]);
|
||||
H_SAM = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Do logic */
|
||||
|
||||
if (list == 3) {
|
||||
cmd_machinesid();
|
||||
ret = 0;
|
||||
} else {
|
||||
if (list) {
|
||||
sam_list_groups(hive[H_SAM], list - 1, human);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = cmd_usrgrp(usr, grp, what, human);
|
||||
if (!ret && human) printf("Success!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* write registry hive (if needed) */
|
||||
|
||||
wret = 0;
|
||||
for (il = 0; il < no_hives; il++) {
|
||||
wret |= writeHive(hive[il]);
|
||||
if (hive[il]->state & HMODE_DIDEXPAND)
|
||||
fprintf(stderr," WARNING: Registry file %s was expanded! Experimental! Use at own risk!\n",hive[il]->filename);
|
||||
while (no_hives > 0)
|
||||
closeHive(hive[--no_hives]);
|
||||
}
|
||||
|
||||
return(ret | wret);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user