2010年6月23日 星期三

Get Icon and save it into a png file

This is not a news to get a icon from a file. But how about the process? I can extrace the process image file name and use it to extract the icons that it contains. The output is a handle of HICON. I survey many articles to find out the solution. Finally, I found a solution to the saving issue. The following sample codes will show the GDI+ and save the HICON into a PNG file. Of course, you can save it into other format that GDI+ provided.

 

HICON GetFileIcon(const CString& strFileName, CString& strSaveFileName, bool bSmallIcon) {

    SHFILEINFO sfi;

    SHGetFileInfo((LPCTSTR)strFileName,

        FILE_ATTRIBUTE_NORMAL,

        &sfi,

        sizeof(SHFILEINFO),

        SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | (bSmallIcon ? SHGFI_SMALLICON : SHGFI_LARGEICON));


    if(sfi.hIcon) {

        Bitmap* pBitmap = Bitmap::FromHICON(sfi.hIcon);

        CLSID encoderClsid;

        GetEncoderClsid(L"image/png", &encoderClsid);

        CStringW strPngFileName;

#ifndef _UNICODE

        strPngFileName.Format(L"%S", strFileName.GetString());

#else

        strPngFileName = strFileName;

#endif

        int nStart = strPngFileName.ReverseFind('\\') + 1;

        int nEnd = strPngFileName.ReverseFind('.');

        int nLength = nEnd - nStart;

        strPngFileName = strPngFileName.Mid(nStart, nLength);

        strPngFileName = CStringW(L"C:\\") + strPngFileName + (bSmallIcon ? CStringW("Small.png") : CStringW("Large.png"));

        strSaveFileName = strPngFileName;

        pBitmap->Save(strPngFileName.GetString(), &encoderClsid, NULL);

    }

    return sfi.hIcon;

}

 

You should include the header file <gdiplus.h> and use the name space "GdiPlus".

2010年6月7日 星期一

Memory Scan Tool

This will not too complex. It a easy way to let you scan your process memory like some game cheater. Of course, there is a free tool named "Game Cheater". That is open source one.

But I just want to write a "string" scan for myself. You can modify this by your self. Totally free.

See the definition.

 

#ifndef __MEMORY_SCAN_TOOL_H__

#define __MEMORY_SCAN_TOOL_H__

 

#pragma once

 

#include <vector>

 

typedef struct _MEMBLOCK {

    DWORD pid;                      // process id

    HANDLE hProc;                   // handle of the process

    unsigned char * addr;           // block address (start address)

    SIZE_T size;                    // memory block size

    unsigned char * buffer;         // a copy buffer of this memory block

    unsigned char * searchmask;     // used for searching

    SIZE_T matches;                 // used for searching

    SIZE_T data_size;               // data size when search

    struct _MEMBLOCK * next;        // linked list

} MEMBLOCK, *PMEMBLOCK;

 

typedef struct _FOUNDADDR {

    unsigned char * addr;           // base address

    unsigned long offset;           // off set

} FOUNDADDR;

 

//#define IS_IN_SEARCH(mb, offset) (mb->searchmask[(offset)/8] & (1 << ((offset)%8)))

//#define REMOVE_FROM_SEARCH(mb, offset) mb->searchmask[(offset)/8] &= ~(1 << ((offset)%8));

 

///

// This class is used for memory scan

// 1. Get memory block for scaning

// 2. Get the scan result

///

class CMemoryScanTool

{

public:

    CMemoryScanTool();

    ~CMemoryScanTool();

 

    static CMemoryScanTool* GetMemoryScanToolInstance();

    static void ReleaseMemoryScanToolInstance();

 

    // create the memory list by using CreateMemoryBlock

    PMEMBLOCK CreateMemoryList(unsigned int pid, int data_size);

    // create the memory block

    PMEMBLOCK CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size);

    // free the memory block (one block with buffer)

    void FreeMemoryBlock(PMEMBLOCK mb);

    // free the memory block list (by using FreeMemoryBlock)

    void FreeMemoryBlockList(PMEMBLOCK mb_list);

    // update the memory block data by using ReadProcessMemory

    void UpdateMemoryBlock(PMEMBLOCK mb);

    // Dump the information into a file

    void DumpScanInformation(FILE* f, PMEMBLOCK mb_list);

    void DumpScanInformation(char* szFileName, PMEMBLOCK mb_list);

 

    // scan the input string in the memory block list

    // Return Value: true indicate that the input string is in the memory block, the nAddr indicate the offset of this block

    bool ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr);

    bool ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr);

 

    // scan all memory block by using ScanString

    bool ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);

    bool ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);

 

};

 

#endif __MEMORY_SCAN_TOOL_H__

 


 

See the implementation.

 

#include "StdAfx.h"

#include "MemoryScanTool.h"

 

using namespace std;

 

namespace {

    static CMemoryScanTool* g_pMemoryScanTool = NULL;

    typedef LONG  NTSTATUS;

    typedef NTSTATUS (WINAPI *pFnRtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled);

    pFnRtlAdjustPrivilege  RtlAdjustPrivilege;

}

 

CMemoryScanTool::CMemoryScanTool()

{

    RtlAdjustPrivilege = (pFnRtlAdjustPrivilege)GetProcAddress(LoadLibrary(_T("Ntdll.dll")), "RtlAdjustPrivilege");

    BOOLEAN bEnabled = FALSE;

    // get debug privilege

    RtlAdjustPrivilege(20, 1, 0, &bEnabled);;

}

 

CMemoryScanTool::~CMemoryScanTool()

{

}

 

CMemoryScanTool* CMemoryScanTool::GetMemoryScanToolInstance() {

    if(g_pMemoryScanTool == NULL)

        g_pMemoryScanTool = new CMemoryScanTool();

    return g_pMemoryScanTool;

}

 

void CMemoryScanTool::ReleaseMemoryScanToolInstance() {

    if(g_pMemoryScanTool)

        delete g_pMemoryScanTool;

    g_pMemoryScanTool = NULL;

}

 

PMEMBLOCK CMemoryScanTool::CreateMemoryList(unsigned int pid, int data_size) {

    MEMBLOCK* mb_list = NULL;

    MEMORY_BASIC_INFORMATION meminfo;

    unsigned char* addr = 0;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

    if(hProc) {

        while(true) {

            if(VirtualQueryEx(hProc, addr, &meminfo, sizeof(meminfo)) == 0)

                break;

#define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)

            if((meminfo.State & MEM_COMMIT) && (meminfo.Protect & WRITABLE)) {

                MEMBLOCK* mb = CreateMemoryBlock(hProc, &meminfo, data_size);

                if(mb) {

                    UpdateMemoryBlock(mb);

                    mb->pid = pid;

                    mb->next = mb_list;

                    mb_list = mb;

                }

            }

            addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;

        }

    }

    return mb_list;

}

 

PMEMBLOCK CMemoryScanTool::CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size) {

    PMEMBLOCK mb = (PMEMBLOCK)malloc(sizeof(MEMBLOCK));

    if(mb) {

        mb->hProc = hProc;

        mb->addr = (unsigned char*)meminfo->BaseAddress;

        mb->size = meminfo->RegionSize;

        mb->buffer = (unsigned char*)malloc(meminfo->RegionSize);

        mb->searchmask = (unsigned char*)malloc(meminfo->RegionSize/8);

        memset(mb->searchmask, 0xff, meminfo->RegionSize/8);    // mark the byte is in searching.

        mb->matches = meminfo->RegionSize;

        mb->data_size = data_size;

        mb->next = NULL;

    }

    return mb;

}

 

void CMemoryScanTool::FreeMemoryBlock(PMEMBLOCK mb) {

    if(mb) {

        if(mb->buffer)

            free(mb->buffer);

 

        if(mb->searchmask)

            free(mb->searchmask);

 

        free(mb);

    }

}

 

void CMemoryScanTool::FreeMemoryBlockList(PMEMBLOCK mb_list) {

    CloseHandle(mb_list->hProc);

    while(mb_list) {

        PMEMBLOCK mb = mb_list;

        mb_list = mb_list->next;

        FreeMemoryBlock(mb);

    }

}

 

// Read the memory data from a process id in MEMBLOCK

void CMemoryScanTool::UpdateMemoryBlock(PMEMBLOCK mb)

{

    static unsigned char tmpbuf[128*1024];

    SIZE_T bytes_left = 0;

    SIZE_T total_read = 0;

    SIZE_T bytes_to_read = 0;

    SIZE_T bytes_read = 0;

 

    if(mb->matches > 0) {

        bytes_left = mb->size;

        mb->matches = 0;

        while(bytes_left) {

            bytes_to_read = (bytes_left > sizeof(tmpbuf)) ? sizeof(tmpbuf) : bytes_left;

            ReadProcessMemory(mb->hProc, mb->addr + total_read, tmpbuf, bytes_to_read, (SIZE_T *)&bytes_read);

            if(bytes_read != bytes_to_read) break;

            memcpy(mb->buffer + total_read, tmpbuf, bytes_read);

            bytes_left -= bytes_read;

            total_read += bytes_read;

        }

        mb->size = total_read;

    }

}

 

 

void CMemoryScanTool::DumpScanInformation(FILE* f, PMEMBLOCK mb_list) {

    MEMBLOCK* mb = mb_list;

    while(mb) {

        fprintf(f, "Process ID: %ld\r\n", GetProcessId(mb->hProc));

        fprintf(f, "0x%08x %d\r\n", mb->addr, mb->size);

        for(unsigned int i = 0; i < mb->size; ++i) {

            fprintf(f, "%c", mb->buffer[i]);

            //if(i % 8 == 0)

            //    fprintf(f, " ");

            //if(i % 16 == 0)

            //    fprintf(f, "\r\n");

        }

        fprintf(f, "\r\n");

        mb = mb->next;

    }

}

 

void CMemoryScanTool::DumpScanInformation(char* szFileName, PMEMBLOCK mb_list) {

    FILE* f = fopen(szFileName, "w");

    if(f) DumpScanInformation(f, mb_list);

}

 

bool CMemoryScanTool::ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr) {

    if(szInput == NULL || mb == NULL)

        return false;

 

    if(mb->size == 0)

        return false;

 

    SIZE_T nStringSize = wcslen(szInput);

 

    // shift one byte per loop (may shift 2 byte?)

    for(SIZE_T i = 0; i < mb->size - nStringSize; ++i) {

        if(memcmp(szInput, mb->buffer + i, nStringSize*2) == 0) {

            nAddr = i;

            return true;

        }

    }

    return false;

}

bool CMemoryScanTool::ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr) {

    if(szInput == NULL || mb == NULL)

        return false;

 

    if(mb->size == 0)

        return false;

 

    SIZE_T nStringSize = strlen(szInput);

 

    // shift one byte per loop

    for(SIZE_T i = 0; i < mb->size - nStringSize*2; ++i) {

        if(memcmp(szInput, (mb->buffer + i), nStringSize*2) == 0) {

            nAddr = (unsigned long)(mb->addr) + i;

            return true;

        }

    }

    return false;

}

 

bool CMemoryScanTool::ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {

    MEMBLOCK* mb = mb_list;

    unsigned long nAddr;

    while(mb) {

        if(ScanString(szInput, mb, nAddr)) {

            FOUNDADDR fa;

            fa.addr = mb->addr;

            fa.offset = nAddr;

            vecOut.push_back(fa);

        }

        mb = mb->next;

    }

    return (vecOut.size() != 0);

}

 

bool CMemoryScanTool::ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {

    MEMBLOCK* mb = mb_list;

    unsigned long nAddr;

    while(mb) {

        if(ScanString(szInput, mb, nAddr)) {

            FOUNDADDR fa;

            fa.addr = mb->addr;

            fa.offset = nAddr;

            vecOut.push_back(fa);

        }

        mb = mb->next;

    }

    return (vecOut.size() != 0);

}

 

 

Really easy to understand. This program use only 3 windows API. 

  1. VirtualQueryEx
  2. ReadProcessMemory
  3. OpenProcess
You can see that the 3 functions is documented on MSDN. This is a teaching article on the Youtube. You can search the keyword "memory scan" to find it. I write the video to an text format. Everyone can use it free.

 

Memory Scan Tool

This will not too complex. It a easy way to let you scan your process memory like some game cheater. Of course, there is a free tool named "Game Cheater". That is open source one.

But I just want to write a "string" scan for myself. You can modify this by your self. Totally free.

See the definition.

#ifndef __MEMORY_SCAN_TOOL_H__

#define __MEMORY_SCAN_TOOL_H__

 

#pragma once

 

#include <vector>

 

typedef struct _MEMBLOCK {

    DWORD pid;                      // process id

    HANDLE hProc;                   // handle of the process

    unsigned char * addr;           // block address (start address)

    SIZE_T size;                    // memory block size

    unsigned char * buffer;         // a copy buffer of this memory block

    unsigned char * searchmask;     // used for searching

    SIZE_T matches;                 // used for searching

    SIZE_T data_size;               // data size when search

    struct _MEMBLOCK * next;        // linked list

} MEMBLOCK, *PMEMBLOCK;

 

typedef struct _FOUNDADDR {

    unsigned char * addr;           // base address

    unsigned long offset;           // off set

} FOUNDADDR;

 

//#define IS_IN_SEARCH(mb, offset) (mb->searchmask[(offset)/8] & (1 << ((offset)%8)))

//#define REMOVE_FROM_SEARCH(mb, offset) mb->searchmask[(offset)/8] &= ~(1 << ((offset)%8));

 

///

// This class is used for memory scan

// 1. Get memory block for scaning

// 2. Get the scan result

///

class CMemoryScanTool

{

public:

    CMemoryScanTool();

    ~CMemoryScanTool();

 

    static CMemoryScanTool* GetMemoryScanToolInstance();

    static void ReleaseMemoryScanToolInstance();

 

    // create the memory list by using CreateMemoryBlock

    PMEMBLOCK CreateMemoryList(unsigned int pid, int data_size);

    // create the memory block

    PMEMBLOCK CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size);

    // free the memory block (one block with buffer)

    void FreeMemoryBlock(PMEMBLOCK mb);

    // free the memory block list (by using FreeMemoryBlock)

    void FreeMemoryBlockList(PMEMBLOCK mb_list);

    // update the memory block data by using ReadProcessMemory

    void UpdateMemoryBlock(PMEMBLOCK mb);

    // Dump the information into a file

    void DumpScanInformation(FILE* f, PMEMBLOCK mb_list);

    void DumpScanInformation(char* szFileName, PMEMBLOCK mb_list);

 

    // scan the input string in the memory block list

    // Return Value: true indicate that the input string is in the memory block, the nAddr indicate the offset of this block

    bool ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr);

    bool ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr);

 

    // scan all memory block by using ScanString

    bool ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);

    bool ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);

 

};

 

#endif __MEMORY_SCAN_TOOL_H__


See the implementation.

#include "StdAfx.h"

#include "MemoryScanTool.h"

 

using namespace std;

 

namespace {

    static CMemoryScanTool* g_pMemoryScanTool = NULL;

    typedef LONG  NTSTATUS;

    typedef NTSTATUS (WINAPI *pFnRtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled);

    pFnRtlAdjustPrivilege  RtlAdjustPrivilege;

}

 

CMemoryScanTool::CMemoryScanTool()

{

    RtlAdjustPrivilege = (pFnRtlAdjustPrivilege)GetProcAddress(LoadLibrary(_T("Ntdll.dll")), "RtlAdjustPrivilege");

    BOOLEAN bEnabled = FALSE;

    // get debug privilege

    RtlAdjustPrivilege(20, 1, 0, &bEnabled);;

}

 

CMemoryScanTool::~CMemoryScanTool()

{

}

 

CMemoryScanTool* CMemoryScanTool::GetMemoryScanToolInstance() {

    if(g_pMemoryScanTool == NULL)

        g_pMemoryScanTool = new CMemoryScanTool();

    return g_pMemoryScanTool;

}

 

void CMemoryScanTool::ReleaseMemoryScanToolInstance() {

    if(g_pMemoryScanTool)

        delete g_pMemoryScanTool;

    g_pMemoryScanTool = NULL;

}

 

PMEMBLOCK CMemoryScanTool::CreateMemoryList(unsigned int pid, int data_size) {

    MEMBLOCK* mb_list = NULL;

    MEMORY_BASIC_INFORMATION meminfo;

    unsigned char* addr = 0;

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

    if(hProc) {

        while(true) {

            if(VirtualQueryEx(hProc, addr, &meminfo, sizeof(meminfo)) == 0)

                break;

#define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)

            if((meminfo.State & MEM_COMMIT) && (meminfo.Protect & WRITABLE)) {

                MEMBLOCK* mb = CreateMemoryBlock(hProc, &meminfo, data_size);

                if(mb) {

                    UpdateMemoryBlock(mb);

                    mb->pid = pid;

                    mb->next = mb_list;

                    mb_list = mb;

                }

            }

            addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;

        }

    }

    return mb_list;

}

 

PMEMBLOCK CMemoryScanTool::CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size) {

    PMEMBLOCK mb = (PMEMBLOCK)malloc(sizeof(MEMBLOCK));

    if(mb) {

        mb->hProc = hProc;

        mb->addr = (unsigned char*)meminfo->BaseAddress;

        mb->size = meminfo->RegionSize;

        mb->buffer = (unsigned char*)malloc(meminfo->RegionSize);

        mb->searchmask = (unsigned char*)malloc(meminfo->RegionSize/8);

        memset(mb->searchmask, 0xff, meminfo->RegionSize/8);    // mark the byte is in searching.

        mb->matches = meminfo->RegionSize;

        mb->data_size = data_size;

        mb->next = NULL;

    }

    return mb;

}

 

void CMemoryScanTool::FreeMemoryBlock(PMEMBLOCK mb) {

    if(mb) {

        if(mb->buffer)

            free(mb->buffer);

 

        if(mb->searchmask)

            free(mb->searchmask);

 

        free(mb);

    }

}

 

void CMemoryScanTool::FreeMemoryBlockList(PMEMBLOCK mb_list) {

    CloseHandle(mb_list->hProc);

    while(mb_list) {

        PMEMBLOCK mb = mb_list;

        mb_list = mb_list->next;

        FreeMemoryBlock(mb);

    }

}

 

// Read the memory data from a process id in MEMBLOCK

void CMemoryScanTool::UpdateMemoryBlock(PMEMBLOCK mb)

{

    static unsigned char tmpbuf[128*1024];

    SIZE_T bytes_left = 0;

    SIZE_T total_read = 0;

    SIZE_T bytes_to_read = 0;

    SIZE_T bytes_read = 0;

 

    if(mb->matches > 0) {

        bytes_left = mb->size;

        mb->matches = 0;

        while(bytes_left) {

            bytes_to_read = (bytes_left > sizeof(tmpbuf)) ? sizeof(tmpbuf) : bytes_left;

            ReadProcessMemory(mb->hProc, mb->addr + total_read, tmpbuf, bytes_to_read, (SIZE_T *)&bytes_read);

            if(bytes_read != bytes_to_read) break;

            memcpy(mb->buffer + total_read, tmpbuf, bytes_read);

            bytes_left -= bytes_read;

            total_read += bytes_read;

        }

        mb->size = total_read;

    }

}

 

 

void CMemoryScanTool::DumpScanInformation(FILE* f, PMEMBLOCK mb_list) {

    MEMBLOCK* mb = mb_list;

    while(mb) {

        fprintf(f, "Process ID: %ldrn", GetProcessId(mb->hProc));

        fprintf(f, "0x%08x %drn", mb->addr, mb->size);

        for(unsigned int i = 0; i < mb->size; ++i) {

            fprintf(f, "%c", mb->buffer[i]);

            //if(i % 8 == 0)

            //    fprintf(f, " ");

            //if(i % 16 == 0)

            //    fprintf(f, "rn");

        }

        fprintf(f, "rn");

        mb = mb->next;

    }

}

 

void CMemoryScanTool::DumpScanInformation(char* szFileName, PMEMBLOCK mb_list) {

    FILE* f = fopen(szFileName, "w");

    if(f) DumpScanInformation(f, mb_list);

}

 

bool CMemoryScanTool::ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr) {

    if(szInput == NULL || mb == NULL)

        return false;

 

    if(mb->size == 0)

        return false;

 

    SIZE_T nStringSize = wcslen(szInput);

 

    // shift one byte per loop (may shift 2 byte?)

    for(SIZE_T i = 0; i < mb->size - nStringSize; ++i) {

        if(memcmp(szInput, mb->buffer + i, nStringSize*2) == 0) {

            nAddr = i;

            return true;

        }

    }

    return false;

}

bool CMemoryScanTool::ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr) {

    if(szInput == NULL || mb == NULL)

        return false;

 

    if(mb->size == 0)

        return false;

 

    SIZE_T nStringSize = strlen(szInput);

 

    // shift one byte per loop

    for(SIZE_T i = 0; i < mb->size - nStringSize*2; ++i) {

        if(memcmp(szInput, (mb->buffer + i), nStringSize*2) == 0) {

            nAddr = (unsigned long)(mb->addr) + i;

            return true;

        }

    }

    return false;

}

 

bool CMemoryScanTool::ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {

    MEMBLOCK* mb = mb_list;

    unsigned long nAddr;

    while(mb) {

        if(ScanString(szInput, mb, nAddr)) {

            FOUNDADDR fa;

            fa.addr = mb->addr;

            fa.offset = nAddr;

            vecOut.push_back(fa);

        }

        mb = mb->next;

    }

    return (vecOut.size() != 0);

}

 

bool CMemoryScanTool::ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {

    MEMBLOCK* mb = mb_list;

    unsigned long nAddr;

    while(mb) {

        if(ScanString(szInput, mb, nAddr)) {

            FOUNDADDR fa;

            fa.addr = mb->addr;

            fa.offset = nAddr;

            vecOut.push_back(fa);

        }

        mb = mb->next;

    }

    return (vecOut.size() != 0);

}

 

Really easy to unders