这个是偶然发现的,通过测试可以在r0中拿到在powershell输入的命令行参数。

原理是hook NtAlpcSendWaitReceivePort函数,通过解析该函数的第三个参数发现类型为0x01d8时候在偏移0xd0的位置就是powershell参数的位置

下面是代码

#include <Ntifs.h>
#include <ntimage.h>
#include <ntstrsafe.h>
typedef struct _LDR_DATA_TABLE_ENTRY {LIST_ENTRY InLoadOrderLinks;LIST_ENTRY InMemoryOrderLinks;LIST_ENTRY InInitializationOrderLinks;PVOID      DllBase;PVOID      EntryPoint;ULONG32    SizeOfImage;UINT8      Unknow0[0x4];UNICODE_STRING FullDllName;UNICODE_STRING BaseDllName;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
typedef struct _SYSTEM_SERVICE_TABLE {PVOID       ServiceTableBase;PVOID       ServiceCounterTableBase;ULONGLONG   NumberOfServices;PVOID       ParamTableBase;
} SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE;PSYSTEM_SERVICE_TABLE KeServiceDescriptorTable;
ULONGLONG g_orgfunc = NULL;//关闭写保护
KIRQL WPOFFx64() {KIRQL irql = KeRaiseIrqlToDpcLevel();UINT64 cr0 = __readcr0();cr0 &= 0xfffffffffffeffff;__writecr0(cr0);_disable();return irql;
}
//开启写保护
void WPONx64(KIRQL irql) {UINT64 cr0 = __readcr0();cr0 |= 0x10000;_enable();__writecr0(cr0);KeLowerIrql(irql);}//得到ntos的基地址
ULONGLONG GetOsBaseAddress(PDRIVER_OBJECT pDriverObject) {UNICODE_STRING osName = { 0 };WCHAR wzData[0x100] = L"ntoskrnl.exe";RtlInitUnicodeString(&osName, wzData);LDR_DATA_TABLE_ENTRY *pDataTableEntry, *pTempDataTableEntry;//双循环链表定义PLIST_ENTRY    pList;//指向驱动对象的DriverSectionpDataTableEntry = (LDR_DATA_TABLE_ENTRY*)pDriverObject->DriverSection;//判断是否为空if (!pDataTableEntry)return;/*开始遍历驱动对象链表*///得到链表地址pList = pDataTableEntry->InLoadOrderLinks.Flink;//判断是否等于头部while (pList != &pDataTableEntry->InLoadOrderLinks) {pTempDataTableEntry = (LDR_DATA_TABLE_ENTRY *)pList;if (RtlEqualUnicodeString(&pTempDataTableEntry->BaseDllName, &osName, TRUE))return (ULONGLONG)pTempDataTableEntry->DllBase;pList = pList->Flink;}return 0;
}
ULONG GetSSDTRVA(UCHAR *funcname) {NTSTATUS Status;HANDLE FileHandle;IO_STATUS_BLOCK ioStatus;FILE_STANDARD_INFORMATION FileInformation;//设置NTDLL路径UNICODE_STRING uniFileName;RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntoskrnl.exe");//初始化打开文件的属性OBJECT_ATTRIBUTES objectAttributes;InitializeObjectAttributes(&objectAttributes, &uniFileName,OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);创建文件Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,&ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);if (!NT_SUCCESS(Status))return 0;//获取文件信息Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);if (!NT_SUCCESS(Status)) {ZwClose(FileHandle);return 0;}//判断文件大小是否过大if (FileInformation.EndOfFile.HighPart != 0) {ZwClose(FileHandle);return 0;}//取文件大小ULONG uFileSize = FileInformation.EndOfFile.LowPart;//分配内存PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize + 0x100, (ULONG)"PGu");if (pBuffer == NULL) {ZwClose(FileHandle);return 0;}//从头开始读取文件LARGE_INTEGER byteOffset;byteOffset.LowPart = 0;byteOffset.HighPart = 0;Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);if (!NT_SUCCESS(Status)) {ZwClose(FileHandle);return 0;}//取出导出表PIMAGE_DOS_HEADER  pDosHeader;PIMAGE_NT_HEADERS  pNtHeaders;PIMAGE_SECTION_HEADER pSectionHeader;ULONGLONG     FileOffset;//这里是64位数的,所以这里不是32个字节PIMAGE_EXPORT_DIRECTORY pExportDirectory;//DLL内存数据转成DOS头结构pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;//取出PE头结构pNtHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)pBuffer + pDosHeader->e_lfanew);//判断PE头导出表表是否为空if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)return 0;//取出导出表偏移FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;//取出节头结构pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONGLONG)pNtHeaders + sizeof(IMAGE_NT_HEADERS));PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;//遍历节结构进行地址运算for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}//导出表地址pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONGLONG)pBuffer + FileOffset);//取出导出表函数地址PLONG AddressOfFunctions;FileOffset = pExportDirectory->AddressOfFunctions;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfFunctions = (PULONG)((ULONGLONG)pBuffer + FileOffset);//这里注意一下foa和rva//取出导出表函数名字PUSHORT AddressOfNameOrdinals;FileOffset = pExportDirectory->AddressOfNameOrdinals;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfNameOrdinals = (PUSHORT)((ULONGLONG)pBuffer + FileOffset);//注意一下foa和rva//取出导出表函数序号PULONG AddressOfNames;FileOffset = pExportDirectory->AddressOfNames;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfNames = (PULONG)((ULONGLONG)pBuffer + FileOffset);//注意一下foa和rva//分析导出表ULONG uNameOffset;ULONG uOffset;LPSTR FunName;ULONG uAddressOfNames;ULONG TargetOff = 0;for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) {uAddressOfNames = *AddressOfNames;pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}FunName = (LPSTR)((ULONGLONG)pBuffer + uOffset);if (!_stricmp(funcname, FunName)) {TargetOff = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];}}ExFreePoolWithTag(pBuffer, (ULONG)"PGu");ZwClose(FileHandle);return TargetOff;
}//得到ssdt表的基地址
ULONGLONG GetKeServiceDescriptorTable64(PDRIVER_OBJECT DriverObject) {/*KdDebuggerNotPresent,FFFFF80353C59B2B1: kd> u fffff803`539dcd07nt!KiSystemServiceStart+0x7:fffff803`539dcd07 8bf8            mov     edi,eaxfffff803`539dcd09 c1ef07          shr     edi,7fffff803`539dcd0c 83e720          and     edi,20hfffff803`539dcd0f 25ff0f0000      and     eax,0FFFhnt!KiSystemServiceRepeat:fffff803`539dcd14 4c8d15659b3b00  lea     r10,[nt!KeServiceDescriptorTable (fffff803`53d96880)]fffff803`539dcd1b 4c8d1d5e1d3a00  lea     r11,[nt!KeServiceDescriptorTableShadow (fffff803`53d7ea80)]fffff803`539dcd22 f7437880000000  test    dword ptr [rbx+78h],80hfffff803`539dcd29 7413            je      nt!KiSystemServiceRepeat+0x2a (fffff803`539dcd3e)*/char KiSystemServiceStart_pattern[13] = "\x8B\xF8\xC1\xEF\x07\x83\xE7\x20\x25\xFF\x0F\x00\x00";ULONGLONG CodeScanStart = GetSSDTRVA("_stricmp") + GetOsBaseAddress(DriverObject);//这样动态定位的就是真正函数的地址ULONGLONG i, tbl_address, b;for (i = 0; i < 0x50000; i++) {if (!memcmp((char*)(ULONGLONG)CodeScanStart + i,(char*)KiSystemServiceStart_pattern, 13)) {for (b = 0; b < 50; b++) {tbl_address = ((ULONGLONG)CodeScanStart + i + b);if (*(USHORT*)((ULONGLONG)tbl_address) == (USHORT)0x8d4c)return ((LONGLONG)tbl_address + 7) + *(LONG*)(tbl_address + 3);}}}return 0;
}
//通过名字得到当前函数的ssdt函数的id
ULONG GetIndexByName(UCHAR *sdName) {NTSTATUS Status;HANDLE FileHandle;IO_STATUS_BLOCK ioStatus;FILE_STANDARD_INFORMATION FileInformation;//设置NTDLL路径UNICODE_STRING uniFileName;RtlInitUnicodeString(&uniFileName, L"\\SystemRoot\\system32\\ntdll.dll");//初始化打开文件的属性OBJECT_ATTRIBUTES objectAttributes;InitializeObjectAttributes(&objectAttributes, &uniFileName,OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);创建文件Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,&ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);if (!NT_SUCCESS(Status))return 0;//获取文件信息Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);if (!NT_SUCCESS(Status)) {ZwClose(FileHandle);return 0;}//判断文件大小是否过大if (FileInformation.EndOfFile.HighPart != 0) {ZwClose(FileHandle);return 0;}//取文件大小ULONG uFileSize = FileInformation.EndOfFile.LowPart;//分配内存PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize + 0x100, (ULONG)"Ntdl");if (pBuffer == NULL) {ZwClose(FileHandle);return 0;}//从头开始读取文件LARGE_INTEGER byteOffset;byteOffset.LowPart = 0;byteOffset.HighPart = 0;Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);if (!NT_SUCCESS(Status)) {ZwClose(FileHandle);return 0;}//取出导出表PIMAGE_DOS_HEADER  pDosHeader;PIMAGE_NT_HEADERS  pNtHeaders;PIMAGE_SECTION_HEADER pSectionHeader;ULONGLONG     FileOffset;//这里是64位数的,所以这里不是32个字节PIMAGE_EXPORT_DIRECTORY pExportDirectory;//DLL内存数据转成DOS头结构pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;//取出PE头结构pNtHeaders = (PIMAGE_NT_HEADERS)((ULONGLONG)pBuffer + pDosHeader->e_lfanew);//判断PE头导出表表是否为空if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)return 0;//取出导出表偏移FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;//取出节头结构pSectionHeader = (PIMAGE_SECTION_HEADER)((ULONGLONG)pNtHeaders + sizeof(IMAGE_NT_HEADERS));PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;//遍历节结构进行地址运算for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}//导出表地址pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONGLONG)pBuffer + FileOffset);//取出导出表函数地址PLONG AddressOfFunctions;FileOffset = pExportDirectory->AddressOfFunctions;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfFunctions = (PULONG)((ULONGLONG)pBuffer + FileOffset);//这里注意一下foa和rva//取出导出表函数名字PUSHORT AddressOfNameOrdinals;FileOffset = pExportDirectory->AddressOfNameOrdinals;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfNameOrdinals = (PUSHORT)((ULONGLONG)pBuffer + FileOffset);//注意一下foa和rva//取出导出表函数序号PULONG AddressOfNames;FileOffset = pExportDirectory->AddressOfNames;//遍历节结构进行地址运算pSectionHeader = pOldSectionHeader;for (UINT16 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= FileOffset && FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}AddressOfNames = (PULONG)((ULONGLONG)pBuffer + FileOffset);//注意一下foa和rva//分析导出表ULONG uNameOffset;ULONG uOffset;LPSTR FunName;PVOID pFuncAddr;ULONG uServerIndex;ULONG uAddressOfNames;for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++) {uAddressOfNames = *AddressOfNames;pSectionHeader = pOldSectionHeader;for (UINT32 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= uAddressOfNames && uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}FunName = (LPSTR)((ULONGLONG)pBuffer + uOffset);if (FunName[0] == 'Z' && FunName[1] == 'w') {pSectionHeader = pOldSectionHeader;uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];for (UINT32 Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++) {if (pSectionHeader->VirtualAddress <= uOffset && uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;}pFuncAddr = (PVOID)((ULONGLONG)pBuffer + uNameOffset);uServerIndex = *(PULONG)((ULONGLONG)pFuncAddr + 4);FunName[0] = 'N';FunName[1] = 't';if (!_stricmp(FunName, sdName)) {//获得指定的编号ExFreePoolWithTag(pBuffer, (ULONG)"Ntdl");ZwClose(FileHandle);return uServerIndex;}//DbgPrint("Name: %s index:%d\n ", FunName, uServerIndex);//index:%d\n, uServerIndex}}ExFreePoolWithTag(pBuffer, (ULONG)"Ntdl");ZwClose(FileHandle);return 0;
}
//通过id得到函数地址
ULONGLONG GetSSDTFuncAddrById(ULONG id) {/*mov rax, rcx ;rcx=Native API 的 indexlea r10,[rdx] ;rdx=ssdt 基址mov edi,eax ;indexshr edi,7and edi,20hmov r10, qword ptr [r10+rdi]//这里得到ServiceTableBasemovsxd r11,dword ptr [r10+rax]//这里得到没有右移的假ssdt的地址mov rax,r11sar r11,4add r10,r11mov rax,r10ret*/LONG dwtmp = 0;PULONG ServiceTableBase = NULL;ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase;dwtmp = ServiceTableBase[id];dwtmp = dwtmp >> 4;return (LONGLONG)dwtmp + (ULONGLONG)ServiceTableBase;//需要先右移4位之后加上基地址,就可以得到ssdt的地址
}//NtOpenProcess
typedef NTSTATUS(NTAPI *NTOPENPROCESS)(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
NTOPENPROCESS g_ntopenprocess = NULL;extern NTSTATUS NTAPI FakeOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId);
/*
nt!NtOpenProcess:
fffff800`5d8235c0 4883ec38        sub     rsp,38h
fffff800`5d8235c4 65488b042588010000 mov   rax,qword ptr gs:[188h]
fffff800`5d8235cd 448a9032020000  mov     r10b,byte ptr [rax+232h]
fffff800`5d8235d4 4488542428      mov     byte ptr [rsp+28h],r10b
fffff800`5d8235d9 4488542420      mov     byte ptr [rsp+20h],r10b
fffff800`5d8235de e80d030000      call    nt!PsOpenProcess (fffff800`5d8238f0)
fffff800`5d8235e3 4883c438        add     rsp,38h
fffff800`5d8235e7 c3              ret
*/NTSTATUS NTAPI Hook_pfnNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) {//DbgBreakPoint();return FakeOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}typedef struct _PORT_MESSAGE{ULONG u1;ULONG u2;union{CLIENT_ID ClientId;float DoNotUseThisField;};ULONG MessageId;union{ULONG ClientViewSize;ULONG CallbackId;};
} PORT_MESSAGE, *PPORT_MESSAGE;
typedef struct _ALPC_MESSAGE_ATTRIBUTES{ULONG AllocatedAttributes;ULONG ValidAttributes;
} ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;
#define MAX_PATH 0x00000104typedef NTSTATUS(*PNTALPCSENDWAITRECEIVEPORT)(_In_ HANDLE PortHandle,_In_ ULONG  Flags,_In_reads_bytes_opt_(SendMessage->u1.s1.TotalLength) PPORT_MESSAGE     SendMessage,_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES    SendMessageAttributes,_Out_writes_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ReceiveMessage,_Inout_opt_ PSIZE_T  BufferLength,_Inout_opt_ PALPC_MESSAGE_ATTRIBUTES   ReceiveMessageAttributes,_In_opt_ PLARGE_INTEGER    Timeout);
PNTALPCSENDWAITRECEIVEPORT g_OldNtAlpcSendWaitReceivePort = NULL;
extern NTSTATUS NTAPI FakeNtAlpcSendWaitReceivePort(_In_ HANDLE PortHandle, _In_ ULONG  Flags, _In_reads_bytes_opt_(SendMessage->u1.s1.TotalLength) PPORT_MESSAGE    SendMessage, _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES   SendMessageAttributes, _Out_writes_bytes_to_opt_(*BufferLength, *BufferLength) PPORT_MESSAGE ReceiveMessage, _Inout_opt_ PSIZE_T    BufferLength, _Inout_opt_ PALPC_MESSAGE_ATTRIBUTES  ReceiveMessageAttributes, _In_opt_ PLARGE_INTEGER   Timeout);
typedef NTSTATUS(*PfnZwQueryInformationProcess) (__in HANDLE ProcessHandle, __in PROCESSINFOCLASS ProcessInformationClass, __out_bcount(ProcessInformationLength) PVOID ProcessInformation, __in ULONG ProcessInformationLength, __out_opt PULONG ReturnLength);
PfnZwQueryInformationProcess ZwQueryInformationProcess;//正则匹配
BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase){return FsRtlIsNameInExpression(Expression,Name,IgnoreCase,/*如果这里设置为TRUE,那么Expression必须是大写的*/NULL);
}
NTSTATUS  GetProcessFullNameByPid(HANDLE nPid, PUNICODE_STRING  FullPath){HANDLE               hFile = NULL;ULONG                nNeedSize = 0;NTSTATUS             nStatus = STATUS_SUCCESS;NTSTATUS             nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;PEPROCESS            Process = NULL;KAPC_STATE           ApcState = { 0 };PVOID                lpBuffer = NULL;OBJECT_ATTRIBUTES    ObjectAttributes = { 0 };IO_STATUS_BLOCK      IoStatus = { 0 };PFILE_OBJECT         FileObject = NULL;PFILE_NAME_INFORMATION FileName = NULL;WCHAR                FileBuffer[MAX_PATH] = { 0 };DECLARE_UNICODE_STRING_SIZE(ProcessPath, MAX_PATH);DECLARE_UNICODE_STRING_SIZE(DosDeviceName, MAX_PATH);PAGED_CODE();nStatus = PsLookupProcessByProcessId(nPid, &Process);if (NT_ERROR(nStatus)){DbgPrint("%s error PsLookupProcessByProcessId.\n", __FUNCTION__);return nStatus;}__try{KeStackAttachProcess(Process, &ApcState);nStatus = ZwQueryInformationProcess(NtCurrentProcess(),ProcessImageFileName,NULL,NULL,&nNeedSize);if (STATUS_INFO_LENGTH_MISMATCH != nStatus){DbgPrint("%s NtQueryInformationProcess error.\n", __FUNCTION__);nStatus = STATUS_MEMORY_NOT_ALLOCATED;__leave;}lpBuffer = ExAllocatePoolWithTag(NonPagedPool, nNeedSize, 'GetP');if (lpBuffer == NULL){DbgPrint("%s ExAllocatePoolWithTag error.\n", __FUNCTION__);nStatus = STATUS_MEMORY_NOT_ALLOCATED;__leave;}nStatus = ZwQueryInformationProcess(NtCurrentProcess(),ProcessImageFileName,lpBuffer,nNeedSize,&nNeedSize);if (NT_ERROR(nStatus)){DbgPrint("%s NtQueryInformationProcess error2.\n", __FUNCTION__);__leave;}RtlCopyUnicodeString(&ProcessPath, (PUNICODE_STRING)lpBuffer);InitializeObjectAttributes(&ObjectAttributes,&ProcessPath,OBJ_CASE_INSENSITIVE,NULL,NULL);nStatus = ZwCreateFile(&hFile,FILE_READ_ATTRIBUTES,&ObjectAttributes,&IoStatus,NULL,FILE_ATTRIBUTE_NORMAL,0,FILE_OPEN,FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,NULL,0);if (NT_ERROR(nStatus)){hFile = NULL;__leave;}nStatus = ObReferenceObjectByHandle(hFile,NULL,*IoFileObjectType,KernelMode,(PVOID*)&FileObject,NULL);if (NT_ERROR(nStatus)){FileObject = NULL;__leave;}FileName = (PFILE_NAME_INFORMATION)FileBuffer;nStatus = ZwQueryInformationFile(hFile,&IoStatus,FileName,sizeof(WCHAR)*MAX_PATH,FileNameInformation);if (NT_ERROR(nStatus)){__leave;}if (FileObject->DeviceObject == NULL){nDeviceStatus = STATUS_DEVICE_DOES_NOT_EXIST;__leave;}nDeviceStatus = RtlVolumeDeviceToDosName(FileObject->DeviceObject, &DosDeviceName);}__finally{if (NULL != FileObject){ObDereferenceObject(FileObject);}if (NULL != hFile){ZwClose(hFile);}if (NULL != lpBuffer){ExFreePool(lpBuffer);}KeUnstackDetachProcess(&ApcState);}if (NT_SUCCESS(nStatus)){RtlInitUnicodeString(&ProcessPath, FileName->FileName);if (NT_SUCCESS(nDeviceStatus)){RtlCopyUnicodeString(FullPath, &DosDeviceName);RtlUnicodeStringCat(FullPath, &ProcessPath);}else{RtlCopyUnicodeString(FullPath, &ProcessPath);}}return nStatus;
}ULONGLONG flag = 0;
extern void __fastcall lockenter(ULONGLONG *flag);
extern void __fastcall lockleave(ULONGLONG *flag);
/*
nt!NtAlpcSendWaitReceivePort:
fffff800`5d7daf00 488bc4          mov     rax,rsp
fffff800`5d7daf03 56              push    rsi
fffff800`5d7daf04 4881ecb0000000  sub     rsp,0B0h
fffff800`5d7daf0b 48895808        mov     qword ptr [rax+8],rbx
fffff800`5d7daf0f 0f57c0          xorps   xmm0,xmm0
fffff800`5d7daf12 48896810        mov     qword ptr [rax+10h],rbp
fffff800`5d7daf16 8bda            mov     ebx,edx
fffff800`5d7daf18 4c896020        mov     qword ptr [rax+20h],r12*/
NTSTATUS Hook_NtAlpcSendWaitReceivePort(HANDLE PortHandle,ULONG Flags,PPORT_MESSAGE SendMessage,PALPC_MESSAGE_ATTRIBUTES SendMessageAttributes,PPORT_MESSAGE ReceiveMessage,PSIZE_T BufferLength,PALPC_MESSAGE_ATTRIBUTES ReceiveMessageAttributes,PLARGE_INTEGER   Timeout){NTSTATUS status = NULL;ULONG g_Pid = 0;UNICODE_STRING StrProcessName = { 0 };StrProcessName.MaximumLength = MAX_PATH * sizeof(WCHAR);StrProcessName.Length = 0;WCHAR tmp[MAX_PATH] = { 0 };StrProcessName.Buffer = tmp;UNICODE_STRING uExpression = { 0 };RtlInitUnicodeString(&uExpression, L"*POWERSHELL.EXE");if (SendMessage){g_Pid = PsGetCurrentProcessId();//这里是发送消息的一方GetProcessFullNameByPid((HANDLE)g_Pid, &StrProcessName);//这里是得到当前进程的名字if (IsPatternMatch(&uExpression, &StrProcessName, TRUE)){DbgBreakPoint();//DbgPrint("aaddress %llX   Parent:%wZ\n", *(ULONGLONG *)SendMessage, &StrProcessName);}}lockenter(&flag);status = FakeNtAlpcSendWaitReceivePort(PortHandle, Flags, SendMessage, SendMessageAttributes, ReceiveMessage, BufferLength, ReceiveMessageAttributes, Timeout);lockleave(&flag);return status;//这里应该会时延
}VOID HookFunc(PVOID OrigAddress , PVOID TargetAddress) {KIRQL irql;ULONGLONG myfun;UCHAR jmp_code[] = "\x48\xB8\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF\xE0\x00\x00";//mov rax xxx,jmp raxmyfun = (ULONGLONG)TargetAddress;//替换成自己的函数地址RtlCopyMemory(jmp_code + 2, &myfun, 8);//debg();irql = WPOFFx64();RtlCopyMemory(OrigAddress, jmp_code, 12);WPONx64(irql);}VOID UnhookSSDT(PVOID org_address ,PUCHAR org_opcode,UINT32 size) {KIRQL irql;irql = WPOFFx64();RtlCopyMemory(org_address, org_opcode, size);WPONx64(irql);}#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
VOID MySleep(LONG msec){LARGE_INTEGER my_interval;my_interval.QuadPart = DELAY_ONE_MILLISECOND;my_interval.QuadPart *= msec;KeDelayExecutionThread(KernelMode, 0, &my_interval);
}VOID DriverUnload(PDRIVER_OBJECT DriverObject) {UCHAR fix_code[] = "\x48\x83\xec\x38\x65\x48\x8b\x04\x25\x88\x01\x00\x00\x44\x8a\x90\x32\x02\x00\x00";UnhookSSDT(g_ntopenprocess, fix_code,sizeof(fix_code)-1);//这里有一个\0UCHAR fix_lpc[] = "\x48\x8b\xc4\x56\x48\x81\xec\xb0\x00\x00\x00\x48\x89\x58\x08\x0f\x57\xc0";UnhookSSDT(g_OldNtAlpcSendWaitReceivePort, fix_lpc, sizeof(fix_lpc) - 1);//WMIHook.sys+0x2048//WMIHook.sys+0x1ae6//DbgBreakPoint();//这里做一个延时int i = 0;while (flag != 0) {DbgPrint("flag:   %d   \n", flag);MySleep(100);}DbgPrint("See You !\n");
}NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath) {DriverObject->DriverUnload = DriverUnload;KeServiceDescriptorTable = GetKeServiceDescriptorTable64(DriverObject);UNICODE_STRING UtrZwQueryInformationProcessName = RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");ZwQueryInformationProcess =(PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);g_ntopenprocess =GetSSDTFuncAddrById(GetIndexByName("NtOpenProcess"));//这个是用来做测试的HookFunc(g_ntopenprocess, Hook_pfnNtOpenProcess);g_OldNtAlpcSendWaitReceivePort = GetSSDTFuncAddrById(GetIndexByName("NtAlpcSendWaitReceivePort"));HookFunc(g_OldNtAlpcSendWaitReceivePort, Hook_NtAlpcSendWaitReceivePort);return STATUS_SUCCESS;
}

没什么好说的就是需要对ALPC有一点了解,我也不是很清楚就不卖弄了,例子的地址我是链接

把asm文件也带上吧,最后说一下测试的操作系统是win10 1903的

.codeEXTERN g_ntopenprocess: qword
EXTERN g_OldNtAlpcSendWaitReceivePort: qwordFakeOpenProcess    procsub     rsp,38hmov     rax,qword ptr gs:[188h]mov     r10b,byte ptr [rax+232h];处理返回地址mov     rax,g_ntopenprocessadd     rax,14hpush    rax;mov     rax,qword ptr gs:[188h];mov     r10b,byte ptr [rax+232h]retFakeOpenProcess    endpFakeNtAlpcSendWaitReceivePort    procmov     rax,rsppush    rsisub     rsp,0B0hmov     qword ptr [rax+8],rbxpush    raxpush    raxmov     rax,g_OldNtAlpcSendWaitReceivePortadd     rax,0fhmov     [rsp+8],raxpop     raxretFakeNtAlpcSendWaitReceivePort    endplockenter    procmov rax,1lock add  [rcx],raxretlockenter    endplockleave    procmov rax,1lock sub  [rcx],raxretlockleave    endpend

获取Powershell命令行参数相关推荐

  1. linux命令行如何上翻,Linux学习教程-获取可用命令行参数 or 文件上下翻转和左右翻转...

    导读 前面使用的,有几个用到了参数如ls -l, head -n 6等,需要注意的是跟参数之间要有空格. 获取可用命令行参数 终端运行man ls可以查看ls所有可用的参数,上下箭头翻页,按q退出查看 ...

  2. python 命令行参数-Python命令行参数处理

    sys模块 sys模块代表了Python解释器,主要用于获取和Python解释器相关的信息,其中 sys.argv 可以获取命令行参数 在Python交互式解释器中可以先导入sys模块 import ...

  3. python 命令行参数-Python3之命令行参数处理

    toc sys模块 sys模块代表了Python解释器,主要用于获取和Python解释器相关的信息,其中 sys.argv 可以获取命令行参数 在Python交互式解释器中可以先导入sys模块 imp ...

  4. Golang系列:打印命令行参数

    记得最早在学校机房学习 Java 时,照着书上的例子,写一个最简单 main 方法,当程序运行并在屏幕上打印出 hello world 时,内心竟有种莫名的激动,相信很多人都有这种经历吧. 不管学什么 ...

  5. python命令行输入参数_Python命令行参数处理

    sys模块 sys模块代表了Python解释器,主要用于获取和Python解释器相关的信息,其中 sys.argv 可以获取命令行参数 在Python交互式解释器中可以先导入sys模块 import ...

  6. Python教程:命令行参数处理

    sys模块 sys模块代表了Python解释器,主要用于获取和Python解释器相关的信息,其中 sys.argv 可以获取命令行参数 在Python交互式解释器中可以先导入sys模块 import ...

  7. python命令行参数 空格_Python - 命令行参数

    前言 每个脚本或者命令行程序都可以输入一些参数,通常有两种规范. 短格式,"-"号后面要紧跟一个选项字母,如果还有此选项的附加参数,可以用空格分开,也可以不分开,长度任意,可以用引 ...

  8. .NET/C# 获取一个正在运行的进程的命令行参数

    在自己的进程内部,我们可以通过 Main 函数传入的参数,也可以通过 Environment.GetCommandLineArgs 来获取命令行参数. 但是,可以通过什么方式来获取另一个运行着的程序的 ...

  9. 不出现php version网页_php冷知识 - 从命令行参数列表中获取选项

    分享一个php的冷知识 - ,从命令行参数列表中获取选项 用到的函数是getopt 说明 函数签名是这样的 getopt ( string $options [, array $longopts [, ...

最新文章

  1. Java8新特性整理篇
  2. java book打印机_Java调用打印机进行打印
  3. 我司那产品经理丨第二期
  4. JavaScript事件绑定的方法说明 收藏
  5. JZOJ 5421. 【NOIP2017提高A组集训10.25】嘟嘟噜
  6. POJ - 3614 Sunscreen(贪心/二分图最大匹配-多重匹配/网络流-最大流)
  7. Effective Java之利用有限制通配符提升API的灵活性(二十八)
  8. sklearn自学指南(part10)--Lasso及多任务Lasso
  9. ROS2学习(十二).ROS概念 - RQt工具的使用
  10. 小孔子文章管理系统V2.0发布测试
  11. CSS hack:区分IE6 IE7 Firefox
  12. 在Windows XP下,安装VS 2010 Express For Windows Phone .
  13. C# 获取枚举的DescriptionAttribute内的字符串
  14. JavaScript基础知识(三个判断、三个循环)
  15. (01背包 排序+特判)饭卡(hdu 2546)
  16. FD.io——助你创新更高效、更灵活的报文处理方案
  17. 用xml模块方式导出多种offcie文件
  18. java semaphore 原理_Java并发编程原理与实战二十八:信号量Semaphore
  19. RTMP播放器网页互联网直播音视频流媒体播放器EasyPlayer-RTMP-iOS播放H265格式的视频源
  20. 网页点击链接,跳转qq添加好友

热门文章

  1. (WPS) 网络地理信息处理服务
  2. Urlparse模块
  3. python评分卡1_woe与IV值
  4. matlab多孔介质蒸发,确定多孔介质流动参数的格子Boltzmann方法
  5. 拼多多售后有哪些处理技巧?店盈通电商解答
  6. html默认值,html基本标签的分类及默认值
  7. 过拟合(出现原因4种,解决方案6种)
  8. DeepFaceLab小白入门(4):提取人脸图片!
  9. cad画不规则实体_cad如何绘制不规则的图形
  10. iptables匹配connlimit限制并发连接数量