X-Git-Url: https://git.sven.stormbind.net/?p=sven%2Fjattach.git;a=blobdiff_plain;f=src%2Fwindows%2Fjattach.c;h=1318a94541a2ef6706bde4d361cc81c4d28385f3;hp=b43e2f875e2aeaef9f692c4282859ee7e0ce5652;hb=HEAD;hpb=54ba80f2c210c8003b4ab5c7112ab64063ee8212 diff --git a/src/windows/jattach.c b/src/windows/jattach.c index b43e2f8..f25f1d6 100644 --- a/src/windows/jattach.c +++ b/src/windows/jattach.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 Andrei Pangin + * Copyright jattach authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,8 @@ #include #include -#include +#include +#include typedef HMODULE (WINAPI *GetModuleHandle_t)(LPCTSTR lpModuleName); typedef FARPROC (WINAPI *GetProcAddress_t)(HMODULE hModule, LPCSTR lpProcName); @@ -84,10 +85,19 @@ static LPVOID allocate_data(HANDLE hProcess, char* pipeName, int argc, char** ar strcpy(data.strJvm, "jvm"); strcpy(data.strEnqueue, "_JVM_EnqueueOperation"); strcpy(data.pipeName, pipeName); + data.args[0][0] = data.args[1][0] = data.args[2][0] = data.args[3][0] = 0; + // jcmd has 2 arguments maximum; merge excessive arguments into one + int cmd_args = argc >= 2 && strcmp(argv[0], "jcmd") == 0 ? 2 : argc >= 4 ? 4 : argc; + + size_t n = 0; int i; - for (i = 0; i < 4; i++) { - strcpy(data.args[i], i < argc ? argv[i] : ""); + for (i = 0; i < argc; i++) { + if (i < cmd_args) { + n = snprintf(data.args[i], sizeof(data.args[i]), "%s", argv[i]); + } else if (n < sizeof(data.args[cmd_args - 1])) { + n += snprintf(data.args[cmd_args - 1] + n, sizeof(data.args[cmd_args - 1]) - n, " %s", argv[i]); + } } LPVOID remoteData = VirtualAllocEx(hProcess, NULL, sizeof(CallData), MEM_COMMIT, PAGE_READWRITE); @@ -202,7 +212,7 @@ static int inject_thread(int pid, char* pipeName, int argc, char** argv) { } // JVM response is read from the pipe and mirrored to stdout -static int read_response(HANDLE hPipe) { +static int read_response(HANDLE hPipe, int print_output) { ConnectNamedPipe(hPipe, NULL); char buf[8192]; @@ -216,17 +226,54 @@ static int read_response(HANDLE hPipe) { buf[bytesRead] = 0; int result = atoi(buf); - do { - fwrite(buf, 1, bytesRead, stdout); - } while (ReadFile(hPipe, buf, sizeof(buf), &bytesRead, NULL)); + if (print_output) { + // Mirror JVM response to stdout + printf("JVM response code = "); + do { + fwrite(buf, 1, bytesRead, stdout); + } while (ReadFile(hPipe, buf, sizeof(buf), &bytesRead, NULL)); + printf("\n"); + } return result; } +int jattach(int pid, int argc, char** argv, int print_output) { + // When attaching as an Administrator, make sure the target process can connect to our pipe, + // i.e. allow read-write access to everyone. For the complete format description, see + // https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format + SECURITY_ATTRIBUTES sec = {sizeof(SECURITY_ATTRIBUTES), NULL, FALSE}; + ConvertStringSecurityDescriptorToSecurityDescriptor("D:(A;;GRGW;;;WD)", SDDL_REVISION_1, + &sec.lpSecurityDescriptor, NULL); + + char pipeName[MAX_PATH]; + sprintf(pipeName, "\\\\.\\pipe\\javatool%d", GetTickCount()); + HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, + 1, 4096, 8192, NMPWAIT_USE_DEFAULT_WAIT, &sec); + if (hPipe == INVALID_HANDLE_VALUE) { + print_error("Could not create pipe", GetLastError()); + LocalFree(sec.lpSecurityDescriptor); + return 1; + } + + LocalFree(sec.lpSecurityDescriptor); + + if (!inject_thread(pid, pipeName, argc, argv)) { + CloseHandle(hPipe); + return 1; + } + + int result = read_response(hPipe, print_output); + CloseHandle(hPipe); + + return result; +} + +#ifdef JATTACH_VERSION + int main(int argc, char** argv) { if (argc < 3) { printf("jattach " JATTACH_VERSION " built on " __DATE__ "\n" - "Copyright 2021 Andrei Pangin\n" "\n" "Usage: jattach [args ...]\n" "\n" @@ -238,27 +285,12 @@ int main(int argc, char** argv) { } int pid = atoi(argv[1]); - - char pipeName[MAX_PATH]; - sprintf(pipeName, "\\\\.\\pipe\\javatool%d", GetTickCount()); - HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, - 1, 4096, 8192, NMPWAIT_USE_DEFAULT_WAIT, NULL); - if (hPipe == NULL) { - print_error("Could not create pipe", GetLastError()); + if (pid <= 0) { + fprintf(stderr, "%s is not a valid process ID\n", argv[1]); return 1; } - if (!inject_thread(pid, pipeName, argc - 2, argv + 2)) { - CloseHandle(hPipe); - return 1; - } - - printf("Response code = "); - fflush(stdout); - - int result = read_response(hPipe); - printf("\n"); - CloseHandle(hPipe); - - return result; + return jattach(pid, argc - 2, argv + 2, 1); } + +#endif // JATTACH_VERSION