Can I push a binary on a remote host windows using WINRM.
If not is there any other mechanism which allows me to push a binary on remote host.
I think I found a solution.
#include <windows.h>
#include <tchar.h>
#define SIZEOF_BUFFER 0x100
// Remote Parameters
LPCTSTR lpszMachine = NULL;
LPCTSTR lpszPassword = NULL;
LPCTSTR lpszUser = NULL;
LPCTSTR lpszDomain = NULL;
LPCTSTR lpszCommandExe = NULL;
LPCTSTR lpszLocalIP = _T("\\\\127.0.0.1");
char szThisMachine[SIZEOF_BUFFER] = "";
char szPassword[SIZEOF_BUFFER] = "";
LPCTSTR GetParamValue( LPCTSTR lpszParam )
{
DWORD dwParamLength = _tcslen( lpszParam );
for ( int i = 1; i < __argc; i++ )
if ( __targv[i][0] == _T('\\') || __targv[i][0] == _T('.'))
continue;
else
if ( __targv[i][0] == _T('/') || __targv[i][0] == _T('-') )
{
if ( _tcsnicmp( __targv[i] + 1, lpszParam, dwParamLength ) == 0 )
return __targv[i] + dwParamLength + 1;
}
else
return NULL;
return NULL;
}
LPCTSTR GetNthParameter( DWORD n, DWORD& argvIndex )
{
DWORD index = 0;
for( int i = 1; i < __argc; i++ )
{
if ( __targv[i][0] != _T('/') && __targv[i][0] != _T('-') )
index++;
if ( index == n )
{
argvIndex = i;
return __targv[i];
}
}
return NULL;
}
BOOL SetConnectionCredentials()
{
lpszPassword = GetParamValue( _T("pwd:") );
lpszUser = GetParamValue( _T("user:") );
return TRUE;
}
LPCTSTR GetRemoteMachineName()
{
DWORD dwIndex = 0;
LPCTSTR lpszMachine = GetNthParameter( 1, dwIndex );
if ( lpszMachine == NULL )
// return NULL;
return lpszLocalIP;
if ( _tcsnicmp( lpszMachine, _T(" "), 2 ) == 0 )
return lpszLocalIP;
if ( _tcsnicmp( lpszMachine, _T("\\\\"), 2 ) == 0 )
return lpszMachine;
// If a dot is entered we take it as localhost
if ( _tcsnicmp( lpszMachine, _T("."), 2 ) == 0 )
return lpszLocalIP;
return NULL;
}
// Establish Connection to Remote Machine
BOOL EstablishConnection( LPCTSTR lpszRemote, LPCTSTR lpszResource, BOOL bEstablish )
{
TCHAR szRemoteResource[_MAX_PATH];
DWORD rc;
_stprintf( szRemoteResource, _T("%s\\%s"), lpszRemote, lpszResource );
NETRESOURCE nr;
nr.dwType = RESOURCETYPE_ANY;
nr.lpLocalName = NULL;
nr.lpRemoteName = (LPTSTR)&szRemoteResource;
nr.lpProvider = NULL;
//Establish connection (using username/pwd)
rc = WNetAddConnection2( &nr, lpszPassword, lpszUser, FALSE );
if ( rc == NO_ERROR )
return TRUE; // indicate success
return FALSE;
}
BOOL CopyBinaryToRemoteSystem()
{
TCHAR drive[_MAX_DRIVE];
TCHAR dir[_MAX_DIR];
TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT];
TCHAR szRemoteResource[_MAX_PATH];
// Gets the file name and extension
_tsplitpath( lpszCommandExe, drive, dir, fname, ext );
_stprintf( szRemoteResource, _T("%s\\ADMIN$\\System32\\%s%s"), lpszMachine, fname, ext );
// Copy the Command's exe file to \\remote\ADMIN$\System32
return CopyFile( lpszCommandExe, szRemoteResource, FALSE );
}
int _tmain( DWORD, TCHAR**, TCHAR** )
{
int rc = 0;
DWORD dwIndex = 0;
lpszMachine = GetRemoteMachineName();
lpszCommandExe = GetNthParameter( 2, dwIndex );
SetConnectionCredentials();
if ( !EstablishConnection( lpszMachine, _T("ADMIN$"), TRUE ) )
{
rc = -2;
}
if ( !CopyBinaryToRemoteSystem())
{
}
return 0;
}
Related
I have some C++ code that I need to use for serial communication between PC and Arduino. The file "Serial.cpp" is including a file called "stdafx.h" that doesn't exist in the project or anywhere on my computer, which obviously causes an error.
Other than that, I also get other errors, such as C2065 'CSerial': undeclared identifier.
Here are the three files that are in the project:
Serial.h
#ifndef __SERIAL_H__
#define __SERIAL_H__
#pragma once
#include <Windows.h>
#include <memory.h>
#define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04
#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13
class CSerial
{
public:
CSerial();
~CSerial();
BOOL Open( int nPort = 2, int nBaud = 9600 );
BOOL Close( void );
int ReadData( void *, int );
int SendData( const char *, int );
int ReadDataWaiting( void );
BOOL IsOpened( void ){ return( m_bOpened ); }
protected:
BOOL WriteCommByte( unsigned char );
HANDLE m_hIDComDev;
OVERLAPPED m_OverlappedRead, m_OverlappedWrite;
bool m_bOpened;
};
#endif
Serial.cpp
// Serial.cpp
#include "stdafx.h"
#include "Serial.h"
CSerial::CSerial()
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = false;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );
wchar_t szPort[15];
wchar_t szComParams[50];
DCB dcb;
wsprintf( szPort, L"COM%d", nPort );
m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == NULL ) return( FALSE );
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
wsprintf( szComParams, L"COM%d:%d,n,8,1", nPort, nBaud );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
return( FALSE );
}
m_bOpened = TRUE;
return( m_bOpened );
}
BOOL CSerial::Close( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
m_bOpened = FALSE;
m_hIDComDev = NULL;
return( TRUE );
}
BOOL CSerial::WriteCommByte( unsigned char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
else{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return( TRUE );
}
int CSerial::SendData( const char *buffer, int size )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwBytesWritten = 0;
int i;
for( i=0; i<size; i++ ){
WriteCommByte( buffer[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
}
int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return( (int) ComStat.cbInQue );
}
int CSerial::ReadData( void *buffer, int limit )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
return( (int) dwBytesRead );
}
SerialExample.cpp
bool sendExample(int port, int baudRate)
{
char data[4];
CSerial* s = new CSerial();
if(!s->Open(port, baudRate))
{
std_out << _T("Could not open COM") << port << endl;
return false;
}
// Sending a string of 4 characters
data[0] = 0x31;
data[1] = 0x32;
data[2] = 0x33;
data[3] = 0x0D; // ASCII CR
s->SendData(data, 4);
s->Close();
delete s;
}
Does anyone know what I have to do?
stdafx.h is a precompiled header for Visual studio. so if you are not working in visual studio, you can just remove it and it should work just fine.
In regard to the compiler not recognizing the CSerial class -
I don't see where you include "CSerial.h" in SerialExample.cpp (i.e: #include "CSerial.h"), but if you do, this may also be a symptom of CSerial.cpp not compiling (less likely though)...
Hope this helps,
Lior
Does Stackwalk64 work on Windows Server 2012 and 2008R2? I can't get this code to work. Anyone else here have it working? I use it to generate a stack trace for another thread.
I'm using:
myframe.AddrPC.Mode = AddrModeFlat;
myframe.AddrFrame.Mode = AddrModeFlat;
myframe.AddrStack.Mode = AddrModeFlat;
myframe.AddrPC.Offset = context.Rip;
myframe.AddrFrame.Offset = context.Rbp;
myframe.AddrStack.Offset = context.Rsp;
while(pStackWalk64(IMAGE_FILE_MACHINE_AMD64, GetCurrentProcess(), handleforanotherthread,&myframe,
&context, NULL, funcTableAccess, SymGetModuleBase64, NULL))
{
if(myframe.AddrPC.Offset == myframe.AddrReturn.Offset)
break;
}
It fails and the address returned is not valid.
Here is our version of this code. The original came from an MSJ article but it has been heavily modified.
bool MSJExceptionHandler::ImagehlpStackWalk( PCONTEXT pCtx )
{
bool result = false;
// PCONTEXT pContext = pEP->ContextRecord;
if( m_Levels == 0 ) {
dbbTrace::OutputWithoutTimestamp( "\nCall stack:\n" );
dbbTrace::OutputWithoutTimestamp( "Address Frame\n" );
}
// Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag
STACKFRAME64 sf;
bool first = true;
FIXED_ARRAY( buf, char, 300 );
size_t buflen = sizeof(buf);
// Indexes into MSJExceptionHandler data when m_Levels > 0
int i_line = 0; // Into char * m_Lines[]
int i_buf = 0; // into char m_Buffer[]
memset( &sf, 0, sizeof(sf) );
// Initialize the STACKFRAME structure for the first call. This is only
// necessary for Intel CPUs, and isn't mentioned in the documentation.
DWORD64 pFrame = 0;
DWORD64 pPrevFrame = 0;
sf.AddrPC.Mode = AddrModeFlat;
sf.AddrStack.Mode = AddrModeFlat;
sf.AddrFrame.Mode = AddrModeFlat;
#ifdef _M_IX86 // Intel Only!
sf.AddrPC.Offset = pCtx->Eip;
sf.AddrStack.Offset = pCtx->Esp;
sf.AddrFrame.Offset = pCtx->Ebp;
#endif
#ifdef _M_X64 // Intel Only!
sf.AddrPC.Offset = pCtx->Rip;
sf.AddrStack.Offset = pCtx->Rsp;
sf.AddrFrame.Offset = pCtx->Rbp;
#endif
#ifdef _M_IA64
// Itanium
DWORD64 pFrame, pPrevFrame;
#pragma message("fix me")
sf.AddrPC.Offset = 0;
sf.AddrStack.Offset = 0;
sf.AddrFrame.Offset = 0;
#endif
#ifdef _M_IX86
DWORD MachineType = IMAGE_FILE_MACHINE_I386;
#endif
#ifdef _M_X64
DWORD MachineType = IMAGE_FILE_MACHINE_AMD64;
#endif
#ifdef _M_IA64
DWORD MachineType = IMAGE_FILE_MACHINE_IA64;
#endif
while ( 1 )
{
SetLastError( 0 );
if ( ! StackWalk64( MachineType,
m_hProcess,
GetCurrentThread(),
&sf,
pCtx,
0,
SymFunctionTableAccess64,
SymGetModuleBase64,
0 ) )
break;
pFrame = sf.AddrFrame.Offset;
if ( 0 == pFrame ) // Basic sanity check to make sure
break; // the frame is OK. Bail if not.
// dbbTrace::OutputWithoutTimestamp( "%08X %08X ", sf.AddrPC.Offset, pFrame );
if( ! first ) {
if( pFrame <= pPrevFrame ) {
// Sanity check
break;
}
if( (pFrame - pPrevFrame) > 10000000 ) {
// Sanity check
break;
}
}
if( (pFrame % sizeof(void *)) != 0 ) {
// Sanity check
break;
}
pPrevFrame = pFrame;
first = false;
// IMAGEHLP is wacky, and requires you to pass in a pointer to an
// IMAGEHLP_SYMBOL structure. The problem is that this structure is
// variable length. That is, you determine how big the structure is
// at runtime. This means that you can't use sizeof(struct).
// So...make a buffer that's big enough, and make a pointer
// to the buffer. We also need to initialize not one, but TWO
// members of the structure before it can be used.
enum { emMaxNameLength = 512 };
// Use union to ensure proper alignment
union {
SYMBOL_INFO symb;
BYTE symbolBuffer[ sizeof(SYMBOL_INFO) + emMaxNameLength ];
} u;
PSYMBOL_INFO pSymbol = & u.symb;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = emMaxNameLength;
PDWORD64 symDisplacement = 0; // Displacement of the input address,
// relative to the start of the symbol
DWORD lineDisplacement = 0;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(line);
line.LineNumber = 0;
BOOL bLine = FALSE;
bLine = SymGetLineFromAddr64( m_hProcess, sf.AddrPC.Offset,
& lineDisplacement, & line );
if ( SymFromAddr(m_hProcess, sf.AddrPC.Offset,
symDisplacement, pSymbol) )
{
if( bLine ) {
_snprintf( buf, buflen,
ADDR_FORMAT " " ADDR_FORMAT " %s() line %d\n",
sf.AddrPC.Offset, pFrame,
pSymbol->Name, line.LineNumber );
} else {
_snprintf( buf, buflen,
ADDR_FORMAT " " ADDR_FORMAT " %s() + %X\n",
sf.AddrPC.Offset, pFrame,
pSymbol->Name, symDisplacement );
}
}
else // No symbol found. Print out the logical address instead.
{
DWORD err = GetLastError();
FIXED_ARRAY( szModule , TCHAR, MAX_PATH );
szModule[0] = '\0';
DWORD section = 0, offset = 0;
GetLogicalAddress( (PVOID)sf.AddrPC.Offset,
szModule, sizeof(szModule), section, offset );
_snprintf( buf, buflen,
ADDR_FORMAT " " ADDR_FORMAT " %04X:%08X %s (err = %d)\n",
sf.AddrPC.Offset, pFrame,
section, offset, szModule, err );
result = true;
}
if( m_Levels == 0 ) {
dbbTrace::OutputString( buf, false );
} else {
// Save line
size_t l = strlen(buf);
if( i_line >= m_Levels || i_buf + l >= m_Bytes ) {
// We have saved all of the stack we can save
break;
}
buf[ l - 1 ] = '\0'; // Remove trailing '\n'
char * s = & m_Buffer[ i_buf ];
m_Lines[ i_line++ ] = s;
strncpy( s, buf, l );
i_buf += l;
}
} // while
return result;
} // MSJExceptionHandler::ImagehlpStackWalk()
I am implementing a recursive registry delete using RegOpenKeyEx, RegDeleteKey and RegEnumKey.
Problem:: Though the code works perfectly fine for Vista x86/x64 and Win 7 x86/x64 but fails on XP for some keys in HKCR
Problem Area:: HKCR\Installer\Products\SomeKey
Error Code:: 87 (INVALID_PARAMETER)
Weird Behaviour:: Deletes the key the moment I open the key using REGEDIT.
Code::
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub )
{
BOOL bRet = TRUE ;
LONG lRet ;
DWORD dwSize = MAX_PATH ;
TCHAR szName[MAX_PATH] ;
TCHAR szFullKey[MAX_PATH * 2] ;
HKEY hKeySub = NULL ;
HRESULT hr = NULL ;
do{
lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKeySub ) ;
printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
if( lRet == ERROR_FILE_NOT_FOUND )
{
bRet = TRUE ;
break ;
}
else
{
bRet = FALSE ;
break ;
}
}
while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL)) )
{
bRet = RcrsvRegDel( hKeySub, szName) ;
if( bRet == FALSE )
break ;
}
if( hKeySub != NULL )
{
RegCloseKey(hKeySub) ;
hKeySub = NULL ;
}
lRet = RegDeleteKey( hKey, lpszSub ) ;
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet == ERROR_SUCCESS )
{
bRet = TRUE ;
break ;
}
}while(0) ;
return bRet ;
}
Any idea whats goin on?
UPDATE::
I have also tried the samDesired Parameter with following flags
-KEY_READ
-KEY_READ | KEY_WRITE
-KEY_ENUMERATE_SUB_KEYS
-KEY_ENUMERATE_SUB_KEYS | DELETE
Neither of the above flag works :-(
Because you can not use RegDeleteKey with handle was opened with flag KEY_WOW64_32KEY.
see http://msdn.microsoft.com/en-us/library/aa384129(v=vs.85).aspx for info.
You have to use RegDeleteKeyEx with same keys.
You can do like this. Take the flag as input parameter and pass one flag for the RegOpenKeyEx and again a set of flags when calling the recursive function. I have tried your code and it is working perfectly now, though it is not sure as to what was it that was causing the problem.
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub, DWORD dwOpenFlags )
{
BOOL bRet = TRUE ;
LONG lRet ;
DWORD dwSize = MAX_PATH ;
TCHAR szName[MAX_PATH] ;
HKEY hKeySub = NULL ;
HRESULT hr = NULL ;
HANDLE hProcess = NULL ;
HANDLE hToken = NULL ;
do{
bRet = SetPrivilege( SE_BACKUP_NAME, TRUE ) ;
if( bRet == FALSE )
{
bRet = FALSE ;
break ;
}
lRet = RegOpenKeyEx( hKey, lpszSub, 0, dwOpenFlags, &hKeySub ) ;
if( lRet != ERROR_SUCCESS )
{
bRet = FALSE ;
break ;
}
while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL,
NULL, NULL, NULL)) )
if( !RcrsvRegDel(hKeySub, szName, dwOpenFlags) )
{
bRet = FALSE ;
break ;
}
lRet = RegDeleteKey( hKey, lpszSub ) ;
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
bRet = FALSE ;
break ;
}
if( hKeySub != NULL )
{
RegCloseKey(hKeySub) ;
hKeySub = NULL ;
}
}while(0) ;
return bRet ;
}
static BOOL SetPrivilege( LPCTSTR lpszPrivilege, BOOL bEnablePrivilege )
{
LUID luid ;
BOOL bRet = TRUE ;
HANDLE hToken = NULL ;
HANDLE hProcess = NULL ;
TOKEN_PRIVILEGES tp ;
do{
hProcess = GetCurrentProcess() ;
if( 0 == OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) )
{
bRet = FALSE ;
break ;
}
if( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) )
{
bRet = FALSE ;
break ;
}
tp.PrivilegeCount = 1 ;
tp.Privileges[0].Luid = luid ;
if( bEnablePrivilege )
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
else
tp.Privileges[0].Attributes = 0 ;
if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL) )
{
bRet = FALSE ;
break ;
}
if( ERROR_NOT_ALL_ASSIGNED == GetLastError() )
{
bRet = FALSE ;
break ;
}
}while(0) ;
if( hToken != NULL ) CloseHandle( hToken ) ;
return bRet ;
}
You cannot use RegDeleteKey() to delete a 32-bit key on a 64-bit system. The documentation says as much:
The RegDeleteKey function cannot be used to access an alternate registry view.
You must use RegDeleteKeyEx() instead.
Try something like this:
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
extern LPFN_ISWOW64PROCESS fnIsWow64Process;
typedef LONG (WINAPI *LPFN_REGDELETEKEYEX)(HKEY, LPCTSTR, REGSAM, DWORD);
extern LPFN_REGDELETEKEYEX fnRegDeleteKeyEx;
.
BOOL WINAPI IsWow64Process_Impl(HANDLE hHandle, PBOOL Wow64Process);
{
*Wow64Process = FALSE;
return TRUE;
}
BOOL WINAPI IsWow64Process_Stub(HANDLE hProcess, PBOOL Wow64Process)
{
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
if ( NULL == fnIsWow64Process )
fnIsWow64Process = &IsWow64Process_Impl;
return fnIsWow64Process(hProcess, Wow64Process);
}
LONG WINAPI RegDeleteKeyEx_Impl(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
return RegDeleteKey( hKey, lpSubKey );
}
LONG WINAPI RegDeleteKeyEx_Stub(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
fnRegDeleteKeyEx = (LPFN_REGDELETEKEYEX) GetProcAddress(GetModuleHandle(TEXT("advapi32")),
#ifdef UNICODE
"RegDeleteKeyExW"
#else
"RegDeleteKeyExA"
#endif
);
if ( NULL == fnRegDeleteKeyEx )
fnRegDeleteKeyEx = &RegDeleteKeyEx_Impl;
return fnRegDeleteKeyEx( hKey, lpSubKey, samDesired, dwReserved );
}
LPFN_ISWOW64PROCESS fnIsWow64Process = &IsWow64Process_Stub;
LPFN_REGDELETEKEYEX fnRegDeleteKeyEx = &RegDeleteKeyEx_Stub;
.
BOOL IsWin64()
{
#if defined(_WIN64)
return FALSE; // 64-bit programs run only on Win64
#elif defined(_WIN32)
// 32-bit programs run on both 32-bit and 64-bit Windows so must sniff
BOOL f64 = FALSE;
return fnIsWow64Process(GetCurrentProcess(), &f64) && f64;
#else
return FALSE; // Win64 does not support Win16
#endif
}
.
static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub )
{
BOOL bRet = TRUE;
LONG lRet;
DWORD dwSize;
TCHAR szName[MAX_PATH+1];
HKEY hKeySub = NULL;
REGSAM Wow64Flag = (IsWin64()) ? KEY_WOW64_32KEY : 0;
lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | DELETE | Wow64Flag, &hKeySub ) ;
printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if( lRet != ERROR_SUCCESS )
{
if ( lRet != ERROR_FILE_NOT_FOUND )
bRet = FALSE;
}
else
{
do
{
dwSize = MAX_PATH;
lRet = RegEnumKeyEx( hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL );
if ( lRet != ERROR_SUCCESS )
{
if ( lRet != ERROR_NO_MORE_ITEMS )
bRet = FALSE;
break;
}
bRet = RcrsvRegDel( hKeySub, szName );
if ( !bRet )
break;
}
while (1);
RegCloseKey(hKeySub);
if ( bRet )
{
if ( Wow64Flag != 0 )
lRet = fnRegDeleteKeyEx( hKey, lpszSub, Wow64Flag, 0 );
else
lRet = RegDeleteKey( hKey, lpszSub );
printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
if ( lRet != ERROR_SUCCESS )
bRet = FALSE;
}
}
return bRet;
}
With that said, consider using RegDeleteTree() or SHDeleteKey() instead. Let them do the recursion for you.
I have a foreign process (exe-file DllProj.exe is running), that has SampleDll.dll linked to it (implicit linking). I can find the base address of the linked dll with the help of my function imageBase(), but not the base address of the process itself! What is the difference and why it's not working as is?
I mean, this code returns pBase with correct DOS/NT-headers:
LPVOID pBase = imageBase("DllProj.exe", "SampleDll.dll");
if (!pBase)
return false;
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER((HMODULE)pBase);
if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ||
IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
return false;
but this code return is FALSE:
LPVOID pBase = imageBase("DllProj.exe", "DllProj.exe");
//and so on...
Here is my procedure:
LPVOID imageBase(LPSTR szVictimProcess, LPSTR szVictim)
{
//находим процесс szVictimProcess
DWORD aProcesses[1024], cbNeeded, nProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return NULL;
nProcesses = cbNeeded / sizeof(DWORD);
HANDLE ProcHandle = 0;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
for (i = 0; i < nProcesses; i++)
{
ProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
if (NULL != ProcHandle)
{
HMODULE hMod[1024];
if ( EnumProcessModules(ProcHandle, hMod, sizeof(hMod), &cbNeeded) )
{
GetModuleBaseName(ProcHandle, hMod[0], szProcessName, sizeof(szProcessName)/sizeof(TCHAR)); // Get the process name
if (0 == lstrcmpiA(szVictimProcess, szProcessName))
{
//находим модуль szVictim
DWORD nModules = cbNeeded / sizeof(HMODULE);
char szModName[MAX_PATH];
for (unsigned int j = 0; j < nModules; j++)
{
if (GetModuleFileNameEx(ProcHandle, hMod[j], szModName, sizeof(szModName))) // Get the module name
{
shortName(szModName);
if (0 == lstrcmpiA(szModName, szVictim))
{
MODULEINFO info;
GetModuleInformation(ProcHandle, hMod[j], &info, sizeof(info));
return info.lpBaseOfDll;
//Equal To:
//return hMod[j];
//Debug:
//LPSTR string = new char[256];
//wsprintf(string,"\t%s (0x%08X)\n", szModName, hMod[j]);
}
}
}
break;
}
}
}
CloseHandle(ProcHandle);
}
return NULL;
}
P.S.: My next goal is to get import-table of DllProj.exe (where Sample.dll is) and hiijack dll's function call
What about using this:
#pragma comment( lib, "psapi" )
DWORD GetModuleBase(HANDLE hProc, string &sModuleName)
{
HMODULE *hModules;
char szBuf[50];
DWORD cModules;
DWORD dwBase = -1;
//------
EnumProcessModules(hProc, hModules, 0, &cModules);
hModules = new HMODULE[cModules/sizeof(HMODULE)];
if(EnumProcessModules(hProc, hModules, cModules/sizeof(HMODULE), &cModules)) {
for(int i = 0; i < cModules/sizeof(HMODULE); i++) {
if(GetModuleBaseName(hProc, hModules[i], szBuf, sizeof(szBuf))) {
if(sModuleName.compare(szBuf) == 0) {
dwBase = (DWORD)hModules[i];
break;
}
}
}
}
delete[] hModules;
return dwBase;
}
Credit to answer here
There is nothing wrong with your code, I compiled your code and it works fine and outputs the correct address to console. Make sure you run as administrator. This is the project using your code which I tested working:
#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <string>
void shortName(LPSTR strToChange)
{
std::string path(strToChange);
std::string filename;
size_t pos = path.find_last_of("\\");
if (pos != std::string::npos)
filename.assign(path.begin() + pos + 1, path.end());
else
filename = path;
lstrcpy(strToChange, filename.data());
}
LPVOID imageBase(LPSTR szVictimProcess, LPSTR szVictim)
{
DWORD aProcesses[1024], cbNeeded, nProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return NULL;
nProcesses = cbNeeded / sizeof(DWORD);
HANDLE ProcHandle = 0;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
for (i = 0; i < nProcesses; i++)
{
ProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
if (NULL != ProcHandle)
{
HMODULE hMod[1024];
if (EnumProcessModules(ProcHandle, hMod, sizeof(hMod), &cbNeeded))
{
GetModuleBaseName(ProcHandle, hMod[0], szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); // Get the process name
if (0 == lstrcmpiA(szVictimProcess, szProcessName))
{
DWORD nModules = cbNeeded / sizeof(HMODULE);
char szModName[MAX_PATH];
for (unsigned int j = 0; j < nModules; j++)
{
if (GetModuleFileNameEx(ProcHandle, hMod[j], szModName, sizeof(szModName))) // Get the module name
{
shortName(szModName);
if (0 == lstrcmpiA(szModName, szVictim))
{
MODULEINFO info;
GetModuleInformation(ProcHandle, hMod[j], &info, sizeof(info));
return info.lpBaseOfDll;
}
}
}
break;
}
}
}
CloseHandle(ProcHandle);
}
return NULL;
}
int main(void)
{
void* base = imageBase((char*)"ac_client.exe", (char*)"ac_client.exe");
std::cout << "0x" << std::hex << base;
}
How do I enumerate network adapters and get their MAC addresses in Win32 API C++?
This code should work:
{
ULONG outBufLen = 0;
DWORD dwRetVal = 0;
IP_ADAPTER_INFO* pAdapterInfos = (IP_ADAPTER_INFO*) malloc(sizeof(IP_ADAPTER_INFO));
// retry up to 5 times, to get the adapter infos needed
for( int i = 0; i < 5 && (dwRetVal == ERROR_BUFFER_OVERFLOW || dwRetVal == NO_ERROR); ++i )
{
dwRetVal = GetAdaptersInfo(pAdapterInfos, &outBufLen);
if( dwRetVal == NO_ERROR )
{
break;
}
else if( dwRetVal == ERROR_BUFFER_OVERFLOW )
{
free(pAdapterInfos);
pAdapterInfos = (IP_ADAPTER_INFO*) malloc(outBufLen);
}
else
{
pAdapterInfos = 0;
break;
}
}
if( dwRetVal == NO_ERROR )
{
IP_ADAPTER_INFO* pAdapterInfo = pAdapterInfos;
while( pAdapterInfo )
{
IP_ADDR_STRING* pIpAddress = &(pAdapterInfo->IpAddressList);
while( pIpAddress != 0 )
{
//
// <<<<
// here pAdapterInfo->Address should contain the MAC address
// >>>>
//
pIpAddress = pIpAddress->Next;
}
pAdapterInfo = pAdapterInfo->Next;
}
}
free(pAdapterInfos);
return false;
}