注入DLL并打印消息

时间:2014-07-24 08:56:26

标签: c dll code-injection

我正在处理两件新事:写一个DLL并在另一个进程中注入它。我想我注入成功,因为如果我尝试删除它,我会收到一条消息,告诉我它被其他程序使用。

我在Visual Studio 2008 http://msdn.microsoft.com/en-us/library/ms235636%28v=vs.80%29.aspx中执行了这些步骤,但是我用C编写了它,而不是C ++。

这是代码

DWORD 
APIENTRY
DllMain(
        HMODULE hModule,
        DWORD  ul_reason_for_call,
        LPVOID lpReserved
        )
{
    printf("Hello World\n");
    Sleep(5000); // added this to make sure I see it when it happens
    return TRUE;
}

我创建了一个引用DLL的应用程序,就像在MSDN文档中说的那样,它可以工作(它打印Hello World)。

在我的DLL注入程序的每一步,我检查错误并打印它们。所以我知道没有任何功能失败。 我检查退出代码,它是1927086080,我不知道是什么意思。 我不知道是否需要它,但这是我的程序的C源。

#include <stdio.h>
#include <windows.h>
#include <string.h>

int main(int argc, TCHAR* argv[])
{
    DWORD procId = 0;   
    DWORD pathLen = 0;
    DWORD writeProcMemory = 0;
    DWORD exitCode = 0;

    HANDLE hProc = NULL;
    HANDLE hDll = NULL;
    HANDLE hThread = NULL;

    LPVOID baseAdr = NULL;
    LPVOID fAdr = NULL;

    procId = atoi((char*)argv[1]); 
    pathLen = strlen((LPCSTR)argv[2]);

    if(0 == pathLen)
    {
        printf("Check DLL path\n");
        return 0;
    }

    // Open process
    hProc = OpenProcess(PROCESS_ALL_ACCESS,
        0,
        procId);

    if(NULL == hProc)
    {
        printf("OpenProcess failed\nGetLastError() = %d\n", 
            GetLastError());
        return 0;
    }

    // Allocate memory
    baseAdr = VirtualAllocEx(hProc,
        0,
        pathLen + 1,
        MEM_COMMIT,
        PAGE_READWRITE);

    if(NULL == baseAdr)
    {
        printf("VirtualAllocEx failed\nGetLastError() = %d\n",
            GetLastError());
        CloseHandle(hProc);
        return 0;
    }

    // write my dll path in the memory I just allocated
    if(!WriteProcessMemory(hProc,
        baseAdr,
        argv[2],
        pathLen + 1,
        0))
    {
        printf("WriteProcessMemory failed\nGetLastError() = %d\n",
            GetLastError());
        VirtualFreeEx(hProc,
            baseAdr,
            0,
            MEM_RELEASE);
        CloseHandle(hProc);
        return 0;
    }

    // get kernel32.dll 
    hDll = LoadLibrary(TEXT("kernel32.dll"));

    if(NULL == hDll)
    {
        printf("LoadLibrary failed\nGetLastError() = %d\n",
            GetLastError());
        VirtualFreeEx(hProc,
            baseAdr,
            0,
            MEM_RELEASE);
        CloseHandle(hProc);
        return 0;
    }

    // get LoadLibraryA entry point
    fAdr = GetProcAddress(hDll,
        "LoadLibraryA");

    if(NULL == fAdr)
    {
        printf("GetProcAddress failed\nGetLastError() = %d\n",
            GetLastError());
        FreeLibrary(hDll);
        VirtualFreeEx(hProc,
            baseAdr,
            0,
            MEM_RELEASE);
        CloseHandle(hProc);
        return 0;
    }

    // create remote thread
    hThread = CreateRemoteThread(hProc,
        0,
        0,
        fAdr,
        baseAdr,
        0,
        0);

    if(NULL == hThread)
    {
        printf("CreateRemoteThread failed\nGetLastError() = %d\n",
            GetLastError());
        FreeLibrary(hDll);
        VirtualFreeEx(hProc,
            baseAdr,
            0,
            MEM_RELEASE);
        CloseHandle(hProc);
        return 0;
    }

    WaitForSingleObject(hThread, 
        INFINITE);
    if(GetExitCodeThread(hThread,
        &exitCode))
    {
        printf("exit code = %d\n",
            exitCode);
    }
    else
    {
        printf("GetExitCode failed\nGetLastError() = %d\n",
            GetLastError());
    }

    CloseHandle(hThread);
    FreeLibrary(hDll);
    VirtualFreeEx(hProc,
        baseAdr,
        0,
        MEM_RELEASE);
    CloseHandle(hProc);
    return 0;
}

现在,当我将一个shellcode(程序与上面的程序略有不同)注入一个进程时,我可以在进程资源管理器中看到我的shell代码如何开始运行以及受害者进程是他的父进程。在这里,我什么都看不见,但是,这是我第一次使用DLL。 但它仍然被加载,因为我无法删除dll文件,直到我杀死受害者进程。

另外,当我运行我的注射程序时,我可以看到它在5秒内无效,所以它就像跳过了printf一样。

在Windows 7 x64上执行此操作。我知道有些情况下CreateRemoteThread不能在Windows 7上运行,但我在我的shell代码注入中使用它并且它可以工作,我在这里使用相同的目标。

更新:更改我的DLL以调用ExitProcess(0);杀死受害者的过程,所以这一切都归结于我不知道如何打印的东西。

我怎样才能打印出来?

1 个答案:

答案 0 :(得分:1)

您希望从DLL获取邮件,但使用printf。你怎么看到DLL的printf输出?您最好将信息写入文件。

#define LOG_FILE L"C:\\MyLogFile.txt"

void WriteLog(char* text)
{
    HANDLE hfile = CreateFileW(LOG_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD written;
    WriteFile(hfile, text, strlen(text), &written, NULL);
    WriteFile(hfile, "\r\n", 2, &written, NULL);
    CloseHandle(hfile);
}

void WriteLog(wchar_t* text)
{
    HANDLE hfile = CreateFileW(LOG_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD written;
    WriteFile(hfile, text, wcslen(text) * 2, &written, NULL);
    WriteFile(hfile, L"\r\n", 4, &written, NULL);
    CloseHandle(hfile);
}

用我的函数替换所有printf次调用,看看实际发生了什么。顺便说一下,如果你的DLL中有线程,你可以每秒写一次日志,以确保你的代码有效。您也可以将时间添加到日志文件中。

我认为如果你有足够的权限将DLL注入进程,没有什么能阻止你。更改代码并告诉我日志文件中会发生什么。

祝你好运