/*
 * Class:     sun_tools_attach_WindowsVirtualMachine
 * Method:    createPipe
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_tools_attach_WindowsVirtualMachine_createPipe
  (JNIEnv *env, jclass cls, jstring pipename)
{
    HANDLE hPipe;
    char name[MAX_PIPE_NAME_LENGTH];

    jstring_to_cstring(env, pipename, name, MAX_PIPE_NAME_LENGTH);

    hPipe = CreateNamedPipe(
          name,                         // pipe name
          PIPE_ACCESS_INBOUND,          // read access
          PIPE_TYPE_BYTE |              // byte mode
            PIPE_READMODE_BYTE |
            PIPE_WAIT,                  // blocking mode
          1,                            // max. instances
          128,                          // output buffer size
          8192,                         // input buffer size
          NMPWAIT_USE_DEFAULT_WAIT,     // client time-out
          NULL);                        // default security attribute

    if (hPipe == INVALID_HANDLE_VALUE) {
        JNU_ThrowIOExceptionWithLastError(env, "CreateNamedPipe failed");
    }
    return (jlong)hPipe;
}
Пример #2
0
/*
 * Class:     sun_tools_attach_VirtualMachineImpl
 * Method:    createPipe
 * Signature: (Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_sun_tools_attach_VirtualMachineImpl_createPipe
  (JNIEnv *env, jclass cls, jstring pipename)
{
    HANDLE hPipe;
    char name[MAX_PIPE_NAME_LENGTH];

    SECURITY_ATTRIBUTES sa;
    LPSECURITY_ATTRIBUTES lpSA = NULL;
    // Custom Security Descriptor is required here to "get" Medium Integrity Level.
    // In order to allow Medium Integrity Level clients to open
    // and use a NamedPipe created by an High Integrity Level process.
    TCHAR *szSD = TEXT("D:")                  // Discretionary ACL
                  TEXT("(A;OICI;GRGW;;;WD)")  // Allow read/write to Everybody
                  TEXT("(A;OICI;GA;;;SY)")    // Allow full control to System
                  TEXT("(A;OICI;GA;;;BA)");   // Allow full control to Administrators

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = FALSE;
    sa.lpSecurityDescriptor = NULL;

    if (ConvertStringSecurityDescriptorToSecurityDescriptor
          (szSD, SDDL_REVISION_1, &(sa.lpSecurityDescriptor), NULL)) {
        lpSA = &sa;
    }

    jstring_to_cstring(env, pipename, name, MAX_PIPE_NAME_LENGTH);

    hPipe = CreateNamedPipe(
          name,                         // pipe name
          PIPE_ACCESS_INBOUND,          // read access
          PIPE_TYPE_BYTE |              // byte mode
            PIPE_READMODE_BYTE |
            PIPE_WAIT,                  // blocking mode
          1,                            // max. instances
          128,                          // output buffer size
          8192,                         // input buffer size
          NMPWAIT_USE_DEFAULT_WAIT,     // client time-out
          lpSA);        // security attributes

    LocalFree(sa.lpSecurityDescriptor);

    if (hPipe == INVALID_HANDLE_VALUE) {
        char msg[256];
        _snprintf(msg, sizeof(msg), "CreateNamedPipe failed: %d", GetLastError());
        JNU_ThrowIOExceptionWithLastError(env, msg);
    }
    return (jlong)hPipe;
}
/*
 * Class:     sun_tools_attach_WindowsVirtualMachine
 * Method:    enqueue
 * Signature: (JZLjava/lang/String;[Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL Java_sun_tools_attach_WindowsVirtualMachine_enqueue
  (JNIEnv *env, jclass cls, jlong handle, jbyteArray stub, jstring cmd,
   jstring pipename, jobjectArray args)
{
    DataBlock data;
    DataBlock* pData;
    DWORD* pCode;
    DWORD numBytes;
    DWORD stubLen;
    HANDLE hProcess, hThread;
    jint argsLen, i;
    jbyte* stubCode;
    jboolean isCopy;

    /*
     * Setup data to copy to target process
     */
    data._LoadLibrary = _LoadLibrary;
    data._GetProcAddress = _GetProcAddress;

    strcpy(data.jvmLib, "jvm");
    strcpy(data.func1, "JVM_EnqueueOperation");
    strcpy(data.func2, "_JVM_EnqueueOperation@20");

    /*
     * Command and arguments
     */
    jstring_to_cstring(env, cmd, data.cmd, MAX_CMD_LENGTH);
    argsLen = (*env)->GetArrayLength(env, args);

    if (argsLen > 0) {
        if (argsLen > MAX_ARGS) {
            JNU_ThrowInternalError(env, "Too many arguments");
        }
        for (i=0; i<argsLen; i++) {
            jobject obj = (*env)->GetObjectArrayElement(env, args, i);
            if (obj == NULL) {
                data.arg[i][0] = '\0';
            } else {
                jstring_to_cstring(env, obj, data.arg[i], MAX_ARG_LENGTH);
            }
            if ((*env)->ExceptionOccurred(env)) return;
        }
    }
    for (i=argsLen; i<MAX_ARGS; i++) {
        data.arg[i][0] = '\0';
    }

    /* pipe name */
    jstring_to_cstring(env, pipename, data.pipename, MAX_PIPE_NAME_LENGTH);

    /*
     * Allocate memory in target process for data and code stub
     * (assumed aligned and matches architecture of target process)
     */
    hProcess = (HANDLE)handle;

    pData = (DataBlock*) VirtualAllocEx( hProcess, 0, sizeof(DataBlock), MEM_COMMIT, PAGE_READWRITE );
    if (pData == NULL) {
        JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed");
        return;
    }
    WriteProcessMemory( hProcess, (LPVOID)pData, (LPVOID)&data, (DWORD)sizeof(DataBlock), &numBytes );


    stubLen = (DWORD)(*env)->GetArrayLength(env, stub);
    stubCode = (*env)->GetByteArrayElements(env, stub, &isCopy);

    pCode = (PDWORD) VirtualAllocEx( hProcess, 0, stubLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
    if (pCode == NULL) {
        JNU_ThrowIOExceptionWithLastError(env, "VirtualAllocEx failed");
        VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE);
        return;
    }
    WriteProcessMemory( hProcess, (LPVOID)pCode, (LPVOID)stubCode, (DWORD)stubLen, &numBytes );
    if (isCopy) {
        (*env)->ReleaseByteArrayElements(env, stub, stubCode, JNI_ABORT);
    }

    /*
     * Create thread in target process to execute code
     */
    hThread = CreateRemoteThread( hProcess,
                                  NULL,
                                  0,
                                  (LPTHREAD_START_ROUTINE) pCode,
                                  pData,
                                  0,
                                  NULL );
    if (hThread != NULL) {
        if (WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0) {
            JNU_ThrowIOExceptionWithLastError(env, "WaitForSingleObject failed");
        } else {
            DWORD exitCode;
            GetExitCodeThread(hThread, &exitCode);
            if (exitCode) {
                switch (exitCode) {
                    case ERR_OPEN_JVM_FAIL :
                        JNU_ThrowIOException(env,
                            "jvm.dll not loaded by target process");
                        break;
                    case ERR_GET_ENQUEUE_FUNC_FAIL :
                        JNU_ThrowIOException(env,
                            "Unable to enqueue operation: the target VM does not support attach mechanism");
                        break;
                    default :
                        JNU_ThrowInternalError(env,
                            "Remote thread failed for unknown reason");
                }
            }
        }
        CloseHandle(hThread);
    } else {
        JNU_ThrowIOExceptionWithLastError(env, "CreateRemoteThread failed");
    }

    VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
    VirtualFreeEx(hProcess, pData, 0, MEM_RELEASE);
}