How to close dumpcap.exe using WinAPI? Dumpcap.exe is work by cmd.exe

93 Views Asked by At

I'm capturing packets with dumpcap.exe in a cmd.exe window:

dumpcap.exe -i 5 -w:\\Users\\xyz.abc\\Desktop\\allPacketTMC.pcapng

This capturing method works in a QT GUI. When I click the "Start LOG" button, it starts capturing packets. Below code works in QT Creator for capturing:

const char *command = "dumpcap.exe -i 5 -w:\\Users\\xyz.abc\\Desktop\\allPacketTMC.pcapng";
std::system(command);

I can close dumpcap.exe in the cmd window with Ctrl-C. But I want to close dumpcap with the Win32 API (or another method).

When I click a button, I am reading all processes with EnumProcessModules() and can show their process PIDs. But the PID of dumpcap.exe doesn't appear, so I cannot close dumpcap from my GUI.

I used QProcess to create the process in QT, but it doesn't work in an opened window.

I use the std::system() function and close dumpcap.exe from the cmd window with Ctrl-C, but I don't want to close dumpcap this way.

I searched for how to use the CreateProcess() function for creating cmd.exe from the Win32 API, but I didn't run dumpcap.exe with CreateProcess() because I didn't declare the lpCommandLine argument.

2

There are 2 best solutions below

6
Remy Lebeau On BEST ANSWER

Simply pass CreateProcess() the same command line you are passing to system(). CreateProcess() gives you a process ID you can use with GenerateConsoleCtrlEvent(), and a process handle you can use with TerminateProcess().

char command[] = "dumpcap.exe -i 5 -w:\\Users\\xyz.abc\\Desktop\\allPacketTMC.pcapng";

STARTUPINFOA si = {};
si.cb = sizeof(si);

PROCESS_INFORMATION pi = {};

if (CreateProcessA(NULL, command, NULL, NULL, FALSE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
{
    ...
    AttachConsole(pi.dwProcessID);
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, pi.dwProcessID);
    AttachConsole(ATTACH_PARENT_PROCESS);
    // or: 
    TerminateProcess(pi.hProcess, 0);
    ...
    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
}

The alternative is to not use dumpcap.exe at all. Use a library like libpcap instead and do the capturing yourself directly in your own code.

0
crazyChicken On

Thanks for your help, guys.

I don't start cmd.exe. Because dumpcap.exe can work directly for capturing packet. So that, I started dumpcap.exe with CreateProcess().

When I click the Start Button on_pushButton_StartLOG_clicked() function runs:

void MainWindow::on_pushButton_StartLOG_clicked()
{
    thread  = new QThread();
    worker  = new Worker();    
    worker->moveToThread(thread);
    connect(thread, SIGNAL(started()), worker, SLOT(capturePacket()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

And also capturePacket() functin in here:

void Worker::capturePacket(){
    TCHAR commandArgs[] = _T("dumpcap.exe -i 5 -w C:\\Users\\abc.xyz\\Desktop\\allPacket.pcapng");

    if(mCloseDumpcapFlag){
        mCloseDumpcapFlag = false;
        if(bCreateResult){
            TerminateProcess(pi.hProcess, 0);

            WaitForSingleObject(pi.hProcess, INFINITE);
            CloseHandle(pi.hThread);
            CloseHandle(pi.hProcess);
            emit finished();
        }
    } else {
        si.cb = sizeof(si);

        bCreateResult = CreateProcess(NULL,
                                      commandArgs,
                                      NULL,
                                      NULL,
                                      FALSE,
                                      CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW,
                                      NULL,
                                      NULL,
                                      &si,
                                      &pi);
    }
}

If I click the Stop Button, on_pushButton_StopLOG_clicked() function runs:

 void MainWindow::on_pushButton_StopLOG_clicked()
 {
    worker->closeDumpcap(true);
 }

closeDumpcap() function in here:

void Worker::closeDumpcap(bool flag){
    mCloseDumpcapFlag = flag;
    capturePacket();
}

mCloseDumpcapFlag = true happen. Condition that is in the capturePacket() function work for mCloseDumpcapFlag = true condition for stopping the dumpcap.exe with TerminateProcess() function.

Conclusively, i can start dumpcap from GUI and stop it from GUI.