void GraphicsCaptureSource::AttemptCapture()
{
    //Log(TEXT("attempting to capture.."));

    if (!bUseHotkey)
        hwndTarget = FindWindow(strWindowClass, NULL);
    else
    {
        hwndTarget = hwndNextTarget;
        hwndNextTarget = NULL;
    }

    if (hwndTarget)
    {
        GetWindowThreadProcessId(hwndTarget, &targetProcessID);
        if(!targetProcessID)
        {
            AppWarning(TEXT("GraphicsCaptureSource::BeginScene: GetWindowThreadProcessId failed, GetLastError = %u"), GetLastError());
            bErrorAcquiring = true;
            return;
        }
    }
    else
    {
        if (!bUseHotkey && !warningID)
            warningID = API->AddStreamInfo(Str("Sources.SoftwareCaptureSource.WindowNotFound"), StreamInfoPriority_High);

        bCapturing = false;

        return;
    }

    if(warningID)
    {
        API->RemoveStreamInfo(warningID);
        warningID = 0;
    }

    //-------------------------------------------
    // see if we already hooked the process.  if not, inject DLL

    char pOPStr[12];
    mcpy(pOPStr, "NpflUvhel{x", 12); //OpenProcess obfuscated
    for (int i=0; i<11; i++) pOPStr[i] ^= i^1;

    OPPROC pOpenProcess = (OPPROC)GetProcAddress(GetModuleHandle(TEXT("KERNEL32")), pOPStr);

    HANDLE hProcess = (*pOpenProcess)(PROCESS_ALL_ACCESS, FALSE, targetProcessID);
    if(hProcess)
    {
        //-------------------------------------------
        // load keepalive event

        hOBSIsAlive = CreateEvent(NULL, FALSE, FALSE, String() << OBS_KEEPALIVE_EVENT << UINT(targetProcessID));

        //-------------------------------------------

        hwndCapture = hwndTarget;

        hSignalRestart = OpenEvent(EVENT_ALL_ACCESS, FALSE, String() << RESTART_CAPTURE_EVENT << UINT(targetProcessID));
        if(hSignalRestart)
        {
            SetEvent(hSignalRestart);
            bCapturing = true;
            captureWaitCount = 0;
        }
        else
        {
            BOOL bSameBit = TRUE;

            if(Is64BitWindows())
            {
                BOOL bCurrentProcessWow64, bTargetProcessWow64;
                IsWow64Process(GetCurrentProcess(), &bCurrentProcessWow64);
                IsWow64Process(hProcess, &bTargetProcessWow64);

                bSameBit = (bCurrentProcessWow64 == bTargetProcessWow64);
            }

            if(bSameBit)
            {
                String strDLL;
                DWORD dwDirSize = GetCurrentDirectory(0, NULL);
                strDLL.SetLength(dwDirSize);
                GetCurrentDirectory(dwDirSize, strDLL);

                strDLL << TEXT("\\plugins\\GraphicsCapture\\GraphicsCaptureHook");

                BOOL b32bit = TRUE;
                if(Is64BitWindows())
                    IsWow64Process(hProcess, &b32bit);

                if(!b32bit)
                    strDLL << TEXT("64");

                strDLL << TEXT(".dll");

                if(InjectLibrary(hProcess, strDLL))
                {
                    captureWaitCount = 0;
                    bCapturing = true;
                }
                else
                {
                    AppWarning(TEXT("GraphicsCaptureSource::BeginScene: Failed to inject library, GetLastError = %u"), GetLastError());

                    CloseHandle(hProcess);
                    hProcess = NULL;
                    bErrorAcquiring = true;
                }
            }
            else
            {
                String strDLLPath;
                DWORD dwDirSize = GetCurrentDirectory(0, NULL);
                strDLLPath.SetLength(dwDirSize);
                GetCurrentDirectory(dwDirSize, strDLLPath);

                strDLLPath << TEXT("\\plugins\\GraphicsCapture");

                BOOL b32bit = TRUE;
                if(Is64BitWindows())
                    IsWow64Process(hProcess, &b32bit);

                String strHelper = strDLLPath;
                strHelper << ((b32bit) ? TEXT("\\injectHelper.exe") : TEXT("\\injectHelper64.exe"));

                String strCommandLine;
                strCommandLine << TEXT("\"") << strHelper << TEXT("\" ") << UIntString(targetProcessID);

                //---------------------------------------

                PROCESS_INFORMATION pi;
                STARTUPINFO si;

                zero(&pi, sizeof(pi));
                zero(&si, sizeof(si));
                si.cb = sizeof(si);

                if(CreateProcess(strHelper, strCommandLine, NULL, NULL, FALSE, 0, NULL, strDLLPath, &si, &pi))
                {
                    int exitCode = 0;

                    WaitForSingleObject(pi.hProcess, INFINITE);
                    GetExitCodeProcess(pi.hProcess, (DWORD*)&exitCode);
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);

                    if(exitCode == 0)
                    {
                        captureWaitCount = 0;
                        bCapturing = true;
                    }
                    else
                    {
                        AppWarning(TEXT("GraphicsCaptureSource::BeginScene: Failed to inject library, error code = %d"), exitCode);
                        bErrorAcquiring = true;
                    }
                }
                else
                {
                    AppWarning(TEXT("GraphicsCaptureSource::BeginScene: Could not create inject helper, GetLastError = %u"), GetLastError());
                    bErrorAcquiring = true;
                }
            }
        }

        CloseHandle(hProcess);
        hProcess = NULL;

        if (!bCapturing)
        {
            CloseHandle(hOBSIsAlive);
            hOBSIsAlive = NULL;
        }
    }
    else
    {
        AppWarning(TEXT("GraphicsCaptureSource::BeginScene: OpenProcess failed, GetLastError = %u"), GetLastError());
        bErrorAcquiring = true;
    }
}
Beispiel #2
0
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nShowCmd)
{
    LPWSTR pCommandLineW = GetCommandLineW();
    int retVal = 0;
    DWORD procID = 0;
    int numArgs = 0;

#ifdef _WIN64
    const wchar_t pDLLName[] = L"GraphicsCaptureHook64.dll";
#else
    const wchar_t pDLLName[] = L"GraphicsCaptureHook.dll";
#endif

    /* -------------------------- */

    LPWSTR *pCommandLineArgs = CommandLineToArgvW(pCommandLineW, &numArgs);

    LoadSeDebugPrivilege();

    if (numArgs > 1)
    {
        procID = wcstoul(pCommandLineArgs[1], NULL, 10);
        if (procID != 0)
        {
            OPPROC pOpenProcess;
            HANDLE hProcess;
            char pOPStr[12];
            int i;

            memcpy(pOPStr, "NpflUvhel{x", 12); //OpenProcess obfuscated
            for (i=0; i<11; i++) pOPStr[i] ^= i^1;

            pOpenProcess = (OPPROC)GetProcAddress(GetModuleHandle(TEXT("KERNEL32")), pOPStr);

            hProcess = (*pOpenProcess)(PROCESS_ALL_ACCESS, FALSE, procID);
            if (hProcess)
            {
                UINT dirLen = GetCurrentDirectory(0, 0); /* includes null terminator */
                const UINT fileNameLen = (sizeof(pDLLName) / sizeof(wchar_t))-1;
                UINT len = dirLen + fileNameLen + 1; /* 1 for '/' */
                wchar_t *pPath;

                /* -------------------------- */

                if (dirLen)
                {
                    pPath = (wchar_t*)malloc(len * sizeof(wchar_t));
                    memset(pPath, 0, len * sizeof(wchar_t));

                    GetCurrentDirectoryW(dirLen, pPath);
                    pPath[dirLen-1] = '\\';
                    wcsncpy_s(pPath+dirLen, len-dirLen, pDLLName, fileNameLen);

                    if(!InjectLibrary(hProcess, pPath, len-1))
                    {
                        retVal = GetLastError();
                        if(!retVal)
                            retVal = -5;
                    }

                    free(pPath);
                }
                else
                    retVal = -4;

                CloseHandle(hProcess);
            }
            else
                retVal = -3;
        }
        else
            retVal = -2;
    }
    else
        retVal = -1;

    LocalFree(pCommandLineArgs);

    return retVal;
}
Beispiel #3
0
int Main(int argc, char const * const argv[], char const * const envp[]) {
    _aprcall(apr_initialize());

    apr_pool_t *pool;
    apr_pool_create(&pool, NULL);

    bool tty(isatty(STDIN_FILENO));
    bool compile(false);
    CYOptions options;

    append_history$ = (int (*)(int, const char *)) (dlsym(RTLD_DEFAULT, "append_history"));

#ifdef CY_ATTACH
    pid_t pid(_not(pid_t));
#endif

    const char *host(NULL);
    const char *port(NULL);

    apr_getopt_t *state;
    _aprcall(apr_getopt_init(&state, pool, argc, argv));

    for (;;) {
        char opt;
        const char *arg;

        apr_status_t status(apr_getopt(state,
            "cg:n:"
#ifdef CY_ATTACH
            "p:"
#endif
            "r:"
            "s"
        , &opt, &arg));

        switch (status) {
            case APR_EOF:
                goto getopt;
            case APR_BADCH:
            case APR_BADARG:
                fprintf(stderr,
                    "usage: cycript [-c]"
#ifdef CY_ATTACH
                    " [-p <pid|name>]"
#endif
                    " [-r <host:port>]"
                    " [<script> [<arg>...]]\n"
                );
                return 1;
            default:
                _aprcall(status);
        }

        switch (opt) {
            case 'c':
                compile = true;
            break;

            case 'g':
                if (false);
                else if (strcmp(arg, "rename") == 0)
                    options.verbose_ = true;
#if YYDEBUG
                else if (strcmp(arg, "bison") == 0)
                    bison_ = true;
#endif
                else {
                    fprintf(stderr, "invalid name for -g\n");
                    return 1;
                }
            break;

            case 'n':
                if (false);
                else if (strcmp(arg, "minify") == 0)
                    pretty_ = true;
                else {
                    fprintf(stderr, "invalid name for -n\n");
                    return 1;
                }
            break;

#ifdef CY_ATTACH
            case 'p': {
                size_t size(strlen(arg));
                char *end;

                pid = strtoul(arg, &end, 0);
                if (arg + size != end) {
                    // XXX: arg needs to be escaped in some horrendous way of doom
                    const char *command(apr_pstrcat(pool, "ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^", arg, " /{s/^[^ ]* //;q;};};d'", NULL));

                    if (FILE *pids = popen(command, "r")) {
                        char value[32];
                        size = 0;

                        for (;;) {
                            size_t read(fread(value + size, 1, sizeof(value) - size, pids));
                            if (read == 0)
                                break;
                            else {
                                size += read;
                                if (size == sizeof(value)) {
                                    pid = _not(pid_t);
                                    goto fail;
                                }
                            }
                        }

                      size:
                        if (size == 0)
                            goto fail;
                        if (value[size - 1] == '\n') {
                            --size;
                            goto size;
                        }

                        value[size] = '\0';
                        size = strlen(value);
                        pid = strtoul(value, &end, 0);
                        if (value + size != end) fail:
                            pid = _not(pid_t);
                        _syscall(pclose(pids));
                    }

                    if (pid == _not(pid_t)) {
                        fprintf(stderr, "invalid pid for -p\n");
                        return 1;
                    }
                }
            } break;
#endif

            case 'r': {
                //size_t size(strlen(arg));

                char *colon(strrchr(arg, ':'));
                if (colon == NULL) {
                    fprintf(stderr, "missing colon in hostspec\n");
                    return 1;
                }

                /*char *end;
                port = strtoul(colon + 1, &end, 10);
                if (end != arg + size) {
                    fprintf(stderr, "invalid port in hostspec\n");
                    return 1;
                }*/

                host = arg;
                *colon = '\0';
                port = colon + 1;
            } break;

            case 's':
                strict_ = true;
            break;
        }
    } getopt:;

    const char *script;
    int ind(state->ind);

#ifdef CY_ATTACH
    if (pid != _not(pid_t) && ind < argc - 1) {
        fprintf(stderr, "-p cannot set argv\n");
        return 1;
    }

    if (pid != _not(pid_t) && compile) {
        fprintf(stderr, "-p conflicts with -c\n");
        return 1;
    }
#endif

    if (ind == argc)
        script = NULL;
    else {
#ifdef CY_EXECUTE
        // XXX: const_cast?! wtf gcc :(
        CYSetArgs(argc - ind - 1, const_cast<const char **>(argv + ind + 1));
#endif
        script = argv[ind];
        if (strcmp(script, "-") == 0)
            script = NULL;
    }

#ifdef CY_ATTACH
    if (pid != _not(pid_t) && script == NULL && !tty) {
        fprintf(stderr, "non-terminal attaching to remote console\n");
        return 1;
    }
#endif

#ifdef CY_ATTACH
    if (pid == _not(pid_t))
        client_ = -1;
    else {
        int server(_syscall(socket(PF_UNIX, SOCK_STREAM, 0))); try {
            struct sockaddr_un address;
            memset(&address, 0, sizeof(address));
            address.sun_family = AF_UNIX;

            sprintf(address.sun_path, "/tmp/.s.cy.%u", getpid());

            _syscall(bind(server, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
            _syscall(chmod(address.sun_path, 0777));

            try {
                _syscall(listen(server, 1));
                InjectLibrary(pid);
                client_ = _syscall(accept(server, NULL, NULL));
            } catch (...) {
                // XXX: exception?
                unlink(address.sun_path);
                throw;
            }
        } catch (...) {
            _syscall(close(server));
            throw;
        }
    }
#else
    client_ = -1;
#endif

    if (client_ == -1 && host != NULL && port != NULL) {
        struct addrinfo hints;
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = 0;
        hints.ai_flags = 0;

        struct addrinfo *infos;
        _syscall(getaddrinfo(host, port, &hints, &infos));

        _assert(infos != NULL); try {
            for (struct addrinfo *info(infos); info != NULL; info = info->ai_next) {
                int client(_syscall(socket(info->ai_family, info->ai_socktype, info->ai_protocol))); try {
                    _syscall(connect(client, info->ai_addr, info->ai_addrlen));
                    client_ = client;
                    break;
                } catch (...) {
                    _syscall(close(client));
                    throw;
                }
            }
        } catch (...) {
            freeaddrinfo(infos);
            throw;
        }
    }

    if (script == NULL && tty)
        Console(options);
    else {
        CYLocalPool pool;

        char *start, *end;
        std::istream *indirect;

        if (script == NULL) {
            start = NULL;
            end = NULL;
            indirect = &std::cin;
        } else {
            size_t size;
            start = reinterpret_cast<char *>(Map(script, &size));
            end = start + size;

            if (size >= 2 && start[0] == '#' && start[1] == '!') {
                start += 2;

                if (void *line = memchr(start, '\n', end - start))
                    start = reinterpret_cast<char *>(line);
                else
                    start = end;
            }

            indirect = NULL;
        }

        CYStream direct(start, end);
        std::istream &stream(indirect == NULL ? direct : *indirect);
        CYDriver driver(stream, script ?: "<stdin>");

        cy::parser parser(driver);
        Setup(driver, parser);

        if (parser.parse() != 0 || !driver.errors_.empty()) {
            for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
                std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
        } else if (driver.program_ != NULL)
            if (client_ != -1) {
                // XXX: this code means that you can't pipe to another process
                std::string code(start, end-start);
                Run(client_, false, code, &std::cout);
            } else {
                std::ostringstream str;
                CYOutput out(str, options);
                Setup(out, driver, options);
                out << *driver.program_;
                std::string code(str.str());
                if (compile)
                    std::cout << code;
                else
                    Run(client_, false, code, &std::cout);
            }
    }

    apr_pool_destroy(pool);

    return 0;
}