Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // 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, NULL, 0, 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( "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;
- }
Add Comment
Please, Sign In to add comment