程序功能是利用NtQueueApcThreadEx注入ShellCode到一个进程中,程序运行后会让你选择模式,按1为普通模式,所需的常规API接口都是使用Windows原本正常的API;在有游戏保护的进程中Windows原本正常的API无法使用,这时候需要选择内核模式,按2选择内核模式。
内核模式下使用的一些关键API都是我自己在ring0从0实现的,本帖仅开源普通模式下的代码。内核模式下使用的关键API以及调用框架不开源。
选择模式之后需要输入被注入进程的PID
项目包含三个源代码文件:1.源.cpp
2.fun.asm
3.fun.h
首先是源.cpp文件代码:
fun.asm文件
fun.h文件
shellCode的功能是给被注入进程设置一个键盘钩子,TAB键。
插入代码
```
/
*
*
函数原型:
NTSTATUS NtQueueTHreadApcEx(
_in HANDLE thread,
_in UCHAR flags,
0
:常规用户APC,
1
:特殊用户APC
_in PAPCFUNC apcRoutine,
_in PVOID context1,
_in PVOID arg1,
_in PVOID arg2
);
需要从Ntdll.dll模块显式导出(GetProcAddress)
*
/
HWND hwndG
=
0
;
BOOL
CALLBACK EnumWindowsProc(
HWND hwnd,
LPARAM lParam)
{
WCHAR path[MAX_PATH]
=
{
0
};
WCHAR
*
text
=
(WCHAR
*
)lParam;
GetWindowText(hwnd, path, MAX_PATH);
if
(lstrcmpW(text, path)
=
=
0
)
{
hwndG
=
hwnd;
return
FALSE;
}
else
{
hwndG
=
0
;
return
TRUE;
}
}
DWORD WINAPI GetThreadIdByProcessId(DWORD dwProcessId)
{
THREADENTRY32 th32;
th32.dwSize
=
sizeof(THREADENTRY32);
DWORD dwThreadId
=
0
;
HANDLE hdTool
=
CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessId);
if
(Thread32First(hdTool, &th32))
{
do
{
if
(th32.th32OwnerProcessID
=
=
dwProcessId)
{
dwThreadId
=
th32.th32ThreadID;
/
/
printf(
"%d\n"
, dwThreadId);
break
;
}
}
while
(Thread32Next(hdTool, &th32));
}
else
{
DWORD dwErro
=
GetLastError();
/
/
printf(
"遍历进程失败!——%d"
, dwErro);
return
dwErro;
}
return
dwThreadId;
}
BOOL
WINAPI PrivilegeAdjust()
{
BOOL
flag;
HANDLE token;
if
(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
{
/
/
printf(
"打开令牌失败!\n"
);
flag
=
FALSE;
}
LUID pid;
if
(!LookupPrivilegeValueA(NULL,
"SeDebugPrivilege"
, &pid))
{
/
/
printf(
"查看特权ID失败\n"
);
flag
=
FALSE;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount
=
1
;
tp.Privileges[
0
].Luid
=
pid;
tp.Privileges[
0
].Attributes
=
SE_PRIVILEGE_ENABLED;
if
(!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
/
/
printf(
"提升特权失败!\n"
);
flag
=
FALSE;
}
return
TRUE;
}
typedef
BOOL
(
*
MYTYPE)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T
*
);
typedef HANDLE(
*
OPPS)(DWORD,
BOOL
, DWORD);
typedef
BOOL
(
*
WRMEMEX)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T
*
);
typedef HANDLE(
*
OPTS)();
typedef ULONG64(
*
GETPEB)(DWORD);
typedef NTSTATUS(
*
NTQUEAPC)(HANDLE, UCHAR, PVOID, PVOID, PVOID, PVOID);
WRMEMEX Read;
WRMEMEX Write;
OPPS OpenPro;
OPTS OpenThr;
NTQUEAPC NtQueueUserApcEx;
VOID InitFrmak()
{
printf(
"内核\n"
);
NtQueueUserApcEx
=
NULL;
HMODULE mod
=
LoadLibraryA(
"ApiSystemCall.dll"
);
Read
=
(WRMEMEX)GetProcAddress(mod,
"YhReadProcessMemory"
);
Write
=
(WRMEMEX)GetProcAddress(mod,
"YhWriteProcessMemory"
);
OpenPro
=
(OPPS)GetProcAddress(mod,
"YhOpenProcess"
);
OpenThr
=
(OPTS)GetProcAddress(mod,
"YhOpenThread"
);
NtQueueUserApcEx
=
(NTQUEAPC)GetProcAddress(GetModuleHandleA(
"ntdll.dll"
),
"NtQueueApcThreadEx"
);
if
(NtQueueUserApcEx
=
=
NULL)
{
MessageBoxA(NULL,
"获取函数失败"
,
0
,
0
);
}
}
VOID InitFrmakEx()
{
NtQueueUserApcEx
=
NULL;
printf(
"普通\n"
);
Read
=
ReadProcessMemory;
Write
=
WriteProcessMemory;
OpenPro
=
OpenProcess;
OpenThr
=
OpenThread;
NtQueueUserApcEx
=
(NTQUEAPC)GetProcAddress(GetModuleHandleA(
"ntdll.dll"
),
"NtQueueApcThreadEx"
);
if
(NtQueueUserApcEx
=
=
NULL)
{
MessageBoxA(NULL,
"获取函数失败"
,
0
,
0
);
}
}
typedef VOID(
*
FUN)();
int
main()
{
DWORD pid;
SIZE_T size
=
0
;
CONTEXT text;
VirtualProtect(fun,
0x60
, PAGE_EXECUTE_READWRITE, &pid);
*
(ULONG64
*
)(&(((UCHAR
*
)fun2)[
0x34
]))
=
MessageBoxA;
*
(ULONG64
*
)(&(((UCHAR
*
)fun2)[
0x9f
]))
=
SetWindowsHookExA;
/
/
fun(NULL,NULL,NULL);
printf(
"请输入模式:\n1.普通模式\n2.内核模式\n"
);
scanf(
"%d"
, &size);
(size
=
=
1
)? InitFrmakEx(): InitFrmak();
printf(
"请输入进程PID:\n"
);
scanf(
"%d"
, &pid);
PrivilegeAdjust();
HANDLE hd
=
OpenPro(PROCESS_ALL_ACCESS, FALSE, pid);
PVOID mem
=
VirtualAllocEx(hd, NULL,
0X1000
, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
DWORD tid
=
GetThreadIdByProcessId(pid);
HANDLE td;
if
(size
=
=
1
)
{
td
=
OpenThr(THREAD_ALL_ACCESS,FALSE,tid);
}
else
{
td
=
OpenThr(tid, hd, THREAD_ALL_ACCESS, FALSE);
}
if
(!Write(hd, mem, fun2,
0x100
, &size))
{
MessageBoxA(
0
,
"写入失败"
,
0
,
0
);
}
SuspendThread(td);
NTSTATUS code
=
NtQueueUserApcEx(td,
1
, (PVOID)(((ULONG64)mem)
+
0x53
), tid,
0
,
0
);
if
(code!
=
0
)
{
printf(
"%x\n"
, code);
MessageBox(
0
,
0
,
0
,
0
);
}
ResumeThread(td);
system(
"pause"
);
return
0
;
}
插入代码
```
/
*
*
函数原型:
NTSTATUS NtQueueTHreadApcEx(
_in HANDLE thread,
_in UCHAR flags,
0
:常规用户APC,
1
:特殊用户APC
_in PAPCFUNC apcRoutine,
_in PVOID context1,
_in PVOID arg1,
_in PVOID arg2
);
需要从Ntdll.dll模块显式导出(GetProcAddress)
*
/
HWND hwndG
=
0
;
BOOL
CALLBACK EnumWindowsProc(
HWND hwnd,
LPARAM lParam)
{
WCHAR path[MAX_PATH]
=
{
0
};
WCHAR
*
text
=
(WCHAR
*
)lParam;
GetWindowText(hwnd, path, MAX_PATH);
if
(lstrcmpW(text, path)
=
=
0
)
{
hwndG
=
hwnd;
return
FALSE;
}
else
{
hwndG
=
0
;
return
TRUE;
}
}
DWORD WINAPI GetThreadIdByProcessId(DWORD dwProcessId)
{
THREADENTRY32 th32;
th32.dwSize
=
sizeof(THREADENTRY32);
DWORD dwThreadId
=
0
;
HANDLE hdTool
=
CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwProcessId);
if
(Thread32First(hdTool, &th32))
{
do
{
if
(th32.th32OwnerProcessID
=
=
dwProcessId)
{
dwThreadId
=
th32.th32ThreadID;
/
/
printf(
"%d\n"
, dwThreadId);
break
;
}
}
while
(Thread32Next(hdTool, &th32));
}
else
{
DWORD dwErro
=
GetLastError();
/
/
printf(
"遍历进程失败!——%d"
, dwErro);
return
dwErro;
}
return
dwThreadId;
}
BOOL
WINAPI PrivilegeAdjust()
{
BOOL
flag;
HANDLE token;
if
(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
{
/
/
printf(
"打开令牌失败!\n"
);
flag
=
FALSE;
}
LUID pid;
if
(!LookupPrivilegeValueA(NULL,
"SeDebugPrivilege"
, &pid))
{
/
/
printf(
"查看特权ID失败\n"
);
flag
=
FALSE;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount
=
1
;
tp.Privileges[
0
].Luid
=
pid;
tp.Privileges[
0
].Attributes
=
SE_PRIVILEGE_ENABLED;
if
(!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
/
/
printf(
"提升特权失败!\n"
);
flag
=
FALSE;
}
return
TRUE;
}
typedef
BOOL
(
*
MYTYPE)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T
*
);
typedef HANDLE(
*
OPPS)(DWORD,
BOOL
, DWORD);
typedef
BOOL
(
*
WRMEMEX)(HANDLE, LPVOID, LPVOID, SIZE_T, SIZE_T
*
);
typedef HANDLE(
*
OPTS)();
typedef ULONG64(
*
GETPEB)(DWORD);
typedef NTSTATUS(
*
NTQUEAPC)(HANDLE, UCHAR, PVOID, PVOID, PVOID, PVOID);
WRMEMEX Read;
WRMEMEX Write;
OPPS OpenPro;
OPTS OpenThr;
NTQUEAPC NtQueueUserApcEx;
VOID InitFrmak()
{
printf(
"内核\n"
);
NtQueueUserApcEx
=
NULL;
HMODULE mod
=
LoadLibraryA(
"ApiSystemCall.dll"
);
Read
=
(WRMEMEX)GetProcAddress(mod,
"YhReadProcessMemory"
);
Write
=
(WRMEMEX)GetProcAddress(mod,
"YhWriteProcessMemory"
);
OpenPro
=
(OPPS)GetProcAddress(mod,
"YhOpenProcess"
);
OpenThr
=
(OPTS)GetProcAddress(mod,
"YhOpenThread"
);
NtQueueUserApcEx
=
(NTQUEAPC)GetProcAddress(GetModuleHandleA(
"ntdll.dll"
),
"NtQueueApcThreadEx"
);
if
(NtQueueUserApcEx
=
=
NULL)
{
MessageBoxA(NULL,
"获取函数失败"
,
0
,
0
);
}
}
VOID InitFrmakEx()
{
NtQueueUserApcEx
=
NULL;
printf(
"普通\n"
);
Read
=
ReadProcessMemory;
Write
=
WriteProcessMemory;
OpenPro
=
OpenProcess;
OpenThr
=
OpenThread;
NtQueueUserApcEx
=
(NTQUEAPC)GetProcAddress(GetModuleHandleA(
"ntdll.dll"
),
"NtQueueApcThreadEx"
);
if
(NtQueueUserApcEx
=
=
NULL)
{
MessageBoxA(NULL,
"获取函数失败"
,
0
,
0
);
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!