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
; 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