Results 1 to 5 of 5

Thread: Signature scanning

  1. #1
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default Signature scanning

    I'm trying to get comfortable with signature scanning. I wrote a simple test application that gets a handle on a open process and then scans the pattern I tell it to and returns the address\s with that pattern.

    I was able to get everything done however when I try to return the address, my application crashes and I'm not sure why.

    To make sure I am retrieving the correct information, I print the following info:
    Code:
    Process ID
    Module Base
    Module Size
    All of these return the correct values for the specified process in my application, because I compare it to it in ollydbg and it's the same.

    I took a random function and copied the BYTES from there to scan and find.

    Here is the 2 lines I took.
    Code:
    00408DC0  /$ 83EC 50        SUB ESP,50
    00408DC3  |. 8B41 50        MOV EAX,DWORD PTR DS:[ECX+50]
    I created the pattern I will scan:
    Code:
    \x83\xEC\x50\x8B\x41\x50
    The actual scanning seems to go through fine, but as soon as I use sprintf_s and output the text, it crashes.

    Here is my whole code:

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <windows.h>
    #include <tlhelp32.h>
    
    
    using namespace std;
    
    
    //Global Defines
    #define process "editplus.exe"
    
    
    int bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask)
    {
        for(;*szMask;++szMask,++pData,++bMask)
            if(*szMask=='x' && *pData!=*bMask) 
                return 0;
        return (*szMask) == NULL;
    }
    
    
    DWORD dwFindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask)
    {
        DWORD i;
    
    
        for(i=0; i < dwLen; i++)
            if(bDataCompare( (BYTE*)( dwAddress+i ),bMask,szMask))
                return (DWORD)(dwAddress+i);
        
        return 0;
    }
    
    
    unsigned long GetModuleSize(unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize)
    {
        unsigned long dwResult;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
        if(hSnapshot)
        {
            MODULEENTRY32 moduleEntry = {sizeof(MODULEENTRY32)};
            if(Module32First(hSnapshot, &moduleEntry))
            {
                do
                {
                    if(strcmp(moduleEntry.szModule, pszModuleName) == 0) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseSize;
    
    
                        if(pdwSize)
                            *pdwSize = moduleEntry.modBaseSize;
    
    
                        break;
                    }
                }
                while(Module32Next( hSnapshot, &moduleEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    unsigned long GetModuleBase(unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize)
    {
        unsigned long dwResult;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
        if(hSnapshot)
        {
            MODULEENTRY32 moduleEntry = {sizeof(MODULEENTRY32)};
            if(Module32First(hSnapshot, &moduleEntry ))
            {
                do
                {
                    if(strcmp(moduleEntry.szModule, pszModuleName) == 0) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseAddr;
    
    
                        if(pdwSize)
                            *pdwSize = moduleEntry.modBaseSize;
    
    
                        break;
                    }
                }
                while(Module32Next(hSnapshot, &moduleEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    unsigned long GetProcessId(char* pszProcessName)
    {
        unsigned long dwResult = 0;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if(hSnapshot)
        {
            PROCESSENTRY32 processEntry = {sizeof(PROCESSENTRY32)};
            if(Process32First(hSnapshot, &processEntry ))
            {
                do
                {
                    if(strcmp(processEntry.szExeFile, pszProcessName) == 0) 
                    {
                        dwResult = processEntry.th32ProcessID;
                        break;
                    }
                }
                while(Process32Next(hSnapshot, &processEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    bool setDebug() 
    {
        HANDLE hToken;
    
    
        if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
        {
            TOKEN_PRIVILEGES tp;
            LUID luid;
            TOKEN_PRIVILEGES tpPrevious;
            DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
            
            if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) 
            {
                tp.PrivilegeCount = 1;
                tp.Privileges[0].Luid = luid;
                tp.Privileges[0].Attributes = 0;
                
                if(AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) 
                {
                    tpPrevious.PrivilegeCount = 1;
                    tpPrevious.Privileges[0].Luid = luid;
                    tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
                    
                    if(AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL )) 
                    {
                        CloseHandle(hToken);
                        return true;
                    }
                }
            }
        }
        CloseHandle(hToken);
        return false;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        unsigned long dwSize;
        unsigned long dwPID1 = GetProcessId(process);
        unsigned long dwBase = GetModuleBase(dwPID1, process, &dwSize);
        unsigned long dwBaseSize = GetModuleSize(dwPID1, process, &dwSize);
    
    
        if(setDebug()) 
        {
            char szBuffer[50];
            char szBuffer2[50]; 
    
    
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, dwPID1);
    
    
            sprintf_s(szBuffer, sizeof(szBuffer), "Base Address: 0x%X Base Size: 0x%X\n", dwBase, dwBaseSize);
            cout << "Process ID: " << dwPID1 << ' ' << szBuffer << endl;
    
    
            DWORD sigScan = dwFindPattern(dwBase, dwBaseSize, (BYTE *)"\x83\xEC\x50\x8B\x41\x50", "xxxxxx");
    
    
            if(sigScan != NULL)
            {
                sprintf_s(szBuffer2, sizeof(szBuffer2), "Pattern found at address: 0x%X\n", sigScan); <----------------------- Crashes 
                cout << szBuffer2 << endl;
    
    
                //printf( "Pattern found at: 0x%X\n", sigScan);
                //cout << sigScan << endl;
            }
            CloseHandle(hProcess);
        }
    
    
        system("Pause");
        return 0;
    }
    Any thoughts?

  2. #2
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Also if this is any help. Here is my application output:
    Code:
    Process ID: 8528 Base Address: 0x400000 Base Size: 0x1A7000
    compared to what ollydbg sees

    Code:
    Executable modules, item 0
     Base=00400000
     Size=001A7000 (1732608.)
     Entry=004C8DCE editplus.<ModuleEntryPoint>
     Name=editplus
     File version=3, 1, 1, 340
     Path=C:\Files\editplus\editplus.exe
    As you can see the base and size all match up.

    When I try running it in debug mode, I get this:
    Code:
    Unhandled exception at 0x774415de in vTable.exe: 0xC0000005: Access violation reading location 0x00400000.
    I'm not sure why I'm getting an access violation??

  3. #3
    Über Prodigy & Developer Razo[R]apiD's Avatar
    Join Date
    May 2010
    Location
    Poland, Lublin
    Posts
    3,257

    Default

    If you are scanning from external process, you have to use ReadProcessMemory, or you will scan your own sections. Additionaly, code section may be "execute only", without the read rights.

  4. #4
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    You sir are a scholar as always. Thank you!

    I ended up rewriting the findPattern() function so it works for external processes and it works perfectly!!!!

    Here is the source:

    Code:
    #include "stdafx.h"
    #include <iostream>
    #include <windows.h>
    #include <tlhelp32.h>
    
    
    using namespace std;
    
    
    char * process = "editplus.exe";
    
    
    bool CompareData(const unsigned char* pbData, const unsigned char* pbMask, const char* pszString) 
    { 
        for( ; *pszString; ++pszString, ++pbData, ++pbMask) 
        {
            if(*pszString == 'x' && *pbData != *pbMask) 
                return FALSE; 
        }
    
    
        return (*pszString) == NULL; 
    }
    
    
    unsigned long dwFindPattern(HANDLE hProcess, unsigned long dwAddress, unsigned long dwLength, unsigned char* pbMask, char* pszString) 
    {
        unsigned long dwResult = NULL;
        unsigned char* pbBuffer = (unsigned char*) malloc(dwLength);
    
    
        if(pbBuffer)
        {
            if(ReadProcessMemory(hProcess, (void*) dwAddress, pbBuffer, dwLength, NULL))
            {
                for(unsigned long i = 0; i < dwLength; i++) 
                {
                    if(CompareData((BYTE*) (pbBuffer + i), pbMask, pszString)) 
                    {
                        dwResult = (unsigned long)(dwAddress + i);
                        break;
                    }
                }
            }
    
    
            free(pbBuffer);
            pbBuffer = NULL;
        }
    
    
        return dwResult; 
    }
    
    
    unsigned long GetModuleSize(unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize)
    {
        unsigned long dwResult;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
        if(hSnapshot)
        {
            MODULEENTRY32 moduleEntry = {sizeof(MODULEENTRY32)};
            if(Module32First(hSnapshot, &moduleEntry))
            {
                do
                {
                    if(strcmp(moduleEntry.szModule, pszModuleName) == 0) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseSize;
    
    
                        if(pdwSize)
                            *pdwSize = moduleEntry.modBaseSize;
    
    
                        break;
                    }
                }
                while(Module32Next( hSnapshot, &moduleEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    unsigned long GetModuleBase(unsigned long dwPID, char* pszModuleName, unsigned long* pdwSize)
    {
        unsigned long dwResult;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
        if(hSnapshot)
        {
            MODULEENTRY32 moduleEntry = {sizeof(MODULEENTRY32)};
            if(Module32First(hSnapshot, &moduleEntry ))
            {
                do
                {
                    if(strcmp(moduleEntry.szModule, pszModuleName) == 0) 
                    {
                        dwResult = (unsigned long)moduleEntry.modBaseAddr;
    
    
                        if(pdwSize)
                            *pdwSize = moduleEntry.modBaseSize;
    
    
                        break;
                    }
                }
                while(Module32Next(hSnapshot, &moduleEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    unsigned long GetProcessId(char* pszProcessName)
    {
        unsigned long dwResult = 0;
    
    
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if(hSnapshot)
        {
            PROCESSENTRY32 processEntry = {sizeof(PROCESSENTRY32)};
            if(Process32First(hSnapshot, &processEntry ))
            {
                do
                {
                    if(strcmp(processEntry.szExeFile, pszProcessName) == 0) 
                    {
                        dwResult = processEntry.th32ProcessID;
                        break;
                    }
                }
                while(Process32Next(hSnapshot, &processEntry));
            }
    
    
            if(hSnapshot)
            {
                CloseHandle(hSnapshot);
                hSnapshot = NULL;
            }
        }
    
    
        return dwResult;
    }
    
    
    bool setDebug() 
    {
        HANDLE hToken;
    
    
        if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
        {
            TOKEN_PRIVILEGES tp;
            LUID luid;
            TOKEN_PRIVILEGES tpPrevious;
            DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
            
            if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) 
            {
                tp.PrivilegeCount = 1;
                tp.Privileges[0].Luid = luid;
                tp.Privileges[0].Attributes = 0;
                
                if(AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &tpPrevious, &cbPrevious)) 
                {
                    tpPrevious.PrivilegeCount = 1;
                    tpPrevious.Privileges[0].Luid = luid;
                    tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
                    
                    if(AdjustTokenPrivileges( hToken, FALSE, &tpPrevious, cbPrevious, NULL, NULL )) 
                    {
                        CloseHandle(hToken);
                        return true;
                    }
                }
            }
        }
        CloseHandle(hToken);
        return false;
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        unsigned long dwSize;
        unsigned long dwPID1 = GetProcessId(process);
        unsigned long dwBase = GetModuleBase(dwPID1, process, &dwSize);
        unsigned long dwBaseSize = GetModuleSize(dwPID1, process, &dwSize);
    
    
    	if(setDebug())
    	{
            char szBuffer[50];
            char szBuffer2[50]; 
    
    
            HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, dwPID1);
    
    
            sprintf_s(szBuffer, sizeof(szBuffer), "Base Address: 0x%X Base Size: 0x%X\n", dwBase, dwBaseSize);
            cout << "Process ID: " << dwPID1 << ' ' << szBuffer << endl;
    
    
            DWORD sigScan = dwFindPattern(hProcess, dwBase, dwBaseSize, (BYTE *)"\x83\xEC\x50\x8B\x41\x50", "xxxxxx");
    
    
            if(sigScan != NULL)
            {
                sprintf_s(szBuffer2, sizeof(szBuffer2), "Pattern found at address: 0x%X\n", sigScan); 
                cout << szBuffer2 << endl;
            }
    
    
            CloseHandle(hProcess);
        }
    
    
        system("Pause");
        return 0;
    }

  5. #5
    Administrator James's Avatar
    Join Date
    May 2010
    Location
    on the intraweb
    Posts
    3,180

    Default

    Quick question for you.
    I have found that if there are multiple matching patterns in a process I'm scanning, it only returns the first address and breaks. How would I modify my code to print all offsets with the matching pattern?

    I changed my code to this, however it's not working.

    Code:
    do
    {
        if(pbBuffer)
        {
            if(ReadProcessMemory(hProcess, (void*) dwAddress, pbBuffer, dwLength, NULL))
            {
                for(unsigned long i = 0; i < dwLength; i++) 
                {
                    if(CompareData((BYTE*) (pbBuffer + i), pbMask, pszString)) 
                    {
                        dwResult = (unsigned long)(dwAddress + i);
    		    dwAddress = dwResult + 1;
                        //break;
                    }
                }
            }
    
    
            free(pbBuffer);
            pbBuffer = NULL;
        }
    }while(dwAddress < 0x007FFFFF);

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •