Memory scanner



  • I'm pretty much a beginner in qt & c++. Still i wanted to try to make a basic memory scanner. I used the ReadProcessMemory & WriteProcessMemory from windows API. I have been developing this for 3 days. It turned out it worked :P. It's really slow though. If anyone has time to read my scannerthread and tell me how to make it faster i would really appreciate it.

    @
    #include "scannerthread.h"

    ScannerThread::ScannerThread(int addressStart, int addressEnd, int value, HANDLE handle, QObject *parent) :
    QThread(parent)
    {
    m_addressEnd = addressEnd;
    m_addressStart = addressStart;
    currentAddress = addressStart;
    m_value = value;
    m_handle = handle;
    running = true;
    }

    void ScannerThread::run()
    {
    while(running)
    {
    mutex.lock();
    ReadProcessMemory(m_handle, PCVOID(currentAddress), PVOID(&values), 1000, 0);
    //values is an array of 250 ints. This is supposed to read the whole page.

        for(int i = 0; i < 250; i++)
        {
            if(values[i] == m_value)
            {
                QPair<int, int> temp;
                temp.first = currentAddress+sizeof(int)*i;
                temp.second = buffer;
    
                matchingAddresses.append(temp);
            }
        }
    
        currentAddress += 1000;
    
        if(currentAddress == m_addressEnd)
        {
            emit finished(this);
        }
    
        mutex.unlock();
    }
    

    }

    QList<QPair<int, int> > ScannerThread::getAddresses()
    {
    return matchingAddresses;
    }
    @



  • Hi,

    One thing I see is your loop end detection. What happens if

    @
    currentAddress += 1000;
    @

    is bigger then m_addressEnd? You will go on looping...
    aditionally, you don't stop your rthread at the end. So I suggest the following:

    @
    void ScannerThread::run()
    {
    while(running)
    {
    mutex.lock();
    ReadProcessMemory(m_handle, PCVOID(currentAddress), PVOID(&values), 1000, 0);
    //values is an array of 250 ints. This is supposed to read the whole page.

        for(int i = 0; i < 250; i++)
        {
            if(values[i] == m_value)
            {
                QPair<int, int> temp;
                temp.first = currentAddress+sizeof(int)*i;
                temp.second = buffer;
     
                matchingAddresses.append(temp);
            }
        }
    
        currentAddress += 1000;
    
        if(currentAddress >= m_addressEnd) // changed
        {
            emit finished(this);
            running = false;               // changed
        }
    
        mutex.unlock();
    }
    

    }
    @

    You don't handle errors (so if you read after the end of the process memory, etc.)

    Your comparison using a for loop is perhaps not the fastest, it could be optimized by using duffs device algorithm. But you have to check, whether it fastenes up your loop or not.

    @
    inline ScannerThread::compare(int nIndex)
    {
    if(values[nIndex] == m_value)
    {
    QPair<int, int> temp;
    temp.first = currentAddress+sizeof(int)*nIndex;
    temp.second = buffer;

        matchingAddresses.append(temp);
    }
    

    }
    void ScannerThread::run()
    {
    while(running)
    {
    mutex.lock();
    ReadProcessMemory(m_handle, PCVOID(currentAddress), PVOID(&values), 1000, 0);
    //values is an array of 250 ints. This is supposed to read the whole page.

        const int nCount = 250;
        register nCounter = (nCount+7)/8
        switch(nCount%8)
        {
            case 0: do{ compare(nCounter++);
            case 7:     compare(nCounter++);
            case 6:     compare(nCounter++);
            case 5:     compare(nCounter++);
            case 4:     compare(nCounter++);
            case 3:     compare(nCounter++);
            case 2:     compare(nCounter++);
            case 1:     compare(nCounter++);
                    }while(--nCounter>0);
        }
    
        currentAddress += 1000;
    
        if(currentAddress >= m_addressEnd) // changed
        {
            emit finished(this);
            running = false;               // changed
        }
    
        mutex.unlock();
    }
    

    }
    @

    Disclaimer: All code was not tested, but just written here in the forum editor.



  • Thx for ur reply. im stopping the thread in other file after i got the data from it.



  • But it does not make sense to go on the while loop of the thread. You keep using CPU time for nothing. I would emit the signal and stop the thread.



  • Since this is a generic memory scanner thread, and for future reference, an approach to solving this problem in linux platform (find the vma maps of a process and the dynamic allocated memory and probably access them) one has to resolve to /proc/<pid>/stat (also /proc/self/stat for the caller) and to /proc/pid/maps for the so entry points/stack/heap/etc, parse them and then use them as usual (accessing memory for r/w ops)

    Just out of curiosity, is the page in windows 250sizeof(int) =(?) 2504 = 1000bytes? this doesn't sound correct



  • I think, page size in Windows is 4k --> 1000 ints

    EDIT: corrected: it's 1024 ints, sorry, gerolf



  • Thx peeps i wasnt sure of the page size just found from internet. One last thing. Do i need to call something like @delete thread;
    thread->deleteLater();@
    or is it ok if i just let it die with exiting the run function?



  • exiting the run function exits the system thread. The object itself lives, untill it is deleted (e.g. becaus it is a member of a class, has a parent which dies some time, ...). You can even reuse a thread object after the execution has finished.

    But, please, do youself a favor, don't call some delete fuinctions from run and don't delete it while run did not exit.



  • @
    #include <stdio.h>
    #include <windows.h>

    int main(void) {
    SYSTEM_INFO s;
    GetSystemInfo(&s);

        printf("Page size : %u bytes", si.dwPageSize);
    
        return 0;
    

    }@
    (from msdn)

    this will tell the actual page size (which I am pretty sure ain't 4000bytes either). probably it is something like 4096 bytes

    About threads:

    You can always delete a thread (for instance if you have limited resources and you are not going to reuse the QThread) but unlikely what Gerolf you can delete anywhere you like (or where it suits you). Be sure prior to deleting to see that the thread is really finished via wait().

    a nice approach as well is to use the eventloop for such tasks :)

    @
    MyThread::MyThread()
    : QThread() {
    QObject::connect(this,
    SIGNAL(finished()),
    this,
    SLOT(deleteLater()));
    }
    @
    something like that seems awesomely hackish. You can replace the deleteLater() slot with your reuse thread method as described earlier by Gerolf.



  • Sure, you can delete a thread in any state. It is possible, but IMHO no good programming style to just delete it. A warning is printed if the run method did not exit. But the objects are deleted. What will happen if you access the object inside the run method afterwards?

    If you first stop the thread and then delete it, it's fine.



  • Gerolf what you say is 100% correct. That's why in my previous post I mention wait() method ( http://doc.qt.nokia.com/latest/qthread.html#wait ) and finished signal ( http://doc.qt.nokia.com/latest/qthread.html#finished )



  • But if you just call wait, without sending some stop logic to the thread, it could take really long till wait returnes.



  • the whole course of the discussion reminds me of http://xkcd.com/386/ :D

    wait()-ing in arbitrary places obviously will cause the caller to block until the waited thread is stop or finished. It is after all a blocking call. Waiting in other places of course after using the terminate () slot is another story, i.e. one can use this as a thread synchronization scheme in some corner cases.

    • However if the thread is running for ever why to stop/delete it?
    • If on the other hand the thread terminates eventually how are you going to know that it has terminated? (also relevant question is why do want it terminated - this will lead you to the sort of policy you are going to implement for its termination). [for instance , If you want to terminate it just for resource/performance reasons polling on the isFinished() is a bad idea, etc] however no matter what, prior to its deletion (obviously it has been terminated either by itself or by an external factor, otherwise why should we release the resources since it is still running via delete?), one has to call the wait() to see that the thread is ready to meet its maker. This is a quirk due to the different behaviour of the many OS after a request to stop the thread. This in most sane OSes (ie linux) will take less than one scheduler's time slot (that is usually in linux 10ms).

    That's the full explanation of my argument about wait(). One should use it when talking for the thread delete case, just to make sure that the thread has actually stopped (after he has learned that it has stopped (signal) or it has requested it to stop).

    /me over and out.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.