start a process in a .bat file but hide it? - windows

I would like to launch one of my apps inside a .bat file but it is visible and taking up space in my taskbar. How do i launch the app and not have it visible?

Here's a utility I wrote years ago to do this:
#include <windows.h>
#pragma comment(lib, "user32.lib")
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
const char *p = GetCommandLine();
if (*p == '"') {
p++;
while (*p && *p != '"') {
p++;
}
p++;
} else {
while (*p && *p != ' ') {
p++;
}
}
while (*p == ' ') {
p++;
}
if (*p == 0) {
MessageBox(NULL, "Usage: nocli <command>\nExecute <command> without a command prompt window.", "nocli Usage", MB_OK);
return 1;
}
//if (MessageBox(NULL, p, "nocli debug", MB_OKCANCEL) != IDOK) return 1;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
if (CreateProcess(NULL, const_cast<char *>(p), NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi)) {
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitcode;
GetExitCodeProcess(pi.hProcess, &exitcode);
CloseHandle(pi.hProcess);
return exitcode;
} else {
MessageBox(NULL, "Error executing command line", "nocli", MB_OK);
return 1;
}
return 0;
}
No guarantees, but it worked for me in one situation at one time. :)

Assuming you want to open an application and have the DOS prompt go away immediately, use start <command> in your .bat file instead of just <command>

If your not afraid to use Perl then this will do the trick
use Win32::GUI;
Win32::GUI::Hide(scalar(Win32::GUI::GetPerlWindow()));

Here I've compiled all ways that I know to start a hidden process with batch without external tools.With a ready to use scripts (some of them rich on options) , and all of them form command line.Where is possible also the PID is returned .Used tools are IEXPRESS,SCHTASKS,WScript.Shell,Win32_Process and JScript.Net - but all of them wrapped in a .bat files.

Related

ReadFile does not return while reading stdout from a child process after it ends

I am working on my library which needs to capture and process the standard output (and err) of a child process as it runs. The problem arises when ReadFile is used to read the output, it does not return once the process ends (gets killed or exits).
It looks like ReadFile is not able to detect that the other end of the pipe (the write handle) is closed. According to the documentation it should return FALSE and set the last error to ERROR_BROKEN_PIPE:
If an anonymous pipe is being used and the write handle has been closed, when ReadFile attempts to read using the pipe's corresponding read handle, the function returns FALSE and GetLastError returns ERROR_BROKEN_PIPE.
Here is my code, I have stripped out the irrelevant bits: (NOTE: I have updated the allium_start to follow the suggested changes, I am keeping the original for reference, please use the newer function code to find flaws)
bool allium_start(struct TorInstance *instance, char *config, allium_pipe *output_pipes) {
// Prepare startup info with appropriate information
SecureZeroMemory(&instance->startup_info, sizeof instance->startup_info);
instance->startup_info.dwFlags = STARTF_USESTDHANDLES;
SECURITY_ATTRIBUTES pipe_secu_attribs = {sizeof(SECURITY_ATTRIBUTES), NULL, true};
HANDLE pipes[2];
if (output_pipes == NULL) {
CreatePipe(&pipes[0], &pipes[1], &pipe_secu_attribs, 0);
output_pipes = pipes;
}
instance->startup_info.hStdOutput = output_pipes[1];
instance->startup_info.hStdError = output_pipes[1];
instance->stdout_pipe = output_pipes[0]; // Stored for internal reference
// Create the process
bool success = CreateProcessA(
NULL,
cmd,
NULL,
NULL,
config ? true : false,
0,
NULL,
NULL,
&instance->startup_info,
SecureZeroMemory(&instance->process, sizeof instance->process)
);
// Return on failure
if (!success) return false;
}
char *allium_read_stdout_line(struct TorInstance *instance) {
char *buffer = instance->buffer.data;
// Process the input
unsigned int read_len = 0;
while (true) {
// Read data
unsigned long bytes_read;
if (ReadFile(instance->stdout_pipe, buffer, 1, &bytes_read, NULL) == false || bytes_read == 0) return NULL;
// Check if we have reached end of line
if (buffer[0] == '\n') break;
// Proceed to the next character
++buffer; ++read_len;
}
// Terminate the new line with null character and return
// Special handling for Windows, terminate at CR if present
buffer[read_len >= 2 && buffer[-1] == '\r' ? -1 : 0] = '\0';
return instance->buffer.data;
}
The allium_start creates the pipe for output redirection (it uses the same pipe for both stdout and stderr to get merged streams) and then creates the child process. The other allium_read_stdout_line function is responsible for reading the output from the pipe and returning it when it encounters a new line.
The issue occurs at the ReadFile function call, it never returns if there is nothing to read after the process exits, from my understanding all the handles of a process are closed by Windows when it ends, so it looks like ReadFile is not able to detect the fact that the pipe (write handle) at the other end has been closed.
How do I fix this? I have been searching for a solution but I have found none so far, one potential option is to use multi-threading and put ReadFile in a separate thread so that it doesn't block the whole program, by using that method I can check if the process still exists periodically while I wait for the reading to finish... or kill/stop the thread if the process is gone.
I do prefer fixing the issue instead of opting for a workaround, but I am open to any other solutions to make it work. Thanks in advance!
Edit: After reading #RemyLebeau's answer and #RbMm's comments in that answer, it is pretty clear that my understand of how handle inheritance works is fundamentally flawed. So I incorporated their suggestions (SetHandleInformation to disable inheritance of read handle and closing it after creating the child process) into my allium_start function:
bool allium_start(struct TorInstance *instance, char *config, allium_pipe *output_pipes) {
// Prepare startup info with appropriate information
SecureZeroMemory(&instance->startup_info, sizeof instance->startup_info);
instance->startup_info.dwFlags = STARTF_USESTDHANDLES;
SECURITY_ATTRIBUTES pipe_secu_attribs = {sizeof(SECURITY_ATTRIBUTES), NULL, true};
HANDLE pipes[2];
if (output_pipes == NULL) {
CreatePipe(&pipes[0], &pipes[1], &pipe_secu_attribs, 0);
output_pipes = pipes;
}
SetHandleInformation(output_pipes[0], HANDLE_FLAG_INHERIT, 0);
instance->startup_info.hStdOutput = output_pipes[1];
instance->startup_info.hStdError = output_pipes[1];
instance->stdout_pipe = output_pipes[0]; // Stored for internal reference
// Create the process
bool success = CreateProcessA(
NULL,
cmd,
NULL,
NULL,
config ? true : false,
0,
NULL,
NULL,
&instance->startup_info,
SecureZeroMemory(&instance->process, sizeof instance->process)
);
// Close the write end of our stdout handle
CloseHandle(output_pipes[1]);
// Return on failure
if (!success) return false;
}
(The below text was originally here before edit 2)
But sadly it still doesn't work :(
Edit 2 (after accepting answer): It does work! See my last comment on the accepted answer.
You are not managing your pipes correctly, or more specifically, you are not controlling the inheritance of your pipe handles. DO NOT let the child process inherit the reading handle of your pipe (output_pipes[0]), otherwise the pipe will not break correctly when the child process ends.
Read MSDN for more details:
Creating a Child Process with Redirected Input and Output
The case of the redirected standard handles that won’t close even though the child process has exited
Use SetHandleInformation() or PROC_THREAD_ATTRIBUTE_LIST to prevent CreateProcess() from passing output_pipes[0] to the child process as an inheritable handle. The child process does not need access to that handle, so there is no need to pass it over the process boundary anyway. It only needs access to the writing handle of your pipe (output_pipes[1]).
For anonymous pipelines, the read process and the write process will have the handler of hRead and hWrite, each of process has its own handler(copy after inheritance). So after your child process exit and close the handler in it, anther hWrite still in parent process. We must pay attention to close hRead in the write process, close hWrite in the read process.
I can reproduce this ReadFile issue, and if closing write handler after setting child's hStdOutput and hStdError, the ReadFile will return 0 after the child process exit.
Here is my code sample,
Parent.cpp:
#include <windows.h>
#include <iostream>
#include <stdio.h>
HANDLE childInRead = NULL;
HANDLE W1 = NULL;
HANDLE W2 = NULL;
HANDLE R2 = NULL;
HANDLE R1 = NULL;
#define BUFSIZE 4096
void CreateChildProcess() {
TCHAR applicationName[] = TEXT("kids.exe");
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL success = FALSE;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdError = W1;
si.hStdOutput = W1;
si.hStdInput = R2;
si.dwFlags |= STARTF_USESTDHANDLES;
success = CreateProcess(NULL, applicationName, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
if (!success) {
printf("Error creating child process \n");
}
else {
printf("Child process successfuly created \n");
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
int main()
{
printf("Parent process running.... \n");
DWORD dRead, dWritten;
CHAR chBuf[BUFSIZE] = { 0 };
BOOL bSuccess = FALSE;
SECURITY_ATTRIBUTES secAttr;
secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
secAttr.bInheritHandle = TRUE;
secAttr.lpSecurityDescriptor = NULL;
printf("Creating first pipe \n");
if (!CreatePipe(&R1, &W1, &secAttr, 0)) {
printf("\n error creating first pipe \n");
}
printf("Creating second pipe \n");
if (!CreatePipe(&R2, &W2, &secAttr, 0)) {
printf("\n error creating second pipe \n");
}
if (!SetHandleInformation(R1, HANDLE_FLAG_INHERIT, 0)) {
printf("\n R1 SetHandleInformation \n");
}
if (!SetHandleInformation(W2, HANDLE_FLAG_INHERIT, 0)) {
printf("\n W1 SetHandleInformation \n");
}
printf("\n Creating child process..... \n");
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
CreateChildProcess();
CloseHandle(W1);
CloseHandle(R2);
for (;;) {
printf("Inside for loop \n");
//1. read from stdin
printf("read from stdin:\n");
bSuccess = ReadFile(hStdIn, chBuf, BUFSIZE, &dRead, NULL);
if (!bSuccess) {
printf("error reading \n");
break;
}
//2. write to Pipe2
printf("write to Pipe2...\n");
bSuccess = WriteFile(W2, chBuf, 100, &dWritten, NULL);
if (!bSuccess) {
printf("error reading \n");
break;
}
//3. read from Pipe1
printf("read from Pipe1...\n");
bSuccess = ReadFile(R1, chBuf, BUFSIZE, &dRead, NULL);
if (!bSuccess)
{
printf("error reading :%d \n", GetLastError());
break;
}
//4. write to stdout
printf("write to stdout:\n");
bSuccess = WriteFile(hStdOut, chBuf, 100, &dWritten, NULL);
if (!bSuccess) {
printf("error reading \n");
break;
}
}
getchar();
return 0;
}
Kids.cpp:
#include <windows.h>
#include <stdio.h>
#define BUFSIZE 4096
int main()
{
DWORD dRead, dWritten;
CHAR chBuf[BUFSIZE];
BOOL success = FALSE;
HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
printf("Child process running....");
if (stdIn == INVALID_HANDLE_VALUE || stdOut == INVALID_HANDLE_VALUE) {
ExitProcess(1);
}
//for (;;) {
success = ReadFile(stdIn, chBuf, BUFSIZE, &dRead, NULL);
//if (!success || dRead == 0) break;
success = WriteFile(stdOut, chBuf, dRead, &dWritten, NULL);
//if (!success) break;
//}
return 0;
}

Building simple unix shell problems

I am new with unix and I've got an assignemnt on college to build a simple shell in c with built in cd and kill command..
This is my code which is not working..tbh I dont understand it the best so Im not suprised it is not working.. can you help me with it? Also have no idea how I would implement kill command. thank you!
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
const int ARGSIZE = 20;
void execute(char*args[])
{
int pid, status;
pid = fork();
if(pid<0)
{
perror("Error forking!");
}
else if(pid > 0)
{
while(wait(&status) != pid)
continue;
}
else if(pid == 0)
{
if (execvp(args[0], args) == -1)
{
perror("Error");
}
}
}
void cd(char*directory)
{
int ret = 0;
if(directory == '\0')
directory = getenv("HOME");
ret = chdir(directory);
if(ret != 0)
fprintf(stderr,"Failed to enter directory: %s\n",directory);
else
printf("%s\n",directory);
}
int main()
{
char line[BUF_SIZE];
char *args[ARGSIZE];
int argIndex = 0;
while(1){
printf("> ");
fgets(line, BUF_SIZE, stdin);
char *token;
token = strtok(line," ");
while(token!=NULL)
{
args[argIndex]=token;
token = strtok(NULL," ");
argIndex++;
}
args[argIndex]=NULL;
if(strcmp(args[0], "quit") == 0 || strcmp(args[0], "exit") == 0)
break;
if(line== "\n")
printf("> ");
else if ((strcmp(args[0], "cd") == 0))
cd(args[1]);
else
execute(args);
}
return 0;
}
You were on the right track. There were a few subtle issues where you were not accounting for the trailing '\n' that would remain in line as the last character following whatever was entered at the prompt. Including " \n" in the delimiters used to tokenize the input with strtok will remove it, allowing valid strcmp comparisons with the final token (e.g. that is why quit and exit would not quit the application).
Other than than, there were several additional things you could do a little different/better, you could handle directories entered as e.g. '~/somedir', and similar additional checks that could be employed. I have notated most below as comments to the code.
Look over the changes below and let me know if you have any questions. There are always additional checks that can be added, etc.., but on balance your approach to the problem was pretty good. (note: some of the changes made were non-substantive, e.g. "shell> " as the prompt, instead of "> ". Just handle any of those as you wish.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
enum {ARGSIZE = 20, BUF_SIZE = 1024};
void execute (char **args);
void cd (char *directory);
int killpid (char *pitstr, int sig);
int main (void)
{
char line[BUF_SIZE] = {0};
char *args[ARGSIZE] = {NULL};
char *token;
int i, argIndex = 0;
while (1) {
argIndex = 0; /* reinitialize variables */
for (i = 0; i < ARGSIZE; i++)
args[i] = NULL;
printf ("shell> "); /* prompt */
if (fgets (line, BUF_SIZE, stdin) == NULL) {
printf ("EOF received\n");
return 0;
}
if (*line == '\n') /* Enter alone */
continue;
token = strtok (line, " \n"); /* add \n to delimiters */
while (token != NULL) {
args[argIndex] = token;
token = strtok (NULL, " \n");
argIndex++;
}
if (!argIndex) continue; /* validate at least 1 arg */
if (strcmp (args[0], "quit") == 0 || strcmp (args[0], "exit") == 0)
break;
/* handle 'cd' or 'kill' separately */
if ((strcmp (args[0], "cd") == 0))
cd (args[1]);
else if ((strcmp (args[0], "kill") == 0)) {
if (args[1]) killpid (args[1], SIGTERM);
}
else
execute (args);
}
return 0;
}
void execute (char **args)
{
int pid, status;
pid = fork ();
if (pid < 0) {
perror ("Error forking!");
return;
}
else if (pid > 0) {
while (wait (&status) != pid)
continue;
}
else if (pid == 0) {
if (execvp (args[0], args) == -1) {
perror ("Error");
}
_exit (EXIT_FAILURE);
}
}
void cd (char *directory)
{
char dir[BUF_SIZE] = {0};
if (!directory) { /* handle 'cd' */
directory = getenv ("HOME");
if (chdir (directory))
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
return;
}
if (*directory == '~') { /* handle cd ~/stuff */
strcpy (dir, getenv ("HOME"));
strcat (dir, "/");
strcat (dir, directory + 2);
if (chdir (dir))
fprintf (stderr, "Failed to enter directory: %s\n", dir);
else
printf ("%s\n", dir);
return;
}
if (chdir (directory)) /* handle given directory */
fprintf (stderr, "Failed to enter directory: %s\n", directory);
else
printf ("%s\n", directory);
}
int killpid (char *pidstr, int sig)
{
pid_t pid = (pid_t)atoi (pidstr);
if (pid < 1) {
fprintf (stderr, "warning: requested pid < 1, ignoring\n");
return (int)pid;
}
printf (" killing pid '%d' with signal '%d'\n", (int)pid, sig);
// return kill (pid, sig);
return 0;
}
Sample Usage/Output
$ ./bin/ushell
shell> cd
/home/david
shell> cd ~/tmp
/home/david/tmp
shell> kill 18004
killing pid '18004' with signal '15'
shell>
shell> quit

How to read a file using readfile on Winapi

I'm learning how to use in Winapi
And I'm trying to read a file from My Computer
But for some reason it doesn't work ...
HANDLE hFile;
//PVOID First_Bytes[2048];
char First_Bytes[2048];
DWORD dbr = 0;
hFile = CreateFile(L"d:\\My-File",GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL , NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("Error %x", GetLastError());
return 1;
}
if (ReadFile(hFile, &First_Bytes, 512, &dbr, NULL) == 0) {
printf("ReadFile error: %x", GetLastError());
return 1;
}
printf("%s", First_Bytes);
CloseHandle(hFile);
The console doesn't print anything.
What am I doing wrong?
I edited the code and add that errors checks.
But still consul does not print anything
The logical conclusion is that the first byte in your file is a zero. You treat the buffer as a null-terminated string, and so nothing is printed.
Do note that there is no guarantee that your buffer is null terminated so you potentially have undefined behaviour.

Win32 ReadFile hangs when reading from pipe

I am creating a child process, and reading its output. My code works fine when the child process creates output (cmd /c echo Hello World), however ReadFile will hang if process does not create output (cmd /c echo Hello World > output.txt). I am only reading after the process has terminated.
Am I doing something horribly wrong? Is there anyway to do this with synchronous mode, or do I have to use asynchronous mode? All of this is happening in a seperate thread, so I dont think asynchronous mode would offer any benefit to me, unless it is the only way to get this to work. Thanks a lot!
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0);
SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0);
memset(&piProcInfo, 0, sizeof(PROCESS_INFORMATION));
memset(&siStartInfo, 0, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = g_hChildStd_OUT_Wr;
siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess(NULL, commandWideString, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo);
while(1)
{
GetExitCodeProcess(piProcInfo.hProcess, &processExitCode);
if(processExitCode != STILL_ACTIVE)
break;
else
Sleep(1);
}
*output = (char *)calloc(32, sizeof(char));
processOutputSize = 0;
while(1)
{
bSuccess = ReadFile( g_hChildStd_OUT_Rd, processOutputTemp, 32, &dwRead, NULL);
if(!bSuccess || !dwRead)
break;
memcpy(*output + processOutputSize, processOutputTemp, dwRead);
processOutputSize += dwRead;
if(dwRead == 32)
*output = (char *)realloc(*output, processOutputSize + 32);
else
{
memset(*output + processOutputSize, 0, 1);
break;
}
}
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
CloseHandle(g_hChildStd_OUT_Rd);
CloseHandle(g_hChildStd_OUT_Wr);
You should close the write end of the output pipe before you read from it, as #Marcus suggested in the comment.
CloseHandle(g_hChildStd_OUT_Wr);
For me this is the real answer.
You redirect the output of the process to a pipe, start the process, wait till it exits, and then read the output.
The problem is that windows buffers just a limited amount of data. So you must read the pipe while the process is still running, otherwise the process will be blocked because it cannot write any more data to the pipe.
You could use PeekNamedPipe in a loop like this:
for (;;)
{
DWORD bytesAvail = 0;
if (!PeekNamedPipe(stdoutPipeRead, NULL, 0, NULL, &bytesAvail, NULL)) {
std::cout << "Failed to call PeekNamedPipe" << std::endl;
}
if (bytesAvail) {
CHAR buf[BUFSIZE];
DWORD n;
BOOL success = ReadFile(stdoutPipeRead, buf, BUFSIZE, &n, NULL);
if (!success || n == 0) {
std::cout << "Failed to call ReadFile" << std::endl;
}
std::cout << std::string(buf, buf + n);
}
}

CreateRemoteThread returning ERROR_ACCESS_DENIED - Windows 7 DLL Injection

I'm trying to write a program that uses CreateRemoteThread to inject a dll.
The problem is that CreateRemoteThread is refusing to work. GetLastError() is returning 5 which is ERROR_ACCESS_DENIED. I cant figure why!
I am working from this video http://www.youtube.com/watch?v=H3O3hmXkt1I .
#include <iostream>
#include <direct.h>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
char* GetCurrentDir()
{
char* szRet = (char*)malloc(MAX_PATH);
_getcwd(szRet, MAX_PATH);
return szRet;
}
LPCTSTR SzToLPCTSTR(char* szString)
{
LPTSTR lpszRet;
size_t size = strlen(szString)+1;
lpszRet = (LPTSTR)malloc(MAX_PATH);
mbstowcs_s(NULL, lpszRet, size, szString, _TRUNCATE);
return lpszRet;
}
void WaitForProcessToAppear(LPCTSTR lpcszProc, DWORD dwDelay)
{
HANDLE hSnap;
PROCESSENTRY32 peProc;
BOOL bAppeared = FALSE;
while(!bAppeared)
{
if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
{
peProc.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hSnap, &peProc))
while(Process32Next(hSnap, &peProc) && !bAppeared)
if(!lstrcmp(lpcszProc, peProc.szExeFile))
bAppeared = TRUE;
}
CloseHandle(hSnap);
Sleep(dwDelay);
}
}
DWORD GetProcessIdByName(LPCTSTR lpcszProc)
{
HANDLE hSnap;
PROCESSENTRY32 peProc;
DWORD dwRet = -1;
if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
{
peProc.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hSnap, &peProc))
while(Process32Next(hSnap, &peProc))
if(!lstrcmp(lpcszProc, peProc.szExeFile))
dwRet = peProc.th32ProcessID;
}
CloseHandle(hSnap);
return dwRet;
}
BOOL InjectDll(DWORD dwPid, char* szDllPath)
{
DWORD dwMemSize;
HANDLE hProc;
LPVOID lpRemoteMem, lpLoadLibrary;
BOOL bRet = FALSE;
if((hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) != NULL)
{
dwMemSize = strlen(szDllPath);
if((lpRemoteMem = VirtualAllocEx(hProc, NULL, dwMemSize, MEM_COMMIT, PAGE_READWRITE)) != NULL)
if(WriteProcessMemory(hProc, lpRemoteMem, szDllPath, dwMemSize, NULL))
{
lpLoadLibrary = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");
if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibrary, lpRemoteMem, 0, NULL) != NULL)
{
bRet = TRUE;
}
cout << GetLastError();
}
}
CloseHandle(hProc);
return bRet;
}
int main()
{
char szProc[MAX_PATH], szDll[MAX_PATH];
char* szDllPath = (char*)malloc(MAX_PATH);
LPTSTR lpszProc = NULL;
for(;;)
{
cout << "Process: ";
cin >> szProc;
cout << "DLL: ";
cin >> szDll;
szDllPath = GetCurrentDir();
strcat_s(szDllPath, MAX_PATH, "\\");
strcat_s(szDllPath, MAX_PATH, szDll);
cout << "Waiting for process.. ." << szDllPath << " " << szDll << endl;
WaitForProcessToAppear(SzToLPCTSTR(szProc), 100);
if(InjectDll(GetProcessIdByName(SzToLPCTSTR(szProc)), szDllPath))
cout << "Injection Succeeded!" << endl;
else
cout << "Injection Failed!" << endl;
cout << "\n";
}
return 0;
After a fair amount of googling I cant find a reason why this should not be working.
Does CreateRemoteThread not work under Windows 7 ?
If it does, have I made any obvious mistakes ?
The reason it fails is because your code is 32-bit and your target process is 64-bit.
It doesn't matter how many privileges you own. Windows won't let that happen.
I had the same problem. Either you spawn a system 32-bit exe and inject that or port your code to 64-bit (which means it won't work on 32-bit systems).
EDIT
A long time ago, I found a nice way of injecting code into and from any processor mode-target. It involves dynamically switching the processor mode to that of (any)the target. Dubbed "heaven's gate". To do this you have to use inline assembly. So basically, you can have both 64-bit and 32-bit code in a 32-bit exe, detect if the machine is 64-bit, then jump into 64-bit mode and run the 64-bit code. You'd then walk the imports to find ntdll and load 64-bit kernel.dll and other libraries.
Link: https://www.google.com/search?q=heaven's+gate+windows
Immediate problems I see are that you are not getting the access token which should be done as so:
HANDLE hToken;
TOKEN_PRIVILEGES tp;
HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId() );
tp.PrivilegeCount = 1;
LookupPrivilegeValue( NULL, _T("SeDebugPrivilege"), &tp.Privileges[0].Luid );
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
OpenProcessToken( hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken );
AdjustTokenPrivileges( hToken, FALSE, &tp, NULL, NULL, NULL );
CloseHandle( hToken );
I don't have time to look through all your code right now, but here is something I ripped out of one of my previous projects:
// returns open process handle
HANDLE InjectDLL( DWORD dwPID, LPCWSTR szDLLPath, HMODULE* lphInjected ) {
int cszDLL;
LPVOID lpAddress;
HMODULE hMod;
HANDLE hThread;
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD |
PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID );
if( hProcess == NULL ) {
return NULL;
}
cszDLL = ( wcslen( szDLLPath ) + 1 ) * sizeof( WCHAR );
// Injection
lpAddress = VirtualAllocEx( hProcess, NULL, cszDLL, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
if( lpAddress == NULL ) {
return NULL;
}
WriteProcessMemory( hProcess, lpAddress, szDLLPath, cszDLL, NULL );
hMod = GetModuleHandle( L"kernel32.dll" );
if( hMod == NULL ) {
return NULL;
}
hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)( GetProcAddress( hMod,
"LoadLibraryW" ) ), lpAddress, 0, NULL );
// Locate address our payload was loaded
if( hThread != 0 ) {
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, ( LPDWORD )lphInjected );
VirtualFreeEx( hProcess, lpAddress, 0, MEM_RELEASE );
CloseHandle( hThread );
}
return hThread != 0 ? hProcess : NULL;
}
See if it helps. Will look again later.
OK, your code is likely to fail in windows 7 and Vista because of "Protected processes", that is, processes which only can be manipulated by other Protected Processes, like explorer.exe, etc... In Windows 7 x32 there is a way: since you are able to load unsigned drivers,... well, you are done (search for Alex Ionescu in google). In Windows 7 x64, though, you can't (duh!)
"The fourth parameter of the CreateRemoteThread() is an address. In your case it is the LoadLibraryA address. However, in windows 7, Kernel32.dll/LoadLibraryA base address will various in different process;"
Well, that's not remotely true, because DLLs are shared at the same addresses in every process, despite ASLR. DLLs can be rebased, though, but you can call GetProcAddress before calling CreateRemoteThread, so it is very unlikely that the DLL will get rebased meanwhile.
I think CreateRemoteThread() dll injection method can not work in windows 7.
The fourth parameter of the CreateRemoteThread() is an address. In your case it is the LoadLibraryA address. However, in windows 7, Kernel32.dll/LoadLibraryA base address will various in different process; Therefore, the CreateRemoteThread() will not work since the address is not what u expected. This is my own opinion, hope it will help. :)
CreateRemoteThread function does not work in Win Vista/7. You have to use NTCreateThread function,which is undocumented, for that.
TLDR : your code is okey , change the Visual Studio debug/compile target to x64.
I've faced the same problem before, your code is Okey, The problem is , the Visual Studio(or any sane person) execute its programs in x86 mode (32bit) by default, because it would be nice to compile your program in a way that runs in both x86 or x64 architecture but not in the process injection scenario! because of its system calls.
In the code injection case, you should change the build and debug setting of the VS to compile/debug for x64 processor in properties of your project in the project explorer,
or if you cross compiling your program, you should use x64 compiler.
If you are looking for global process injection method, there was a method called Heaven’s Gate or The 0x33 Segment Selector, which was used in Vawtrak banking malware.
You could see this link about Heaven’s Gate method, which says:
In other words, it gives one the ability to create “naked” 64-bit
code, which will be able to run covertly, including issuing system
calls, without the majority of products able to intercept and/or
introspect its execution

Resources