I'm modifying a small one that works only by console and requires console arguments. But now I wanted to pass it to winmain (form) and get those arguments using GetCommandLine
and use them in WinMain
as I did in console. The program is as follows:
#include "stdafx.h"
int wmain(int argc, wchar_t* argv[]) {
assert(argc > 1);
// build command line
wchar_t commandLine[MAX_PATH * 2];
::lstrcpyW(commandLine, argv[1]);
if (argc > 2) {
::lstrcatW(commandLine, L" ");
::lstrcatW(commandLine, argv[2]);
}
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
// create the actual process with the debug flag to avoid an infinite loop
BOOL bCreated = ::CreateProcessW(nullptr, commandLine, nullptr, nullptr, FALSE, DEBUG_PROCESS, nullptr, nullptr, &si, &pi);
if (bCreated) {
WCHAR path[MAX_PATH];
::GetModuleFileName(nullptr, path, MAX_PATH);
*::wcsrchr(path, L'\') = L'int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
//int wmain(int argc, wchar_t* argv[]) {
assert(argc > 1);
// build command line
wchar_t commandLine[MAX_PATH * 2];
::lstrcpyW(commandLine, argv[1]);
if (argc > 2) {
::lstrcatW(commandLine, L" ");
::lstrcatW(commandLine, argv[2]);
}
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
// create the actual process with the debug flag to avoid an infinite loop
BOOL bCreated = ::CreateProcessW(nullptr, commandLine, nullptr, nullptr, FALSE, DEBUG_PROCESS, nullptr, nullptr, &si, &pi);
if (bCreated) {
WCHAR path[MAX_PATH];
::GetModuleFileName(nullptr, path, MAX_PATH);
*::wcsrchr(path, L'\') = L'C2065: 'argc': undeclared identifier
C2065: 'argv': undeclared identifier
C2660: 'lstrcpyW': function does not take 1 arguments
C2065: 'argc': undeclared identifier
C2065: 'argv': undeclared identifier
C2660: 'lstrcatW': function does not take 1 arguments
';
::wcscat_s(path, MAX_PATH, L"\Injected.Dll");
// create a semaphore which count represents the main thread ID
HANDLE hSemaphore = ::CreateSemaphore(nullptr, pi.dwThreadId - 1, pi.dwThreadId, L"InjectedMainThread");
assert(hSemaphore);
// duplicate in the injected process so the semaphore survives after the injected process goes away
HANDLE hTarget = nullptr;
::DuplicateHandle(::GetCurrentProcess(), hSemaphore, pi.hProcess, &hTarget, 0, FALSE, DUPLICATE_SAME_ACCESS);
assert(hTarget);
// allocate buffer for the DLL path name
void* pPathBuffer = ::VirtualAllocEx(pi.hProcess, nullptr, MAX_PATH * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
assert(pPathBuffer);
// write the path
SIZE_T written;
::WriteProcessMemory(pi.hProcess, pPathBuffer, path, MAX_PATH * sizeof(WCHAR), &written);
// create a remote thread to load the DLL
HANDLE hRemoteThread = ::CreateRemoteThread(pi.hProcess, nullptr, 0,
(PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(L"kernel32"), "LoadLibraryW"),
pPathBuffer, 0, nullptr);
// allow the process to continue after this one exits
::DebugSetProcessKillOnExit(FALSE);
// close handles (not really needed as we're existing)
//::CloseHandle(hRemoteThread);
//::CloseHandle(pi.hProcess);
//::CloseHandle(pi.hThread);
//::CloseHandle(hSemaphore);
}
return 0;
}
';
::wcscat_s(path, MAX_PATH, L"\dllmain.Dll");
// create a semaphore which count represents the main thread ID
HANDLE hSemaphore = ::CreateSemaphore(nullptr, pi.dwThreadId - 1, pi.dwThreadId, L"InjectedMainThread");
assert(hSemaphore);
// duplicate in the injected process so the semaphore survives after the injected process goes away
HANDLE hTarget = nullptr;
::DuplicateHandle(::GetCurrentProcess(), hSemaphore, pi.hProcess, &hTarget, 0, FALSE, DUPLICATE_SAME_ACCESS);
assert(hTarget);
// allocate buffer for the DLL path name
void* pPathBuffer = ::VirtualAllocEx(pi.hProcess, nullptr, MAX_PATH * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
assert(pPathBuffer);
// write the path
SIZE_T written;
::WriteProcessMemory(pi.hProcess, pPathBuffer, path, MAX_PATH * sizeof(WCHAR), &written);
// create a remote thread to load the DLL
HANDLE hRemoteThread = ::CreateRemoteThread(pi.hProcess, nullptr, 0,
(PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(L"kernel32"), "LoadLibraryW"),
pPathBuffer, 0, nullptr);
// allow the process to continue after this one exits
::DebugSetProcessKillOnExit(FALSE);
// close handles (not really needed as we're existing)
::CloseHandle(hRemoteThread);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
::CloseHandle(hSemaphore);
}
return 0;
}
I ask because I need help from an expert since I can make the modification but I am not sure if this program will work correctly.
In this case you will pass two arguments and the assert does not understand very well so that it works since it is assumed that if it is not greater than one (the number of arguments) the program will abort.
I convert it to winmain:
#include "stdafx.h"
int wmain(int argc, wchar_t* argv[]) {
assert(argc > 1);
// build command line
wchar_t commandLine[MAX_PATH * 2];
::lstrcpyW(commandLine, argv[1]);
if (argc > 2) {
::lstrcatW(commandLine, L" ");
::lstrcatW(commandLine, argv[2]);
}
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
// create the actual process with the debug flag to avoid an infinite loop
BOOL bCreated = ::CreateProcessW(nullptr, commandLine, nullptr, nullptr, FALSE, DEBUG_PROCESS, nullptr, nullptr, &si, &pi);
if (bCreated) {
WCHAR path[MAX_PATH];
::GetModuleFileName(nullptr, path, MAX_PATH);
*::wcsrchr(path, L'\') = L'int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
//int wmain(int argc, wchar_t* argv[]) {
assert(argc > 1);
// build command line
wchar_t commandLine[MAX_PATH * 2];
::lstrcpyW(commandLine, argv[1]);
if (argc > 2) {
::lstrcatW(commandLine, L" ");
::lstrcatW(commandLine, argv[2]);
}
PROCESS_INFORMATION pi;
STARTUPINFO si = { sizeof(si) };
// create the actual process with the debug flag to avoid an infinite loop
BOOL bCreated = ::CreateProcessW(nullptr, commandLine, nullptr, nullptr, FALSE, DEBUG_PROCESS, nullptr, nullptr, &si, &pi);
if (bCreated) {
WCHAR path[MAX_PATH];
::GetModuleFileName(nullptr, path, MAX_PATH);
*::wcsrchr(path, L'\') = L'C2065: 'argc': undeclared identifier
C2065: 'argv': undeclared identifier
C2660: 'lstrcpyW': function does not take 1 arguments
C2065: 'argc': undeclared identifier
C2065: 'argv': undeclared identifier
C2660: 'lstrcatW': function does not take 1 arguments
';
::wcscat_s(path, MAX_PATH, L"\Injected.Dll");
// create a semaphore which count represents the main thread ID
HANDLE hSemaphore = ::CreateSemaphore(nullptr, pi.dwThreadId - 1, pi.dwThreadId, L"InjectedMainThread");
assert(hSemaphore);
// duplicate in the injected process so the semaphore survives after the injected process goes away
HANDLE hTarget = nullptr;
::DuplicateHandle(::GetCurrentProcess(), hSemaphore, pi.hProcess, &hTarget, 0, FALSE, DUPLICATE_SAME_ACCESS);
assert(hTarget);
// allocate buffer for the DLL path name
void* pPathBuffer = ::VirtualAllocEx(pi.hProcess, nullptr, MAX_PATH * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
assert(pPathBuffer);
// write the path
SIZE_T written;
::WriteProcessMemory(pi.hProcess, pPathBuffer, path, MAX_PATH * sizeof(WCHAR), &written);
// create a remote thread to load the DLL
HANDLE hRemoteThread = ::CreateRemoteThread(pi.hProcess, nullptr, 0,
(PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(L"kernel32"), "LoadLibraryW"),
pPathBuffer, 0, nullptr);
// allow the process to continue after this one exits
::DebugSetProcessKillOnExit(FALSE);
// close handles (not really needed as we're existing)
//::CloseHandle(hRemoteThread);
//::CloseHandle(pi.hProcess);
//::CloseHandle(pi.hThread);
//::CloseHandle(hSemaphore);
}
return 0;
}
';
::wcscat_s(path, MAX_PATH, L"\dllmain.Dll");
// create a semaphore which count represents the main thread ID
HANDLE hSemaphore = ::CreateSemaphore(nullptr, pi.dwThreadId - 1, pi.dwThreadId, L"InjectedMainThread");
assert(hSemaphore);
// duplicate in the injected process so the semaphore survives after the injected process goes away
HANDLE hTarget = nullptr;
::DuplicateHandle(::GetCurrentProcess(), hSemaphore, pi.hProcess, &hTarget, 0, FALSE, DUPLICATE_SAME_ACCESS);
assert(hTarget);
// allocate buffer for the DLL path name
void* pPathBuffer = ::VirtualAllocEx(pi.hProcess, nullptr, MAX_PATH * sizeof(WCHAR), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
assert(pPathBuffer);
// write the path
SIZE_T written;
::WriteProcessMemory(pi.hProcess, pPathBuffer, path, MAX_PATH * sizeof(WCHAR), &written);
// create a remote thread to load the DLL
HANDLE hRemoteThread = ::CreateRemoteThread(pi.hProcess, nullptr, 0,
(PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(L"kernel32"), "LoadLibraryW"),
pPathBuffer, 0, nullptr);
// allow the process to continue after this one exits
::DebugSetProcessKillOnExit(FALSE);
// close handles (not really needed as we're existing)
::CloseHandle(hRemoteThread);
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
::CloseHandle(hSemaphore);
}
return 0;
}
But I returned the following errors obviously for the arguments that I put them I have to read them .. using getcommandline from lpszCmdParam
, but I do not know very well, errors: