EnumProcesses是PSAPI提供的导出函数,利用该函数可以在无须快照的情况下枚举进程,甚至可以枚举出一些简单的隐藏进程。本例中的枚举用到了回调过程,在回调过程中用户可以随时决定是否中断枚举,从而有效的控制枚举过程。另外,进程隐藏与否的状态也可以在回调过程的参数中取得。如果结合笔者的一篇《Win32汇编实现提升进程Debug权限的两种方法 》文章,则可以进一步扩大枚举范围。本例在XP(SP2)和Vista下测试通过。
(声明:魏滔序原创,转贴请注明出处。)
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Win32汇编实现枚举进程(PSAPI.DLL)
; Programmed by 魏滔序
; WebSite: http:
//
www.chenoe.com
; Blog: http:
//
blog.youkuaiyun.com
/
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