News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

The good old cmd.exe

Started by clamicun, February 02, 2017, 02:58:59 AM

Previous topic - Next topic

clamicun

If I use this in a cmd console
tasklist.exe /? > help.txt

it works of course

If I use this in an exefile

.data
exe_file  db "C:\windows\system32\tasklist.exe",0
param1   db "/? > help.txt",0
sei         SHELLEXECUTEINFO <?>

.code

    mov     esi,offset sei
    xor     eax,eax
    mov     SHELLEXECUTEINFO.cbSize[esi],SIZEOF SHELLEXECUTEINFO
    mov     SHELLEXECUTEINFO.fMask[esi], SEE_MASK_NOCLOSEPROCESS
    mov     SHELLEXECUTEINFO.hwnd[esi],eax
    mov     SHELLEXECUTEINFO.lpVerb[esi],offset fOpen
    mov     SHELLEXECUTEINFO.lpFile[esi],offset exe_file
    mov     SHELLEXECUTEINFO.lpParameters[esi],offset param1
    mov     SHELLEXECUTEINFO.lpDirectory[esi],eax
    mov     SHELLEXECUTEINFO.nShow[esi],SW_SHOWNORMA
    mov     SHELLEXECUTEINFO.hInstApp[esi],eax
    INVOKE ShellExecuteEx,esi

It opens tasklist.exe (returns 1 ) but does not write the textfile

Where is the secret ? 

TWell

piping belongs to console...
exe_file  db "C:\windows\system32\cmd.exe",0
param1   db "/c tasklist.exe /? > help.txt",0
...

jj2007

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init

  FileWrite "help1.txt", Launch$("C:\windows\system32\tasklist.exe /?")
  Let esi=FileRead$("help1.txt")
  PrintLine "Method A: [", Left$(esi, 200), "...] **", CrLf$, CrLf$

  Launch Chr$("C:\windows\system32\cmd.exe /c tasklist.exe /? ", 62, " help2.txt")
  Let esi=FileRead$("help2.txt")
  PrintLine "Method B: [", Left$(esi, 200), "...] **"

EndOfCode


Method A: [
TASKLIST [/S sistema [/U nomeutente [/P [password]]]]
         [/M [modulo] | /SVC | /V] [/FI filtro] [/FO formato] [/NH]

Descrizione:
    Questo strumento visualizza un elenco dei processi in ...] **


Method B: [
TASKLIST [/S sistema [/U nomeutente [/P [password]]]]
         [/M [modulo] | /SVC | /V] [/FI filtro] [/FO formato] [/NH]

Descrizione:
    Questo strumento visualizza un elenco dei processi in ...] **


;)

clamicun

TWell,
no - checked that out before. Using a computer since 1984 I am quite ok. with batch style files.

JJ, I check your code out   

clamicun

TWELL,
excuse me - your code works...
Thanks

clamicun

TWELL thanks again,

my aim was to check if mysqld.exe is running.
There are various methods to do this.

This is the shortest and easiest.

.data
exe_file db "C:\windows\system32\cmd.exe",0
param1  db "/c tasklist.exe | FINDSTR mysqld.exe > mysql.txt",0
fOpen   db "open",0

.code
start:
INVOKE ShellExecute,0,offset fOpen,offset exe_file,offset param1,NULL,SW_HIDE   
INVOKE ExitProcess,0
   
end start

If mysql.txt is empty mysqld.exe does not run

jj2007

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  .if Instr_(Launch$("tasklist.exe"), "svchost", 1)
      Inkey "There is at least one svchost active"
  .else
      Inkey "Sorry, no svchost here"
  .endif
EndOfCode


No file created. Replace svchost with mysqld.exe ...

TWell

Or just in RealBoy(tm) style#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tlhelp32.h>

BOOL FindProc(TCHAR *pszExe)
{
HANDLE hSnapShot;
PROCESSENTRY32 pEntry;
BOOL bFound = FALSE;

hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapShot) {
pEntry.dwSize = sizeof(pEntry);
if (Process32First(hSnapShot, &pEntry)) {
do {
//wsprintf(szTmp, "%d %s", pEntry.th32ProcessID, pEntry.szExeFile);
if (!lstrcmp(pEntry.szExeFile, pszExe)) {
// found it
bFound = TRUE;
break;
}
} while (Process32Next(hSnapShot, &pEntry));
}
CloseHandle(hSnapShot);
}
return bFound;
}


void __cdecl WinMainCRTStartup(void)
{
if (FindProc(TEXT("explorer.exe")))
MessageBox(0,TEXT("Found explorer.exe"),0,MB_OK);
ExitProcess(0);
}

jj2007


hutch--

With your original question, write the data to a batch file then run the batch file. Easy to do and it always works.

jj2007

One more option:

include \masm32\MasmBasic\MasmBasic.inc
  Init
  mov ecx, GetProcessArray(?)
  .Repeat
      dec ecx
      .Break .if Sign?
  .Until Instr_(MbProc$(ecx), "\Explorer.exe", 1)
  .if Sign?
      Inkey "Explorer not found"
  .else
      Inkey "Process found: ", MbProc$(ecx)
  .endif
EndOfCode

Vortex

Tested with the Cygwin terminal :

$ tasklist | grep explorer.exe
explorer.exe                   688 Console                    0     44.884 K

adeyblue

Quote from: TWell on February 02, 2017, 07:59:27 AM
Or just in RealBoy(tm) style
Let's round it out with the Puts-hairs-on-your-chest-Real-Men(TM) method in C++ & WMI  :P

Just so I'm not reiterating things above, and to make it maybe a bit useful, this also includes how to be notified of new and ending processes without manually checking for them yourself. That functionality requires running the program as admin though. There is a method that doesn't require admin, but I haven't done it this way before so I chose this over that.


#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <ole2.h>
#include <wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

#define CHECK_HR_AND_RETURN(x) \
    if(FAILED(hr = (x))) \
    { \
        printf(#x " failed with hr=%x\n", hr); \
        return 1; \
    }

#define CHECK_HR(x) \
    if(FAILED(hr = (x))) \
    { \
        printf(#x " failed with hr=%x\n", hr); \
    }

#define CONCAT_INT(a, b) a##b
#define CONCAT(a, b) CONCAT_INT(a, b)

#define STACK_BSTR(contents, varName) \
    struct CONCAT(StackBStr, __COUNTER__) \
    { \
        ULONG bstrSize; \
        WCHAR text[sizeof(contents) / sizeof(WCHAR)]; \
        operator BSTR() {return text;} \
    } varName = {sizeof(contents), contents}

class ProcessNotifier : public IWbemObjectSink
{
    STDMETHOD(QueryInterface)(REFIID iid, PVOID* ppv)
    {
        *ppv = NULL;
        if(iid == IID_IUnknown || iid == IID_IWbemObjectSink)
        {
            AddRef();
            *ppv = this;
        }
        return *ppv ? S_OK : E_NOINTERFACE;
    }
    // Implement proper ref counting if using for more than this
    STDMETHOD_(ULONG, AddRef) () { return 1; }
    STDMETHOD_(ULONG, Release) () { return 1; }
    STDMETHOD(Indicate)(long numObjs, IWbemClassObject** ppObjs)
    {
        if(numObjs == 0 || ppObjs == NULL) return WBEM_E_INVALID_PARAMETER;
        for(long i = 0; i < numObjs; ++i)
        {
            if(IWbemClassObject* pProc = ppObjs[i])
            {
                HRESULT hr;
                VARIANT vName = {VT_EMPTY}, vCmdLine = {VT_EMPTY}, vPid = {VT_EMPTY};
                CIMTYPE type;
                hr = pProc->Get(L"Name", 0, &vName, &type, NULL);
                hr = pProc->Get(L"CommandLine", 0, &vCmdLine, &type, NULL);
                hr = pProc->Get(L"ProcessId", 0, &vPid, &type, NULL);
                printf("Found existing pid %lu, %ws (%ws)\n", V_UI4(&vPid), V_BSTR(&vName), V_BSTR(&vCmdLine));
                VariantClear(&vName);
                VariantClear(&vCmdLine);
                VariantClear(&vPid);
            }
        }
        return WBEM_S_NO_ERROR;
    }

    STDMETHOD(SetStatus)(long, HRESULT hr, BSTR param, IWbemClassObject*)
    {
        if(hr == WBEM_E_CALL_CANCELLED)
        {
            puts("Ending notifications for process enum");
        }
        else if(hr != WBEM_S_NO_ERROR)
        {
            printf(__FUNCTION__ " called with param=%ws, hr=%#08x\n", param, hr);
        }
        return WBEM_S_NO_ERROR;
    }
};

class ProcessChangeNotifier : public ProcessNotifier
{
    IWbemServices* pServices;
public:
    ProcessChangeNotifier(IWbemServices* pSvc) : pServices(pSvc) {}
    STDMETHOD(Indicate)(long numObjs, IWbemClassObject** ppObjs)
    {
        if(numObjs == 0 || ppObjs == NULL) return WBEM_E_INVALID_PARAMETER;
        // offset to --- is hardcoded below, change that if changing this
        // have to use Handle (aka the PID) to find the process, since it's
        // the 'key property', whatever that means
        STACK_BSTR(L"Win32_Process.Handle=\"------------", parentPath);
        for(long i = 0; i < numObjs; ++i)
        {
            if(IWbemClassObject* pProc = ppObjs[i])
            {
                HRESULT hr, hrExitCode;
                VARIANT vName, vPid, vExitCode;
                CIMTYPE type;
                hrExitCode = pProc->Get(L"ExitStatus", 0, &vExitCode, &type, NULL);
                hr = pProc->Get(L"ProcessName", 0, &vName, &type, NULL);
                hr = pProc->Get(L"ProcessId", 0, &vPid, &type, NULL);
                if(SUCCEEDED(hrExitCode))
                {
                    // this is a stopped process
                    printf("Process %ws (PID %lu) exited with code %lu\n", V_BSTR(&vName), V_UI4(&vPid), V_UI4(&vExitCode));
                    VariantClear(&vExitCode);
                }
                else
                {
                    // this is a created process
                    VARIANT vParentId, vParentName = {VT_EMPTY};
                    hr = pProc->Get(L"ParentProcessID", 0, &vParentId, &type, NULL);

                    _snwprintf(parentPath.text + 22, 11, L"%lu\"", V_UI4(&vParentId));
                    IWbemClassObject* pParentProcess = NULL;
                    // apparently calling into WMI from Indicate is bad, I don't care
                    if(SUCCEEDED(hr = pServices->GetObject(parentPath, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pParentProcess, NULL)))
                    {
                        hr = pParentProcess->Get(L"Name", 0, &vParentName, &type, NULL);
                        pParentProcess->Release();
                    }
                    PCWSTR pParentName = (V_VT(&vParentName) == VT_BSTR) ? V_BSTR(&vParentName) : L"Unknown";
                    printf("Process %ws (%lu) created by process %ws\n", V_BSTR(&vName), V_UI4(&vPid), pParentName);
                    VariantClear(&vParentName);
                    VariantClear(&vParentId);
                }
                VariantClear(&vName);
                VariantClear(&vPid);
            }
        }
        return WBEM_S_NO_ERROR;
    }

    STDMETHOD(SetStatus)(long, HRESULT hr, BSTR param, IWbemClassObject*)
    {
        if(hr == WBEM_E_CALL_CANCELLED)
        {
            puts("Ending process start/stop notifications");
        }
        else if(hr != WBEM_S_NO_ERROR)
        {
            printf(__FUNCTION__ " called with param=%ws, hr=%#08x\n", param, hr);
        }
        return WBEM_S_NO_ERROR;
    }
};

int __cdecl main(int, char**)
{
    HRESULT hr;
    CHECK_HR_AND_RETURN(CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE));
    CHECK_HR_AND_RETURN(
        CoInitializeSecurity(
            NULL,
            -1,
            NULL,
            NULL,
            RPC_C_AUTHN_LEVEL_DEFAULT,
            RPC_C_IMP_LEVEL_IMPERSONATE,
            NULL,
            EOAC_DISABLE_AAA,
            NULL
        )
    );
    IWbemLocator* pLocator = NULL;
    CHECK_HR_AND_RETURN(CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pLocator)));
    STACK_BSTR(L"root\\cimv2", cimName);
    IWbemServices* pNamespace = NULL;
    CHECK_HR_AND_RETURN(pLocator->ConnectServer(cimName, NULL, NULL, NULL, 0, NULL, NULL, &pNamespace));
    pLocator->Release();
    CHECK_HR_AND_RETURN(CoSetProxyBlanket(pNamespace, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE));

    STACK_BSTR(L"WQL", wql);
    STACK_BSTR(L"SELECT * From Win32_Process", processQuery);
    STACK_BSTR(L"SELECT * From Win32_ProcessStartTrace", newProcessQuery);
    STACK_BSTR(L"SELECT * From Win32_ProcessStopTrace", deadProcessQuery);
    ProcessNotifier procNotifier;
    CHECK_HR_AND_RETURN(pNamespace->ExecQueryAsync(wql, processQuery, 0, NULL, &procNotifier));
    ProcessChangeNotifier newProcNotifier(pNamespace);
    // these two will fail with WBEM_E_ACCESS_DENIED unless running as admin
    CHECK_HR(pNamespace->ExecNotificationQueryAsync(wql, newProcessQuery, 0, NULL, &newProcNotifier));
    CHECK_HR(pNamespace->ExecNotificationQueryAsync(wql, deadProcessQuery, 0, NULL, &newProcNotifier));
    puts("Press enter to exit");
    getchar();
    pNamespace->CancelAsyncCall(&newProcNotifier);
    pNamespace->CancelAsyncCall(&procNotifier);
    pNamespace->Release();
    CoUninitialize();
}

jj2007

Quote from: adeyblue on February 04, 2017, 06:06:55 AMLet's round it out with the Puts-hairs-on-your-chest-Real-Men(TM) method in C++ & WMI  :P

Just so I'm not reiterating things above, and to make it maybe a bit useful, this also includes how to be notified of new and ending processes without manually checking for them yourself.

Great code :t

In the meantime, I've implemented a lean-and-mean FindProcess() macro based on Tim's example, see here.