2013年1月25日星期五
64位驱动的asm与c混合编程
64位汇编的驱动环境的搭建就不说了。
汇编文件如下:
.data
EXTERN OrigKeBugCheckExRestorePointer:PROC
EXTERN KeBugCheckExHookPointer:PROC
.code
;
; Points the stack pointer at the supplied argument and returns to the caller.
;
public AdjustStackCallPointer
AdjustStackCallPointer PROC
mov rsp, rcx
xchg r8, rcx
jmp rdx
AdjustStackCallPointer ENDP
;
; Wraps the overwritten preamble of KeBugCheckEx.
;
public OrigKeBugCheckEx
OrigKeBugCheckEx PROC
mov [rsp+8h], rcx
mov [rsp+10h], rdx
mov [rsp+18h], r8
lea rax, [OrigKeBugCheckExRestorePointer]
jmp qword ptr [rax]
OrigKeBugCheckEx ENDP
END
编译命令:
ml64 lib.asm
link /lib lib.obj
上面可能有一些警告(我用ida64打开一看少了一个函数),我忽略了。请高手指点。
c文件如下:
#include <ntddk.h>
#include <ntifs.h>
#include <wdm.h>
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
// Both of these routines reference the assembly code described above
extern VOID OrigKeBugCheckEx(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR
BugCheckParameter4);
extern VOID AdjustStackCallPointer(IN ULONG_PTR NewStackPointer, IN PVOID StartAddress, IN PVOID Argument);
// mov eax, ptr
// jmp eax
static CHAR HookStub[] = "\x48\xb8\x41\x41\x41\x41\x41\x41\x41\x41\xff\xe0";
// The offset into the ETHREAD structure that holds the start routine.
static ULONG ThreadStartRoutineOffset = 0;
// The pointer into KeBugCheckEx after what has been overwritten by the hook.
PVOID OrigKeBugCheckExRestorePointer;
VOID KeBugCheckExHook(IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4)
{
PUCHAR LockedAddress;
PCHAR ReturnAddress;
PMDL Mdl = NULL;
// Call the real KeBugCheckEx if this isn't the bug check code we're looking for.
if (BugCheckCode != 0x109)
{
//DebugPrint(("Passing through bug check %.4x to %p.", BugCheckCode, OrigKeBugCheckEx));
OrigKeBugCheckEx(BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4);
}
else
{
PCHAR CurrentThread = (PCHAR)PsGetCurrentThread();
PVOID StartRoutine = *(PVOID **)(CurrentThread + ThreadStartRoutineOffset);
PVOID StackPointer = IoGetInitialStack();
//DebugPrint(("Restarting the current worker thread %p at %p (SP=%p, off=%lu).", PsGetCurrentThread(), StartRoutine, StackPointer, ThreadStartRoutineOffset));
DbgPrint("拦截了0x109号蓝屏\n");
DbgPrint("Restarting the current worker thread %p at %p (SP=%p, off=%lu).\n", PsGetCurrentThread(), StartRoutine, StackPointer, ThreadStartRoutineOffset);
// Shift the stack pointer back to its initial value and call the routine.
//We subtract eight to ensure that the stack is aligned properly as thread entry point routines would expect.
AdjustStackCallPointer((ULONG_PTR)StackPointer - 0x8, StartRoutine, NULL);
}
// In either case, we should never get here.
__debugbreak();
}
VOID DisablePatchProtectionSystemThreadRoutine(IN PVOID Nothing)
{
UNICODE_STRING SymbolName;
NTSTATUS Status = STATUS_SUCCESS;
PUCHAR LockedAddress;
PUCHAR CurrentThread = (PUCHAR)PsGetCurrentThread();
PCHAR KeBugCheckExSymbol;
PMDL Mdl = NULL;
RtlInitUnicodeString(&SymbolName, L"KeBugCheckEx");
do
{
// Find the thread's start routine offset.
for (ThreadStartRoutineOffset = 0; ThreadStartRoutineOffset < 0x1000; ThreadStartRoutineOffset += 4)
{
if (*(PVOID **)(CurrentThread + ThreadStartRoutineOffset) == (PVOID)DisablePatchProtectionSystemThreadRoutine) //DisablePatchProtection2SystemThreadRoutine
break;
}
//DebugPrint(("Thread start routine offset is 0x%.4x.", ThreadStartRoutineOffset));
// If we failed to find the start routine offset for some strange reason, then return not supported.
if (ThreadStartRoutineOffset >= 0x1000)
{
Status = STATUS_NOT_SUPPORTED;
break;
}
// Get the address of KeBugCheckEx.
if (!(KeBugCheckExSymbol = MmGetSystemRoutineAddress(&SymbolName)))
{
Status = STATUS_PROCEDURE_NOT_FOUND;
break;
}
// Calculate the restoration pointer.
OrigKeBugCheckExRestorePointer = (PVOID)(KeBugCheckExSymbol + 0xf);
// Create an initialize the MDL.
if (!(Mdl = MmCreateMdl(NULL, (PVOID)KeBugCheckExSymbol, 0xf)))
{
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
MmBuildMdlForNonPagedPool(Mdl);
// Probe & Lock.
if (!(LockedAddress = (PUCHAR)MmMapLockedPages(Mdl, KernelMode)))
{
IoFreeMdl(Mdl);
Status = STATUS_ACCESS_VIOLATION;
break;
}
// Set the aboslute address to our hook.
*(PULONG64)(HookStub + 0x2) = (ULONG64)KeBugCheckExHook;
//DebugPrint(("Copying hook stub to %p from %p (Symbol %p).", LockedAddress, HookStub, KeBugCheckExSymbol));
// Copy the relative jmp into the hook routine.
RtlCopyMemory(LockedAddress, HookStub, 0xf);
// Cleanup the MDL.
MmUnmapLockedPages(LockedAddress, Mdl);
IoFreeMdl(Mdl);
} while (0);
KeBugCheckEx(0x109,0,0,0,0);//测试专用。
}
// A pointer to KeBugCheckExHook
PVOID KeBugCheckExHookPointer = KeBugCheckExHook;
NTSTATUS DisablePatchProtection()
{
OBJECT_ATTRIBUTES Attributes;
NTSTATUS Status;
HANDLE ThreadHandle = NULL;
InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
// Create the system worker thread so that we can automatically find the offset inside the ETHREAD structure to the thread's start routine.
Status = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &Attributes, NULL, NULL, DisablePatchProtectionSystemThreadRoutine, NULL);
if (ThreadHandle)
ZwClose(ThreadHandle);
return Status;
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
//KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
DisablePatchProtection();
return 0;
}
关键是在source文件里面加入一行:
TARGETLIBS=lib.lib
那个文件也要复制到相应的位置。与源文件在一个目录里面。
键入bld
enter!
ok!
你看效果吧。
顺便说一下破除PatchGuard的思路:
1.改变或者添加启动模式,如安全,调试,签名等。
2.替换内核文件,那就是吧加载PatchGuard的机制给去掉。
3.从定时器队列中摘除,我没有试验成功,代码没有编译过。
4.就是本文的用到的KeBugCheckEx Hook。
5.异常处理,参考:http://uninformed.org/index.cgi?v=3&a=3&p=16
6.一些hook库。
7.其他,等你告诉我。
注释:隐藏进程的摘链,inline hook都会被PatchGuard发现。
/////////////////////////////////////////////////////////////////////
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
其实还有更简单的:
第一个办法:
在source文件中直接加入:
AMD64_SOURCES = amd64\asm.asm #这是64位的,32位的可以改为I386_SOURCES
但是SOURCES里面就不要再加入asm.asm了。
第二个办法:
工程目录下新建一个名为amd64的文件夹,里面放置汇编文件,
然后再source里面直接添加汇编文件即可。
注意:
如果出现下面的情况:
1>d:\winddk\work\c\amd64\asm.asm(1) : error A2039:line too long
1>d:\winddk\work\c\amd64\asm.asm(1) : error A2088:END directive required at end of file
google一下说是某个版本的ml.exe问题,可能后来改进了。解决办法是:
用系统自带的记事本打开文件,一看源代码只有一行。注释:用别的编辑工具都是好好的。
在记事本里面手工格式化代码就ok!
made by correy
2013.02.18添加。
2013年1月23日星期三
ml64.asm
64位汇编怎能不会。
以前以为64位汇编和32位汇编差不多,学好32位汇编就可以了。
直到用到了,才知道还有点小麻烦。
最主要的是环境的搭建.
支持64位汇编的环境有好几个,这里就不列举了。
因为是Windows上的编程,所以要首选ml64.exe了。
暂时没有发现微软的64位汇编环境,也许孤陋寡闻,也许懒得搜索。
知道masm32的原理,那就自己来吧!
所有的产品来自微软,如:mvs,sdk,wdk,所以需要先安装以上的东西。
收集过程就不说了,假定你已经熟悉mvs和masm32了。
罗嗦一句,那些东西要来自64位的目录。
具体的编写与编译有点小区别,这就令当别论了。
实验一下:
; Sample x64 Assembly Program
; Chris Lomont 2009 www.lomont.org
extrn ExitProcess: PROC ; external functions in system libraries
extrn MessageBoxA: PROC
.data
caption db '64-bit hello!', 0
message db 'Hello World!', 0
.code
Start PROC
sub rsp,28h ; shadow space, aligns stack
mov rcx, 0 ; hWnd = HWND_DESKTOP
lea rdx, message ; LPCSTR lpText
lea r8, caption ; LPCSTR lpCaption
mov r9d, 0 ; uType = MB_OK
call MessageBoxA ; call MessageBox API function
mov ecx, eax ; uExitCode = MessageBox(...)
call ExitProcess
Start ENDP
End
编译命令:ml64 hello.asm /link /subsystem:windows /defaultlib:kernel32.lib /defaultlib:user32.lib /entry:Start
从此开始我的64位汇编之旅。
汇编很少用,有时候必须用(或者用变相的方式),因为64位不支持内联汇编。
其实最根本的还是汇编,因为机器运行的是指令,相信汇编,坚信!
2013年1月20日星期日
GetActiveProcessLinksOffset.C
/*
这篇文件本想命名为PsActiveProcessHead.C的,改名为:GetActiveProcessLinksOffset.C吧!
PsActiveProcessHead 内核没有导出这个变量,微软更没有公开,只在一个结构及一些函数中用到了。
定义在:_KDDEBUGGER_DATA64,_KDDEBUGGER_DATA32结构。
#define DEBUG_DATA_PsActiveProcessHeadAddr 80
ULONG64
ExtNtOsInformation::GetKernelProcessListHead(void)
{
return GetNtDebuggerData(DEBUG_DATA_PsActiveProcessHeadAddr,"nt!PsActiveProcessHead",0);
}
以上定义在:engextcpp.cpp,wdbgexts.h,dbgeng.h,WDBGEXTS.H中。
以前觉得能操作内核结构,如:e(k)process,就是牛屄的高手。
慢慢发现这是硬编码,不通用。
后来感觉应该听微软的话,不公开就不用,用操作之的函数,或者别的理论。
但是有时后必须用之,这是下下策。
以前也见过获取eprocees中ActiveProcessLinks成员的偏移量的。
受之启发,几个月后有了自己的思路(方法),有了此文。
此文是获取eprocees中ActiveProcessLinks成员的偏移量的两个办法(函数),力求各个Windows的版本通用,包括32位与64位的。
方法一是:检测ActiveProcessLinks处的有效性,变化之后可得到eprocess,然后检查。
方法二是:通过两个特定进程的关系,如:idle和system,但是idle的eprocess的获取需要汇编,所以放弃。
system的eprocess的下一个ActiveProcessLinks一般是smss.exe(第一个进程,应该也只用一个)。
然后比较特定的值,如地址(本办法使用),或者名字等。
本文编译有几个Warnings,正式使用,请去掉。
made by correy
made at 2013.01.20
QQ:112426112
Email:kouleguan at hotmail dot com
Homepage:http://correy.webs.com
*/
#include <ntddk.h>
#include <ntifs.h>
#include <wdm.h>
extern PEPROCESS PsInitialSystemProcess;
DRIVER_UNLOAD Unload;
VOID Unload(__in PDRIVER_OBJECT DriverObject)
{
}
int GetPsActiveProcessHead1()
{
unsigned int x = 0;
HANDLE h,h2;
EPROCESS tem_PEPROCESS;
NTSTATUS r;
PEPROCESS CurrentProcess = PsGetCurrentProcess();//用当前的吧!
int b;
int n = 0;
KIRQL OldIrql;
#ifdef _X86_
unsigned int y;
#endif
#if defined(_AMD64_) || defined(_IA64_)
unsigned __int64 y;
#endif
//代码开始
KeRaiseIrql(APC_LEVEL, &OldIrql);
for (x = 8; x<10000; x +=8) //经验所得是8的倍数。eproceess的结构大小不会超过10000。
{
if (x == 0x188) //测试专用。
{
//KdBreakPoint();
}
y =
#ifdef _X86_
(unsigned int)
#endif
#if defined(_AMD64_) || defined(_IA64_)
(unsigned __int64)
#endif
CurrentProcess + x;
y =
#ifdef _X86_
*(unsigned int *)
#endif
#if defined(_AMD64_) || defined(_IA64_)
*(unsigned __int64 *)
#endif
y;
y -= x;
__try
{
//#ifdef _X86_
// ProbeForRead(y, sizeof (unsigned int), sizeof (unsigned int)); //IRQL <= APC_LEVEL
//#endif
//#if defined(_AMD64_) || defined(_IA64_)
// ProbeForRead(y, sizeof (unsigned __int64), sizeof (unsigned __int64));
//#endif
//必须用MmIsAddressValid,尽管微软已经不建议使用。因为ProbeForRead只检测用户称的。注意IRQL <= APC_LEVEL
if (!MmIsAddressValid(y))
{
continue;
}
h = PsGetProcessId(y);//这家伙不检查错误,返回正确不?用异常。
}
__except (1)
{
continue;
}
b = (int)h%4;
if (8 >= h || h >10000 || b != 0)
{
continue;
}
r = PsLookupProcessByProcessId(h,&tem_PEPROCESS);
h2 = PsGetProcessId(y);//这个条件还加不加,多余?
if (r != STATUS_INVALID_PARAMETER && h == h2) // && 不再加附加的验证条件了。
{
DbgPrint("0x%x\n", x);
ObDereferenceObject(tem_PEPROCESS);//必须调用,在某些情况下会死锁,建议使用ObReferenceObjectByHandle
#ifdef _X86_
KeLowerIrql(OldIrql);
return x;
#endif
#if defined(_AMD64_) || defined(_IA64_)
n++;
if (n == 2) //第一个是kprocess的ProcessListEntry。
{
KeLowerIrql(OldIrql);
return x;
}
#endif
}
}
KeLowerIrql(OldIrql);
return -1;//失败返回-1.应该不会返回这里。
}
extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C"
HANDLE GetPidFromProcessName(char * ProcessName)
{
PEPROCESS Process;
int h;
CHAR * pName;
STRING s1,s2;
KIRQL OldIrql;
KeRaiseIrql(APC_LEVEL, &OldIrql);
for (h = 0; h < 10000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。
{
if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER)
{
pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。
//如果pName不可以访问,请退出,不然蓝屏。 解决办法是下面加异常处理
__try
{
if (!MmIsAddressValid(pName))
{
continue;
}
RtlInitString(&s1, pName);
RtlInitString(&s2, ProcessName);
}
__except (1)
{
continue;
}
//ObDereferenceObject(Process);//加这一行蓝屏。
if (RtlEqualString(&s1, &s2, 1))
{
DbgPrint("pid == %08d\n",h);
KeLowerIrql(OldIrql);
return (HANDLE)h;
}
}
}
KeLowerIrql(OldIrql);
return (HANDLE)-1;
}
int GetPsActiveProcessHead2()
{
unsigned int x = 0;
PEPROCESS system_eprocess,smss_eprocess;
int b;
int n = 0;
HANDLE h_system,h_smss;
#ifdef _X86_
unsigned int y;
#endif
#if defined(_AMD64_) || defined(_IA64_)
unsigned __int64 y;
#endif
//代码开始
h_system = GetPidFromProcessName("system");
h_smss = GetPidFromProcessName("smss.exe");
if (h_system == -1 || h_smss == -1)
{
return -1;
}
if (PsLookupProcessByProcessId(h_system, & system_eprocess) == STATUS_INVALID_PARAMETER ||
PsLookupProcessByProcessId(h_smss, & smss_eprocess) == STATUS_INVALID_PARAMETER)
{
return -1;
}
for (x = 8; x<10000; x +=8) //经验所得是8的倍数。eproceess的结构大小不会超过10000。
{
__try
{
y =
#ifdef _X86_
(unsigned int)
#endif
#if defined(_AMD64_) || defined(_IA64_)
(unsigned __int64)
#endif
system_eprocess + x;
y =
#ifdef _X86_
*(unsigned int *)
#endif
#if defined(_AMD64_) || defined(_IA64_)
*(unsigned __int64 *)
#endif
y; //主要是看这里的内容可以访问不?其实这里没有问题。
y -= x;
if (y == smss_eprocess)
{
DbgPrint("0x%x\n", x);
#ifdef _X86_
return x;
#endif
#if defined(_AMD64_) || defined(_IA64_)
n++;
if (n == 2) //第一个是kprocess的ProcessListEntry。
{
return x;
}
#endif
}
}
__except (1)
{
continue;
}
}
ObDereferenceObject(system_eprocess);
ObDereferenceObject(smss_eprocess);
return -1;//失败返回-1.应该不会返回这里。
}
DRIVER_INITIALIZE DriverEntry;
NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
unsigned __int64 PsActiveProcessHead = 0;
unsigned __int64 t;
PEPROCESS Process; //看看和t相等不?
KSPIN_LOCK SpinLock;
KIRQL OldIrql;
KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint()
DriverObject->DriverUnload = Unload;
PsLookupProcessByProcessId(4, & Process);
t = PsInitialSystemProcess;//断定这个是错误的,和Process不一样,进程的名字为空。
//DbgPrint("PsInitialSystemProcess == 0x%16x\n", PsInitialSystemProcess);
//KeInitializeSpinLock(&SpinLock);//里面用KeRaiseIrql,这里就不用了。
//KeAcquireSpinLock(&SpinLock, &OldIrql);//注意锁的使用。
PsActiveProcessHead = GetPsActiveProcessHead1();
//KeReleaseSpinLock(&SpinLock, OldIrql);
DbgPrint("ActiveProcessLinks 在 eprocess中的偏移是:0x%x\n", PsActiveProcessHead);
PsActiveProcessHead = GetPsActiveProcessHead2();
DbgPrint("ActiveProcessLinks 在 eprocess中的偏移是:0x%x\n", PsActiveProcessHead);
return 0;
}
2013年1月18日星期五
PsLookupProcessByProcessId.C
/* 本文就暂时命名为PsLookupProcessByProcessId.C吧! pid与进程名互换,很简单的问题,不削一顾,可到用的时候才知道重要。 网上很多,那是别人的。 还是自己的感觉好,完全懂,还一个修改。 made by correy made at 2013.01.18 QQ:112426112 Email:kouleguan at hotmail dot com Homepage:http://correy.webs.com If the call to PsLookupProcessByProcessId is successful, PsLookupProcessByProcessID increases the reference count on the object returned in the Process parameter. Consequently, when a driver has completed using the Process parameter, the driver must call ObDereferenceObject to dereference the Process parameter received from the PsLookupProcessByProcessID routine. */ #include <ntddk.h> #include <ntifs.h> extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C" DRIVER_UNLOAD Unload; VOID Unload(__in PDRIVER_OBJECT DriverObject) { } HANDLE GetPidFromProcessName(char * ProcessName) { PEPROCESS Process; int h; CHAR * pName; STRING s1,s2; for (h = 0; h < 10000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。 { if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER) { pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。 RtlInitString(&s1, pName); RtlInitString(&s2, ProcessName); if (RtlEqualString(&s1, &s2, 1)) { DbgPrint("pid == %08d\n",h); return (HANDLE)h; } } } return (HANDLE)-1; } char * GetProcessNameFromPid(HANDLE pid) { PEPROCESS Process; if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER) { return "pid不存在"; } DbgPrint("ProcessName is %s\n",PsGetProcessImageFileName(Process)); return (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。 } DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_UNSUCCESSFUL; HANDLE h; char * ProcessName; //KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint() DriverObject->DriverUnload = Unload; h = GetPidFromProcessName("explorer.exe"); ProcessName = GetProcessNameFromPid(h); return 0; } ////////////////////////////////////////////////////////////////////////////// //改进版,排除了死进程。有一些垃圾的东西。 /* 本文就暂时命名为PsLookupProcessByProcessId.C吧! pid与进程名互换,很简单的问题,不削一顾,可到用的时候才知道重要。 网上很多,那是别人的。 还是自己的感觉好,完全懂,还可以修改。 made by correy made at 2013.01.24 QQ:112426112 Email:kouleguan at hotmail dot com Homepage:http://correy.webs.com */ #include <ntddk.h> #include <ntifs.h> typedef struct _SYSTEM_THREAD_INFORMATION { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; LONG State; LONG WaitReason; } SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved1[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters; SYSTEM_THREAD_INFORMATION Threads[1]; } SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION; extern UCHAR *PsGetProcessImageFileName(IN PEPROCESS Process); //c++ 才需要"C" extern int PsGetProcessExitStatus(PEPROCESS Process); extern NTSTATUS ZwQuerySystemInformation( int SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength OPTIONAL); DRIVER_UNLOAD Unload; VOID Unload(__in PDRIVER_OBJECT DriverObject) { } //HANDLE GetPidFromProcessName(char * ProcessName) //int IsActiveProcess(int h) //{//枚举进程 // NTSTATUS ntStatus; // ULONG cbBuffer = 0x8000; // PVOID pBuffer = NULL; // PSYSTEM_PROCESS_INFORMATION pInfo; // UNICODE_STRING us1,us2; // // do { // pBuffer = ExAllocatePoolWithTag(NonPagedPool, cbBuffer,'tag'); // if (pBuffer == NULL) { // return 0; // } // // ntStatus = ZwQuerySystemInformation(5, pBuffer, cbBuffer, NULL); // if (ntStatus == STATUS_INFO_LENGTH_MISMATCH) { // ExFreePoolWithTag(pBuffer,'tag'); // cbBuffer *= 2; // } else if (!NT_SUCCESS(ntStatus)) { // ExFreePoolWithTag(pBuffer,'tag'); // return 0; // } // } while(ntStatus == STATUS_INFO_LENGTH_MISMATCH); // // pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer; // while(TRUE) // { // /*LPWSTR pszProcessName = pInfo->ProcessName.Buffer; // if (pszProcessName == NULL) { // pszProcessName = L"NULL"; // }*/ // // DbgPrint("pid == %08d;pname:%wZ\n", pInfo->ProcessId,pInfo->ProcessName.Buffer); // // RtlInitUnicodeString(&us1, pInfo->ProcessName.Buffer); // RtlInitUnicodeString(&us2, L"explorer.exe"); ///wgclient.exe // // if (RtlEqualUnicodeString(&us1, &us2, 1)) { // ExFreePoolWithTag(pBuffer,'tag'); // return h; // } // // /*if (pInfo->ProcessId == h) { // ExFreePoolWithTag(pBuffer,'tag'); // return h; // }*/ // // if (pInfo->NextEntryDelta == 0) { // break; // } // pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)+pInfo->NextEntryDelta); // } // // ExFreePoolWithTag(pBuffer,'tag'); //} //用ZwQueryInformationProcess ProcessBasicInformation->ExitStatus的办法没有能实现, //不用eprocess的exittime和判断ObjectTable是否为0 , //更不用ZwQuerySystemInformation的5号功能枚举。 //也没有使用peb的办法。 int IsActiveProcess(int h) { PEPROCESS Process; int ExitCode; if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER) { __try { ExitCode = PsGetProcessExitStatus(Process); if (ExitCode == 259) //这个观察所得。 { return 1; } else //等于1就是退出了。 { return 0; } } __except (1) { //这时候大多是Process是错误的。 } } return 0; } HANDLE GetPidFromProcessName(char * ProcessName) { PEPROCESS Process; int h; CHAR * pName; STRING s1,s2; KIRQL OldIrql; KeRaiseIrql(APC_LEVEL, &OldIrql); for (h = 0; h < 10000; h += 4) //由于PEPROCESS结构不公开,不采用遍历的办法,反而更通用。 { if (PsLookupProcessByProcessId((HANDLE)h, & Process) != STATUS_INVALID_PARAMETER) { pName = (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。 //如果pName不可以访问,请退出,不然蓝屏。 解决办法是下面加异常处理 //KeRaiseIrql(APC_LEVEL, &OldIrql); __try { if (!MmIsAddressValid(pName)) { continue; } RtlInitString(&s1, pName); RtlInitString(&s2, ProcessName); } __except (1) { //KeLowerIrql(OldIrql); continue; } //KeLowerIrql(OldIrql); //ObDereferenceObject(Process);//加这一行蓝屏。 if (RtlEqualString(&s1, &s2, 1)) { DbgPrint("pid == %08d\n",h); //KeLowerIrql(OldIrql); //放置在这里会运行的快一点。放到上一个if语句,运行的很慢。 //排除已经退出的进程。 if (IsActiveProcess(h)) { KeLowerIrql(OldIrql); return (HANDLE)h; } } s1.MaximumLength = 0;//释放,避免以后还运行。 s2.MaximumLength = 0; } } KeLowerIrql(OldIrql); return (HANDLE)-1; } char * GetProcessNameFromPid1(HANDLE pid) { PEPROCESS Process; if (PsLookupProcessByProcessId(pid, & Process) == STATUS_INVALID_PARAMETER) { return "pid不存在"; } DbgPrint("ProcessName is %s\n",PsGetProcessImageFileName(Process)); return (CHAR*)PsGetProcessImageFileName(Process);//未公开函数。也有替换的办法。 } DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry( __in struct _DRIVER_OBJECT * DriverObject, __in PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_UNSUCCESSFUL; HANDLE h; char * ProcessName; int b = 0; LARGE_INTEGER interval; KdBreakPoint();//#define KdBreakPoint() DbgBreakPoint() DriverObject->DriverUnload = Unload; for (;;) //主要是测试用的。 { if (b) { break; } h = GetPidFromProcessName("explorer.exe"); ProcessName = GetProcessNameFromPid1(h); interval.QuadPart = (1 * (((-10) * 1000) * 1000)); //暂停5秒钟。 KeDelayExecutionThread(KernelMode, FALSE, &interval);//这3行是新添加的. } return 0; } 还有一个种微软公开,但过时的办法:ZwQuerySystemInformation和ZwQueryInformationProcess
2013年1月6日星期日
QueryPerformanceCounter.Cpp
/*
QueryPerformanceCounter.Cpp
本文开启我的算法之旅.
c的c++(stl)的.
排序(升降)
查找(最大,最小,特定)
还有树,图等.
不停的更新改进中.
没有考虑效率,也不是最优秀的算法,关键是能实现.
*/
#include <windows.h>
//也可以考虑用链表.
int x[100] = {};//100个元素,最后一个的索引是99.
void init ()
{
LARGE_INTEGER counter;
for (int i = 0;i<100;i++)
{
//Sleep(0);//不加这个会重复,加这个相差为1.
Sleep(i);//这个效果比较好.
QueryPerformanceCounter(&counter);//失败的可能性很小,不考虑了.
x[i] = counter.QuadPart % 1000;//这个没有重复的,在双核的cpu上.
//x[i] = GetTickCount() % 1000;//这个有一些是重复的.
//x[i] = GetTickCount64() % 1000;//这个有一些是重复的.
}
}
void ergodic()
{
for (int i = 0;i<100;i++)
{
printf("%4d\n", x[i]);
}
}
int find_max()
{
int m = 0;
for (int i = 0;i<100;i++)
{
if (m <= x[i])
{
m = x[i];
}
}
return m;
}
int find_min()
{
int m = x[0];
for (int i = 0;i<100;i++)
{
if (m >= x[i])
{
m = x[i];
}
}
return m;
}
int find(int n)
{
//返回索引,如果找不到返回-1.
unsigned int m = -1;
for (int i = 0;i<100;i++)
{
if (n == x[i])
{
return i;
}
}
return m;
}
void sort_up()
{
for (int j = 0;j<100;j++)
{
for (int i = 0;i<100-1;i++)
{
if (x[i] > x[i+1])
{
int t = x[i];
x[i] = x[i+1];
x[i+1] = t;
}
}
}
}
void sort_down()
{
for (int j = 0;j<100;j++)
{
for (int i = 0;i<100;i++)
{
if (x[i] < x[i+1])
{
int t = x[i];
x[i] = x[i+1];
x[i+1] = t;
}
}
}
}
int main()
{
int r = 0;
init();
ergodic();
r = find_max();//返回最大的.
printf("最大是:%4d\n", r);
r = find_min();//返回最小的.
printf("最小是:%4d\n", r);
int n = x[99];
r = find(n);//查询索引.
sort_up();//升序,从小到大
sort_down(); //降序,从大到小
}
订阅:
博文 (Atom)