News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Can't terminate a "rogue" msiexec.exe

Started by Magnum, April 08, 2010, 10:40:59 PM

Previous topic - Next topic

Magnum

This code works fine terminating other apps, but not for msiexec.exe.
Can someone please help?

I installed the 2003 SDK.

When I deleted all the directories except the one containing the help files, then
windows has a fit and trie to re-install it when I re-log on as a limited user.

I would greatly appreciate any suggestions.

Thanks.


; Stop_Msiexec.asm
; Terminate msiexec.exe when started unnecessarily    
;
;
.586
.model flat, stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib

.data
AppName         db "Terminate",0
Problem_child   db "msiexec.exe",0

errSnapshot     db "CreateToolhelp32Snapshot failed.",0
errProcFirst    db "Process32First failed.",0

.data?
hSnapshot   HANDLE ?
ProcEnt     PROCESSENTRY32 <?>

.code
start:
   invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS,0
   .IF (eax != INVALID_HANDLE_VALUE)
       mov hSnapshot,eax
       mov [ProcEnt.dwSize],SIZEOF ProcEnt
       invoke Process32First, hSnapshot,ADDR ProcEnt
       .IF (eax)
         @@:
           invoke lstrcmpi, ADDR Problem_child ,ADDR [ProcEnt.szExeFile]
           .IF (eax == 0)
               invoke OpenProcess, PROCESS_TERMINATE,FALSE,[ProcEnt.th32ProcessID]
               .IF (eax)
                   invoke TerminateProcess, eax,0
               .ELSE
                   ;failed for some reason
               .ENDIF
           .ENDIF

           invoke Process32Next, hSnapshot,ADDR ProcEnt
           test eax,eax
           jnz @B

       .ELSE
           invoke MessageBox, NULL,ADDR errProcFirst,ADDR AppName,MB_OK or MB_ICONERROR
       .ENDIF
       invoke CloseHandle, hSnapshot
   .ELSE
       invoke MessageBox, NULL,ADDR errSnapshot,ADDR AppName,MB_OK or MB_ICONERROR
   .ENDIF
   invoke ExitProcess, NULL
end start
Have a great day,
                         Andy

dedndave

#1
if msiexec is running, it means you have an install or uninstall process in progress
you should be able to get rid of it by re-booting
i do not recommend forcing termination of msiexec.exe

Slugsnack

Check the return value, and also check to see whether your OpenProcess() call actually succeeded. Also if you succeed in obtaining a process' handle, you should close it with CloseHandle() after you are done with it.

Magnum

Quote from: dedndave on April 08, 2010, 10:43:09 PM
if msiexec is running, it means you have an install or uninstall process in progress
you should be able to get rid of it by re-booting
i do not recommend forcing termination of msiexec.exe

I got the problem fixed. I was able to just install the help files.

Have a great day,
                         Andy

akane

When the Windows Installer finds any damaged instalation, eg. deleted files, it will pop a window each time you start any (other) application installed with it.
If you delete files from an installed product, remove also all tracks from the registry (manual hardcore, not recommended)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installeror remove the whole product from MSI database using
Windows Installer Clean Up utility http://support.microsoft.com/kb/290301
Really only a small set of MSI based applications relies on the MSI database (Office, Daemon tools), but MSDN, PSDK, WDK does not, and you can safelly remove all the trash from your registry after installing it, using the tool above, as I do.

Magnum

Have a great day,
                         Andy

xandaz

   i'm experiencing problems with process enumeration. CreateToolhelp32Snapshot works fine but then i get -1 in Process32First. i did something like this

   invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,NULL
   .if eax!=-1
   mov hSnap,eax
   mov tvi.pszText,offset pe32.psz
   mov pe32.dwSize,sizeof pe32
   invoke Process32First,hSnap, addr pe32
   test eax,eax
   jnz   to_listview
  invoke



   

xandaz

   i'm experiencing problems with process enumeration. CreateToolhelp32Snapshot works fine but then i get -1 in Process32First. i did something like this

  invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,NULL
  .if eax!=-1
  mov hSnap,eax
  mov tvi.pszText,offset pe32.psz
  mov pe32.dwSize,sizeof pe32
  invoke Process32First,hSnap, addr pe32
  test eax,eax
  jnz   to_listview
 invoke SendMessage,hStatic,WM_SETTEXT,NULL,addr ErrProcess32First
 jmp end_enum
to_listview:
 invoke SendMessage,hListView,LVM_INSERTITEM,0,addr tvi

Gimme a hand will you?
bests from x



 

xandaz

   Well, i can now enumerate processes but they don't seem to close. Does anyone know how to? Do i need the OpenProcessToken thing?
   ...thanks.


Magnum

Quote from: xandaz on May 25, 2010, 05:46:57 PM
   Well, i can now enumerate processes but they don't seem to close. Does anyone know how to? Do i need the OpenProcessToken thing?
   ...thanks.


Here is a working example of how to close a program.



; killbart.asm       Tuesday, August 04, 2009
; Help from Tedd,sinsi,Nordwind64,AsmGuru62,Jongware,
;
; Terminates bartshel.exe!!
; (A badly behaved program no longer needed after connection.)
.586
.model flat,stdcall
option casemap:none

include  \masm32\include\windows.inc
include  \masm32\include\user32.inc
include  \masm32\include\kernel32.inc
include  \masm32\include\shlwapi.inc
include  \masm32\macros\macros.asm
include  \masm32\include\advapi32.inc

includelib  \masm32\lib\advapi32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\shlwapi.lib

; Local Prototypes

    IsWinNT         PROTO
    ReqNTPrivilege  PROTO :DWORD
   
.const

    dwMaskNT        DWORD   2

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

.data

   msg_NotNT   BYTE    "This is NOT an NT system.",0
   msg_NotPL   BYTE    "Privilege requested NOT granted.",0
   BoxName     BYTE    "ASM Win NT Shutdown",0
   
   ClassName    BYTE    "MainWinClass",0
   AppName      BYTE    "CLOSE THIS WINDOW!",0
   ProcessName  BYTE    "bartshel.exe",0
   successtext  BYTE    "Bartshel.exe is terminated!                                                                                          ",0
   failedtext   BYTE    "Bartshel.exe is not currently running!",0
   started      BYTE    "Bye_Bye_Bart",0

.data?

   hInstance   HINSTANCE ?
   CommandLine LPSTR     ?

.code

start:

    invoke GetModuleHandle, NULL
    mov    hInstance,eax
   
    invoke GetCommandLine
    mov    CommandLine,eax
   
    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT

    ; with ReqNTPrivilege call, we ask for the 'SeShutdownPrivilege'
    ; note string names of possible privilege are in windows.inc

    invoke  ReqNTPrivilege, SADD("SeShutdownPrivilege")
    .if eax == FALSE
      invoke  MessageBox,NULL,addr msg_NotPL,addr BoxName,MB_OK
      invoke  ExitProcess,NULL
    .endif

    invoke ExitProcess,eax
   
KillProcess proc lpszExecutable:LPSTR
    LOCAL bLoop:BOOL
    LOCAL bResult:BOOL
    LOCAL pe32:PROCESSENTRY32
    LOCAL hProcess:HANDLE
    LOCAL hProcesses:HANDLE

    mov bLoop,TRUE
    mov bResult,FALSE

    ; Returns an open handle to the specified snapshot if successful or - 1 otherwise.
    invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
    mov hProcesses,eax   

    mov pe32.dwSize,SIZEOF PROCESSENTRY32

    invoke Process32First,hProcesses,ADDR pe32
    .IF eax
        .WHILE bLoop
            invoke CompareString, LOCALE_USER_DEFAULT, NORM_IGNORECASE, addr pe32.szExeFile, -1, lpszExecutable, -1
            .IF eax==2 ; check if strings are equal in lexical value
                 
                invoke OpenProcess, PROCESS_TERMINATE, FALSE, pe32.th32ProcessID ; returns handle 

                 .IF eax!=NULL
                    mov hProcess, eax        ; Need to save the process handle to terminate
                    invoke TerminateProcess, hProcess, 0
                    invoke CloseHandle, hProcess ; fails if eax is zero
                   
                    mov bResult,TRUE;
                   
                .endif
            .endif
           ; why go on to next process ?
           invoke Process32Next, hProcesses, ADDR pe32
            ; Retrieves information about the next process recorded in a system snapshot.

            mov bLoop,eax
        .endw
        invoke CloseHandle,hProcesses
    .endif
    mov eax,bResult
    ret

KillProcess endp

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
    LOCAL wc:WNDCLASSEX
    LOCAL msg:MSG
    LOCAL hwnd:HWND
    LOCAL tc   :DWORD
   
    mov   wc.cbSize,SIZEOF WNDCLASSEX
    mov   wc.style, CS_HREDRAW or CS_VREDRAW
    mov   wc.lpfnWndProc, OFFSET WndProc
    mov   wc.cbClsExtra,NULL
    mov   wc.cbWndExtra,NULL
    push  hInstance
    pop   wc.hInstance
    mov   wc.hbrBackground,COLOR_BTNFACE+1
    mov   wc.lpszMenuName,NULL
    mov   wc.lpszClassName,OFFSET ClassName
   
    invoke LoadIcon,NULL,IDI_APPLICATION
    mov   wc.hIcon,eax
    mov   wc.hIconSm,eax
   
    invoke LoadCursor,NULL,IDC_ARROW
    mov   wc.hCursor,eax
   
   
    invoke RegisterClassEx, addr wc

    ; If I want a window off screen
    ;
    ; Replacing CW_USEDEFAULT with NULL creates a "hidden" window

    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
           WS_OVERLAPPEDWINDOW,NULL,\ ; creates a "hidden" window
           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
           hInst,NULL
    mov   hwnd,eax

    invoke ShowWindow, hwnd,SW_MINIMIZE    ;Minimal window
    invoke UpdateWindow, hwnd

     add tc,1    ; get rid of window quickly 
                 ; 2000 =  2 seconds

   
    ; loop until Tick count catches up with added time
   
    @@:
      invoke GetTickCount
        .if tc > eax
          jmp @B
        .endif
   
    ; Close screen
   
      invoke SendMessage,hwnd,WM_SYSCOMMAND,SC_CLOSE,NULL
   
    ; Loop until PostQuitMessage is sent

    StartLoop:
      invoke GetMessage,ADDR msg,NULL,0,0
      cmp eax, 0
      je ExitLoop
      invoke TranslateMessage, ADDR msg
      invoke DispatchMessage,  ADDR msg
      jmp StartLoop
    ExitLoop:
   
    mov     eax,msg.wParam
    ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   
    LOCAL bResult:BOOL
    LOCAL bLoop:BOOL

    .IF uMsg==WM_DESTROY
        invoke PostQuitMessage,NULL

    .ELSEIF uMsg==WM_CREATE
        mov eax, -1        ;FALSE
       
        mov bResult,eax
        invoke KillProcess,OFFSET ProcessName

        mov bResult,eax ;

        .IF bResult==FALSE
            invoke MessageBox,0,OFFSET failedtext,OFFSET started,MB_OK
        .ELSE
            invoke MessageBox,0,OFFSET successtext,OFFSET started,MB_OK
        .ENDIF

         mov bLoop,FALSE
                 
        ret
   
    .ELSE
        invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
        ret
    .ENDIF
   
    xor eax,eax
    ret
WndProc endp

ReqNTPrivilege proc lpPrivilegeName:DWORD

; return TRUE (not zero) in eax if privilege is granted
; lpPrivilegeName parameter points to a string with request privilege name

    LOCAL   hProcess:DWORD
    LOCAL   hToken:DWORD
    LOCAL   phToken:DWORD
    LOCAL   RetLen:DWORD
    LOCAL   pRetLen:DWORD
    LOCAL   tkp:TOKEN_PRIVILEGES
    LOCAL   tkp_old:TOKEN_PRIVILEGES
;
    invoke  GetCurrentProcess
    mov     hProcess, eax
    lea     eax, hToken
    mov     phToken, eax
    invoke  OpenProcessToken, hProcess, \
            TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, \
            phToken 
    .if eax != FALSE
      lea     eax, tkp.Privileges[0].Luid
      invoke  LookupPrivilegeValue, NULL, \
              lpPrivilegeName, \
              eax
      lea     eax, RetLen
      mov     pRetLen, eax
      mov     tkp.PrivilegeCount, 1
      mov     tkp.Privileges[0].Attributes, SE_PRIVILEGE_ENABLED
      invoke  AdjustTokenPrivileges, hToken, \
              NULL, \
              addr tkp, \
              sizeof tkp_old, \
              addr tkp_old, \
              pRetLen
    .endif
    ret
   
ReqNTPrivilege endp

end start


Have a great day,
                         Andy

xandaz

   Thanks a lot Magnum. Meanwhile i got the program working. The problem was that i was using a listview control to show all the parameters of PROCESSENTRY32. So i had to convert all things to strings and reconvert them back when a given item was chosen for termination. The reconvertion function was returning an invalid processID number so the processes didn't close.
    thanks all. You're the best
    Hail m32 forum
    Bests from X

Tedd

Andy, "SeShutdownPrivilege" only gives you rights to shutdown the machine (e.g. ExitWindows), it has no effect on whether you can kill a process or not. You can already kill most processes, as long as they are 'yours.' An administrator user should be able to kill most things, but you can't kill system processes without being the system user.

Also, there's no need for a window (hidden or otherwise) - just walk the process list and kill the required process, display a message box if necessary (use NULL as the owner), then exit.



xandaz, you can store the process-id value in lParam of the LV_ITEM structure (and set LVIF_LPARAM in the mask), and then use the value directly (no conversion from-to string!) for killing the selected process.
No snowflake in an avalanche feels responsible.

Magnum

Have a great day,
                         Andy

xandaz

   That's right Ted!!! Stupid me. Well, ... what can i say? I'm always learning. Thanks again you all and best regards.
    Hail ASM!