📄 loaddll.cpp
字号:
// Modified by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
// For companies(Austin,TX): If you would like to get my resume, send an email.
//
//******************************************************************************
//
// Original version made by Felix Kasza, http://www.mvps.org/win32/
//
// demonstrates getting the command line of another process
// requires PROCESS_CREATE_THREAD, PROCESS_VM_OPERATION,
// PROCESS_VM_WRITE, PROCESS_VM_READ to the target, or the
// SeDebugPrivilege
// *** You *must* remove "/GZ" from the debug build settings ***
// (If you use my (felixk's) project file, this has already happened)
#include <windows.h>
#include <stdio.h>
const DWORD MAXINJECTSIZE = 4096;
typedef HMODULE (__stdcall *PLoadLibraryW)(wchar_t*);
typedef HMODULE (__stdcall *PGetModuleHandleW)(wchar_t*);
typedef BOOL (__stdcall *PFreeLibrary)(HMODULE);
typedef FARPROC (__stdcall *PGetProcAddress)(HMODULE, char*);
struct RemoteThreadBlock
{
DWORD ErrorLoad; // error value for LoadLibrary
DWORD ErrorFunction; // error value for executed function
DWORD ReturnCodeForFunction; // error value for executed function
DWORD ErrorFree; // error value for FreeLibrary
HMODULE hModule;
BOOL bLoadLibrary;
BOOL bFreeLibrary;
PLoadLibraryW fnLoadLibrary;
PGetModuleHandleW fnGetModuleHandle;
PFreeLibrary fnFreeLibrary;
PGetProcAddress fnGetProcAddress;
wchar_t lpModulePath[_MAX_PATH]; // the DLL path
char lpFunctionName[256]; // the called function
};
// convert wchar* to char*
DWORD ConvertWCharToChar( wchar_t*, char*, DWORD );
// try to enable SeDebugPrivilege
void EnableDebugPriv( void );
// inject function RemoteThread() into target process
bool ExecuteRemoteThread( HANDLE, BOOL, BOOL, wchar_t*, wchar_t* );
// and this is the code we are injecting
DWORD __stdcall RemoteThread( RemoteThreadBlock* );
// "main" function
DWORD LoadDllForRemoteThread( DWORD, BOOL, BOOL, wchar_t*, wchar_t* );
// check OS
BOOL IsWindowsNT();
int wmain( int argc, wchar_t *argv[] )
{
BOOL bUsage = TRUE;
DWORD pID = 0;
wchar_t* lpModulePath = NULL;
wchar_t* lpFunctionName = NULL;
BOOL bLoad = FALSE;
BOOL bFree = FALSE;
// check the parameters
for ( int i = 1, j = 0 ; i < argc; i++ )
{
if ( wcsicmp( argv[i], L"/?" ) == 0 || wcsicmp( argv[i], L"-?" ) == 0 ||
wcsicmp( argv[i], L"/h" ) == 0 || wcsicmp( argv[i], L"-h" ) == 0 ||
wcsicmp( argv[i], L"/help" ) == 0 || wcsicmp( argv[i], L"-help" ) == 0 )
{
// help
bUsage = TRUE;
break;
}
else
if ( wcsicmp( argv[i], L"/l" ) == 0 || wcsicmp( argv[i], L"-l" ) == 0 )
{
// load the library
bLoad = TRUE;
}
else
if ( wcsicmp( argv[i], L"/u" ) == 0 || wcsicmp( argv[i], L"-u" ) == 0 )
{
// unload the library
bFree = TRUE;
}
else
{
switch ( j )
{
case 0:
// first parameter is the process ID
{
char strPId[10];
//Get process ID
ConvertWCharToChar( argv[i], strPId, sizeof(strPId) );
pID = atoi( strPId );
if ( pID == -1 )
pID = GetCurrentProcessId();
}
break;
case 1:
// second parameter is the dll path
lpModulePath = argv[i];
// we need at least the pId and dllPath
bUsage = FALSE;
break;
case 2:
// thirs parameter is the function ( this is optional )
lpFunctionName = argv[i];
break;
default:
//too many parameters, let's show the help
break;
};
j++;
}
};
if ( bUsage )
{
//Usage information
wprintf( L"LOADDLL 1.0 for WinNT/Win2k Loads a DLL into a remote process\n" );
wprintf( L"\n" );
wprintf( L"Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com\n" );
wprintf( L"Based on Felix Kasza's CreateRemoteThread exmample, www.mvps.org\\win32\n" );
wprintf( L"\n" );
wprintf( L"Usage: LOADDLL [/L] [/U] processID dllPath [functionName]\n" );
wprintf( L"\n" );
wprintf( L" /L Loads the module\n" );
wprintf( L" /U Unloads the module\n" );
wprintf( L"\n" );
wprintf( L" processID Process ID\n" );
wprintf( L" dllPath Path for the module\n" );
wprintf( L" functionName Called function. Mustn't have parameters\n" );
wprintf( L"\n" );
wprintf( L"Examples:\n" );
wprintf( L" Loads and then unloads the module for process #728\n" );
wprintf( L" LOADDLL /L /U 728 your.dll\n" );
wprintf( L"\n" );
wprintf( L" Loads, calls the fnTest and unloads the module for process #728\n" );
wprintf( L" LOADDLL /L /U 728 your.dll fnTest\n" );
wprintf( L"\n" );
wprintf( L" Call the fnTest function. The module has to be loaded to the process\n" );
wprintf( L" LOADDLL 728 your.dll fnTest\n" );
wprintf( L"\n" );
wprintf( L" Unload the \"your.dll\" from process #728\n" );
wprintf( L" LOADDLL /U 728 your.dll\n" );
wprintf( L"\n" );
wprintf( L" Breaks the remote process\n" );
wprintf( L" LOADDLL 728 kernel32.dll DebugBreak\n" );
return 1;
}
// we need WinNT/Win2k
if ( !IsWindowsNT() )
{
wprintf( L"This executable needs WindowsNT/Windows2000\n" );
return 2;
}
//Enable debug privilege
EnableDebugPriv();
//Let's work
LoadDllForRemoteThread( pID, bLoad, bFree, lpModulePath, lpFunctionName );
return 0;
}
BOOL IsWindowsNT()
{
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure,
// which is supported on Windows 2000.
//
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
if( bOsVersionInfoEx == 0 )
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return FALSE;
}
return osvi.dwPlatformId == VER_PLATFORM_WIN32_NT;
}
DWORD ConvertWCharToChar( wchar_t* wStr, char* cStr, DWORD size )
{
ULONG i = 0;
wchar_t* wAct = wStr;
char* cAct = cStr;
*cStr = 0;
while ( *wAct != 0 && i < size )
{
*cAct++ = (char)*wAct++;
i++;
}
return i;
}
DWORD LoadDllForRemoteThread( DWORD processID, BOOL bLoad, BOOL bFree, wchar_t* lpModuleName, wchar_t* lpFunctionName )
{
// open the process
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, processID );
if ( hProcess != NULL )
{
// let's work
ExecuteRemoteThread( hProcess, bLoad, bFree, lpModuleName, lpFunctionName );
CloseHandle( hProcess );
}
else
wprintf( L"Open remote process failed! Error = %d\n", GetLastError() );
return 0;
}
void EnableDebugPriv( void )
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
// enable the SeDebugPrivilege
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
{
wprintf( L"OpenProcessToken() failed, Error = %d SeDebugPrivilege is not available.\n", GetLastError() );
return;
}
if ( ! LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) )
{
wprintf( L"LookupPrivilegeValue() failed, Error = %d SeDebugPrivilege is not available.\n", GetLastError() );
CloseHandle( hToken );
return;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if ( ! AdjustTokenPrivileges( hToken, FALSE, &tkp, sizeof tkp, NULL, NULL ) )
wprintf( L"AdjustTokenPrivileges() failed, Error = %d SeDebugPrivilege is not available.\n", GetLastError() );
CloseHandle( hToken );
}
bool ExecuteRemoteThread( HANDLE hProcess, BOOL bLoad, BOOL bFree, wchar_t* lpDllPath, wchar_t* lpFunctionName )
{
HANDLE ht = 0;
void *p = 0;
RemoteThreadBlock *c = 0;
bool result = false;
DWORD rc;
HMODULE hKernel32 = 0;
RemoteThreadBlock localCopy;
// clear the parameter block
::ZeroMemory( &localCopy, sizeof(localCopy) );
// allocate memory for injected code
p = VirtualAllocEx( hProcess, 0, MAXINJECTSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if ( p == 0 )
{
wprintf( L"VirtualAllocEx() failed, Error = %d \n", GetLastError() );
goto cleanup;
}
// allocate memory for parameter block
c = (RemoteThreadBlock*) VirtualAllocEx( hProcess, 0, sizeof(RemoteThreadBlock), MEM_COMMIT, PAGE_READWRITE );
if ( c == 0 )
{
wprintf( L"VirtualAllocEx() failed, Error = %d \n", GetLastError() );
goto cleanup;
}
// copy function there, we will execute this piece of code
if ( ! WriteProcessMemory( hProcess, p, &RemoteThread, MAXINJECTSIZE, 0 ) )
{
wprintf( L"WriteProcessMemory() failed, Error = %d \n", GetLastError() );
goto cleanup;
}
// copy dll path to parameter block
wcscpy( localCopy.lpModulePath, lpDllPath );
//GetProcAddrees doesn't support UNICODE ?!?!
if ( lpFunctionName == NULL )
localCopy.lpFunctionName[0] = 0;
else
ConvertWCharToChar( lpFunctionName, localCopy.lpFunctionName, sizeof(localCopy.lpFunctionName) );
localCopy.bLoadLibrary = bLoad;
localCopy.bFreeLibrary = bFree;
// load kernel32.dll
hKernel32 = LoadLibrary( L"kernel32.dll" );
if ( hKernel32 == NULL )
{
wprintf( L"Couldn't load kernel32.dll. That's a surprise!\n" );
goto cleanup;
}
// get the addresses for the functions, what we will use in the remote thread
localCopy.fnLoadLibrary = (PLoadLibraryW)GetProcAddress( hKernel32, "LoadLibraryW" );
localCopy.fnGetModuleHandle = (PGetModuleHandleW)GetProcAddress( hKernel32, "GetModuleHandleW" );
localCopy.fnFreeLibrary = (PFreeLibrary)GetProcAddress( hKernel32, "FreeLibrary" );
localCopy.fnGetProcAddress = (PGetProcAddress)GetProcAddress( hKernel32, "GetProcAddress" );
if (localCopy.fnLoadLibrary == NULL ||
localCopy.fnGetModuleHandle == NULL ||
localCopy.fnFreeLibrary == NULL ||
localCopy.fnGetProcAddress == NULL)
{
wprintf( L"GetProcAddress() failed. Error = %d\n", GetLastError() );
goto cleanup;
}
// copy the parameterblock to the other process adress space
if ( ! WriteProcessMemory( hProcess, c, &localCopy, sizeof localCopy, 0 ) )
{
wprintf( L"WriteProcessMemory() failed, Error = %d \n", GetLastError() );
goto cleanup;
}
// CreateRemoteThread()
ht = CreateRemoteThread( hProcess, 0, 0, (DWORD (__stdcall *)( void *)) p, c, 0, &rc );
if ( ht == NULL )
{
wprintf( L"CreateRemoteThread() failed, Error = %d \n", GetLastError() );
goto cleanup;
}
rc = WaitForSingleObject( ht, INFINITE );
switch ( rc )
{
case WAIT_TIMEOUT:
wprintf( L"WaitForSingleObject() timed out. INFINITE is over!" );
goto cleanup;
case WAIT_FAILED:
wprintf( L"WaitForSingleObject() failed, Error = %d \n", GetLastError() );
goto cleanup;
case WAIT_OBJECT_0:
// this might just have worked, pick up the result!
// rad back the prameter block, it has the error code
if ( ! ReadProcessMemory( hProcess, c, &localCopy, sizeof localCopy, 0 ) )
{
wprintf( L"ReadProcessMemory() failed, Error = %d\n", GetLastError() );
goto cleanup;
}
// get the result about loading the library
if ( bLoad )
{
wprintf( L"Loading \"%s\": ", lpDllPath );
switch( localCopy.ErrorLoad )
{
case 0:
wprintf( L"Loaded (0x%08X)\n", localCopy.hModule );
break;
default:
wprintf( L"Couldn't load\n", localCopy.ErrorLoad );
break;
}
}
// get the result about loading the library
if ( lpFunctionName != NULL )
{
wprintf( L"Calling \"%s\": ", lpFunctionName );
switch( localCopy.ErrorFunction )
{
case 0:
wprintf( L"Executed (0x%X)\n", localCopy.ReturnCodeForFunction );
break;
default:
wprintf( L"Couldn't find\n" );
break;
}
}
// get the result about freeing the library
if ( bFree )
{
wprintf( L"Freeing \"%s\": ", lpDllPath );
switch( localCopy.ErrorFree )
{
case 0:
wprintf( L"Released (0x%08X)\n", localCopy.hModule );
break;
default:
wprintf( L"Couldn't free\n" );
break;
}
}
break;
default:
wprintf( L"WaitForSingleObject() failed, Error = %d \n", GetLastError() );
break;
}
cleanup:
CloseHandle( ht );
// Let's clean
if ( p != 0 )
VirtualFreeEx( hProcess, p, 0, MEM_RELEASE );
if ( c != 0 )
VirtualFreeEx( hProcess, c, 0, MEM_RELEASE );
if ( hKernel32 != NULL)
FreeLibrary( hKernel32 );
return result;
}
// The whole shebang makes a number of assumptions:
// -- target process is a Win32 process
// -- kernel32.dll loaded at same address in each process (safe)
// -- bem() shorter than MAXINJECTSIZE
// -- bem() does not rely on the C/C++ runtime
// -- /GZ is _not_ used. (If it is, the compiler generates calls
// to functions which are not injected into the target. Oops!
DWORD __stdcall RemoteThread( RemoteThreadBlock* execBlock )
{
// and this is the code we are injecting
typedef DWORD (*PRemoteDllFunction)();
HMODULE hModule = NULL;
// clear the error codes
execBlock->ErrorLoad = 0;
execBlock->ErrorFunction = 0;
execBlock->ErrorFree = 0;
// load the requested dll
if ( execBlock->bLoadLibrary )
{
execBlock->hModule = (HMODULE)(*execBlock->fnLoadLibrary)( execBlock->lpModulePath );
hModule = execBlock->hModule;
execBlock->ErrorLoad = execBlock->hModule != NULL ? 0 : 1;
}
// if we didn't load the library, try to query the module handle
if ( hModule == NULL )
hModule = (*execBlock->fnGetModuleHandle)( execBlock->lpModulePath );
// call function
if ( execBlock->lpFunctionName[0] != 0 )
{
//execute a function if we have a function name
PRemoteDllFunction fnRemoteDllFunction = (PRemoteDllFunction)
(*execBlock->fnGetProcAddress)( hModule, execBlock->lpFunctionName );
// execute the function, and get the result
if ( fnRemoteDllFunction != NULL )
{
execBlock->ErrorFunction = 0;
execBlock->ReturnCodeForFunction = (*fnRemoteDllFunction)();
}
else
execBlock->ErrorFunction = 1;
}
// free library
if ( execBlock->bFreeLibrary )
{
execBlock->ErrorFree = execBlock->fnFreeLibrary( hModule ) ? 0 : 1;
}
execBlock->hModule = hModule;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -