Author Topic: The good old cmd.exe  (Read 5108 times)

clamicun

  • Member
  • ***
  • Posts: 355
The good old cmd.exe
« on: February 02, 2017, 02:58:59 AM »
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

  • Member
  • ****
  • Posts: 748
Re: The good old cmd.exe
« Reply #1 on: February 02, 2017, 04:18:48 AM »
piping belongs to console
Code: [Select]
...
exe_file  db "C:\windows\system32\cmd.exe",0
param1   db "/c tasklist.exe /? > help.txt",0
...

jj2007

  • Member
  • *****
  • Posts: 11550
  • Assembler is fun ;-)
    • MasmBasic
Re: The good old cmd.exe
« Reply #2 on: February 02, 2017, 04:26:50 AM »
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


Code: [Select]
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

  • Member
  • ***
  • Posts: 355
Re: The good old cmd.exe
« Reply #3 on: February 02, 2017, 06:02:40 AM »
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

  • Member
  • ***
  • Posts: 355
Re: The good old cmd.exe
« Reply #4 on: February 02, 2017, 06:13:07 AM »
TWELL,
excuse me - your code works...
Thanks

clamicun

  • Member
  • ***
  • Posts: 355
Re: The good old cmd.exe
« Reply #5 on: February 02, 2017, 06:58:28 AM »
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

  • Member
  • *****
  • Posts: 11550
  • Assembler is fun ;-)
    • MasmBasic
Re: The good old cmd.exe
« Reply #6 on: February 02, 2017, 07:34:52 AM »
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

  • Member
  • ****
  • Posts: 748
Re: The good old cmd.exe
« Reply #7 on: February 02, 2017, 07:59:27 AM »
Or just in RealBoy(tm) style
Code: [Select]
#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

  • Member
  • *****
  • Posts: 11550
  • Assembler is fun ;-)
    • MasmBasic
Re: The good old cmd.exe
« Reply #8 on: February 02, 2017, 08:09:04 AM »
 :t

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 8492
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: The good old cmd.exe
« Reply #9 on: February 02, 2017, 10:13:18 AM »
With your original question, write the data to a batch file then run the batch file. Easy to do and it always works.
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :skrewy:

jj2007

  • Member
  • *****
  • Posts: 11550
  • Assembler is fun ;-)
    • MasmBasic
Re: The good old cmd.exe
« Reply #10 on: February 02, 2017, 12:00:46 PM »
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

  • Member
  • *****
  • Posts: 2583
Re: The good old cmd.exe
« Reply #11 on: February 03, 2017, 05:20:56 AM »
Tested with the Cygwin terminal :

Code: [Select]
$ tasklist | grep explorer.exe
explorer.exe                   688 Console                    0     44.884 K

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: The good old cmd.exe
« Reply #12 on: February 04, 2017, 06:06:55 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.

Code: [Select]
#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

  • Member
  • *****
  • Posts: 11550
  • Assembler is fun ;-)
    • MasmBasic
Re: The good old cmd.exe
« Reply #13 on: February 08, 2017, 03:03:42 AM »
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.

Great code :t

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