【问题标题】:Unable to write to AllocConsole()无法写入 AllocConsole()
【发布时间】:2021-03-26 09:00:12
【问题描述】:

我有一个 cpp dll,我想在注入后将文本打印到控制台。我使用 AllocConsole() 创建控制台,因为它是最简单的方法,但我不能在控制台中写入。

当我尝试 printf() 时,什么也没有发生。我也试过 std::cout

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
        AllocConsole();
        printf("Injected");
        CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)main, NULL, NULL, NULL);
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

【问题讨论】:

标签: c++ console dll-injection


【解决方案1】:

通过AllocConsole()分配新的控制台后,您需要重新打开标准流(stdoutstderrstdin)才能使用它们。

您可以使用freopen 来执行此操作(在较新版本的 Visual Studio 中,您需要使用 freopen_s) 示例:

FILE *fDummy;
freopen_s(&fDummy, "CONIN$", "r", stdin);
freopen_s(&fDummy, "CONOUT$", "w", stderr);
freopen_s(&fDummy, "CONOUT$", "w", stdout);

如果您想使用已弃用的freopen,您可以通过#defineing _CRT_SECURE_NO_WARNINGSdisable the warning

如果您还想使用宽字符流(std::wcoutstd::wcerr 等...),则需要调用 SetStdHandle() 为您的进程设置新的输出句柄。您可以通过使用CONOUT$ / CONIN$ 作为文件名调用CreateFile() 来获得所需的文件句柄:

HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
SetStdHandle(STD_OUTPUT_HANDLE, hConOut);

此外,如果您在重新打开它们之前尝试使用其中一个流,它们将具有 std::ios_base::badbitstd::ios_base::failbit 在他们的iostate 中设置,因此后续的写入/读取将被忽略。
您可以使用.clear() 重置流状态,之后您可以再次读取/写入流:

std::cout.clear();
std::cin.clear();

这是在AllocConsole() 之后重新打开所有流的完整示例:

void CreateConsole()
{
    if (!AllocConsole()) {
        // Add some error handling here.
        // You can call GetLastError() to get more info about the error.
        return;
    }

    // std::cout, std::clog, std::cerr, std::cin
    FILE* fDummy;
    freopen_s(&fDummy, "CONOUT$", "w", stdout);
    freopen_s(&fDummy, "CONOUT$", "w", stderr);
    freopen_s(&fDummy, "CONIN$", "r", stdin);
    std::cout.clear();
    std::clog.clear();
    std::cerr.clear();
    std::cin.clear();

    // std::wcout, std::wclog, std::wcerr, std::wcin
    HANDLE hConOut = CreateFile(_T("CONOUT$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    HANDLE hConIn = CreateFile(_T("CONIN$"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    SetStdHandle(STD_OUTPUT_HANDLE, hConOut);
    SetStdHandle(STD_ERROR_HANDLE, hConOut);
    SetStdHandle(STD_INPUT_HANDLE, hConIn);
    std::wcout.clear();
    std::wclog.clear();
    std::wcerr.clear();
    std::wcin.clear();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多