EnumProcesses是PSAPI提供的导出函数,利用该函数可以在无须快照的情况下枚举进程,甚至可以枚举出一些简单的隐藏进程。本例中的枚举用到了回调过程,在回调过程中用户可以随时决定是否中断枚举,从而有效的控制枚举过程。另外,进程隐藏与否的状态也可以在回调过程的参数中取得。如果结合笔者的一篇《Win32汇编实现提升进程Debug权限的两种方法 》文章,则可以进一步扩大枚举范围。本例在XP(SP2)和Vista下测试通过。
(声明:魏滔序原创,转贴请注明出处。)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Win32汇编实现枚举进程(PSAPI.DLL)
; Programmed by 魏滔序
; WebSite: http://www.chenoe.com
; Blog: http://blog.csdn.net/Modest
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
.486 ; create 32 bit code
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include windows.inc
include psapi.inc
include kernel32.inc
includelib psapi.lib
includelib kernel32.lib
include user32.inc
includelib user32.lib
EnumProcs proto :DWORD
CallProc Proto :DWORD,:DWORD,:DWORD,:DWORD
.data
szPSAPI db 'psapi.dll',0
szGetProcessImageFileNameA db 'GetProcessImageFileNameA',0
text db '%d',0
.code
Start:

invoke EnumProcs,addr CallProc
invoke ExitProcess,0

EnumProcs Proc dwCallProc
LOCAL dwProcs[1023], dwProcCount
LOCAL cbNeeded, dwPID
LOCAL hProcess, hModule, szName[MAX_PATH]:BYTE
LOCAL i, dwHide,dwCancel

Invoke EnumProcesses,addr dwProcs, SIZEOF dwProcs,ADDR cbNeeded
.If EAX != 0

MOV EAX,cbNeeded
CDQ
MOV ECX, 4
IDIV ECX
MOV dwProcCount ,EAX

MOV dwPID,0CH
.While TRUE
Invoke OpenProcess,PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, FALSE, dwPID
MOV hProcess,EAX
.If hProcess != 0

MOV dwHide,TRUE
MOV i,0
.While TRUE
LEA EAX,dwProcs
MOV ECX,i
IMUL ECX,4
ADD EAX,ECX
MOV EAX,[EAX]
.IF dwPID == EAX
MOV dwHide,FALSE
.Break .If TRUE
.EndIf
INC i
MOV EAX,dwProcCount
.Break .IF i == EAX
.EndW
Invoke EnumProcessModules,hProcess, ADDR hModule, 4, ADDR cbNeeded
.If EAX != 0
Invoke GetModuleFileNameEx,hProcess, hModule, addr szName, MAX_PATH
MOV dwCancel,FALSE
LEA EAX,dwCancel
PUSH EAX
PUSH dwHide
LEA EAX,szName
PUSH EAX
PUSH dwPID
CALL dwCallProc
.If dwCancel==TRUE
Invoke CloseHandle,hProcess
MOV EAX,FALSE
RET
.EndIf
.Else
PUSH MAX_PATH
LEA EAX,szName
PUSH EAX
PUSH hProcess
Invoke LoadLibrary,addr szPSAPI
Invoke GetProcAddress,EAX, addr szGetProcessImageFileNameA
CALL EAX
MOV dwCancel,FALSE
LEA EAX,dwCancel
PUSH EAX
PUSH -1
LEA EAX,szName
PUSH EAX
PUSH dwPID
CALL dwCallProc
.If dwCancel==TRUE
Invoke CloseHandle,hProcess
MOV EAX,FALSE
RET
.EndIf
.EndIf
Invoke CloseHandle,hProcess
.EndIf
;
ADD dwPID,4
.Break .IF dwPID > 0FFFFH
.EndW
.EndIf
MOV EAX,TRUE
RET
EnumProcs EndP

CallProc Proc dwPID,szName,dwHide,dwCancel
LOCAL szBuffer[10]:byte

Invoke wsprintf,addr szBuffer,addr text,dwPID
Invoke MessageBox, NULL, szName,addr szBuffer,MB_OK
;以下5行用来决定是否继续枚举
mov ecx,dwCancel
assume ecx:ptr
push TRUE ;←-如果为FALSE则继续枚举,TRUE则停止,所以在本例中仅枚举出第一个进程。
pop [ecx]
assume ecx:nothing
ret
CallProc endp

End Start
发表于 @ 2008年02月01日 21:27:00|评论(loading...)|编辑