winston 发表于 2012-3-8 15:01:55

[原]VC++信息安全编程(13)实现扫描内存,实现内存读写

扫描内存,实现内存读写是杀毒软件必备的功能,这个功能如何实现呢,
请见代码实现与分析
调用美国大牛写的PSAPI.DLL



#include "stdafx.h"
#include "DoProcess.h"
#include "DoProcessDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
char ch[]="zhao1234";
/////////////////////////////////////////////////////////////////////////////
// CDoProcessDlg dialog

CDoProcessDlg::CDoProcessDlg(CWnd* pParent /*=NULL*/)
        : CDialog(CDoProcessDlg::IDD, pParent)
{
        //{{AFX_DATA_INIT(CDoProcessDlg)
        m_Code = _T("zhao1234");
        m_Ebase = _T("");
        m_Esize = _T("");
        m_Eaddress = _T("");
        m_Edata = _T("");
        m_EAdd_Change = _T("");
        //}}AFX_DATA_INIT
        // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CDoProcessDlg::DoDataExchange(CDataExchange* pDX)
{
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CDoProcessDlg)
        DDX_Control(pDX, IDC_LIST2, m_list);
        DDX_Control(pDX, IDC_ScanProcess, m_Scan);
        DDX_Text(pDX, IDC_Code, m_Code);
    DDX_Control(pDX, IDC_LIST1, m_lCtrl);
        DDX_Text(pDX, IDC_Ebase, m_Ebase);
        DDX_Text(pDX, IDC_Esize, m_Esize);
        DDV_MaxChars(pDX, m_Esize, 2000);
        DDX_Text(pDX, IDC_Eaddress, m_Eaddress);
        DDX_Text(pDX, IDC_Edata, m_Edata);
        DDX_Text(pDX, IDC_EAdd_Change, m_EAdd_Change);
        //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDoProcessDlg, CDialog)
        //{{AFX_MSG_MAP(CDoProcessDlg)
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ON_BN_CLICKED(IDC_GetProcess, OnGetProcess)
        ON_BN_CLICKED(IDC_GetProcess2, OnGetProcess2)
        ON_BN_CLICKED(IDC_KillProcess, OnKillProcess)
        ON_BN_CLICKED(IDC_ScanProcess, OnScanProcess)
        ON_BN_CLICKED(IDC_ReadMem, OnReadMem)
        ON_EN_CHANGE(IDC_Code, OnChangeCode)
        ON_EN_CHANGE(IDC_Ebase, OnChangeEbase)
        ON_EN_CHANGE(IDC_Esize, OnChangeEsize)
        ON_NOTIFY(NM_DBLCLK, IDC_LIST1, OnDblclkList1)
        ON_EN_CHANGE(IDC_Eaddress, OnChangeEaddress)
        ON_EN_CHANGE(IDC_Edata, OnChangeEdata)
        ON_BN_CLICKED(IDC_BWriteMem, OnBWriteMem)
        ON_BN_CLICKED(IDC_BEnumAllDLL, OnBEnumAllDLL)
        ON_BN_CLICKED(IDC_BChangeAttr, OnBChangeAttr)
        ON_EN_CHANGE(IDC_EAdd_Change, OnChangeEAddChange)
        ON_BN_CLICKED(IDC_BgetModule, OnBgetModule)
        ON_BN_CLICKED(IDC_BGetAllDLL2, OnBGetAllDLL)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDoProcessDlg message handlers

BOOL CDoProcessDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        // Set the icon for this dialog.The framework does this automatically
        //when the application's main window is not a dialog
        SetIcon(m_hIcon, TRUE);                        // Set big icon
        SetIcon(m_hIcon, FALSE);                // Set small icon
        // TODO: Add extra initialization here

    ListView_SetExtendedListViewStyleEx(m_lCtrl.m_hWnd, LVS_EX_FULLROWSELECT|
                LVS_SORTDESCENDING, 0xFFFFFFFF);        
    m_lCtrl.InsertColumn(0,"序号",HDF_LEFT,50,0);
    m_lCtrl.InsertColumn(1,"进程ID",HDF_LEFT,60,0);       
    m_lCtrl.InsertColumn(2,"路径",HDF_LEFT,560,0);       
    m_lCtrl.InsertColumn(3,"基地址",HDF_LEFT,60,0);
       
        return TRUE;// return TRUEunless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//to draw the icon.For MFC applications using the document/view model,
//this is automatically done for you by the framework.

void CDoProcessDlg::OnPaint()
{
        if (IsIconic())
        {
                CPaintDC dc(this); // device context for painting

                SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

                // Center icon in client rectangle
                int cxIcon = GetSystemMetrics(SM_CXICON);
                int cyIcon = GetSystemMetrics(SM_CYICON);
                CRect rect;
                GetClientRect(&rect);
                int x = (rect.Width() - cxIcon + 1) / 2;
                int y = (rect.Height() - cyIcon + 1) / 2;

                // Draw the icon
                dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {
                CDialog::OnPaint();
        }
}

// The system calls this to obtain the cursor to display while the user drags
//the minimized window.
HCURSOR CDoProcessDlg::OnQueryDragIcon()
{
        return (HCURSOR) m_hIcon;
}

void CDoProcessDlg::OnGetProcess()
{
m_list.ResetContent();
m_lCtrl.DeleteAllItems();
DWORD aProcesses, cbNeeded, cProcesses;
unsigned int i;
//枚举系统进程ID列表
if(!EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )return;
// Calculate how many process identifiers were returned.
//计算进程数量
cProcesses = cbNeeded / sizeof(DWORD);
// 输出每个进程的名称和ID
for ( i = 0; i < cProcesses; i++ )PrintProcessNameAndID( aProcesses,i);

}


void CDoProcessDlg::PrintProcessNameAndID( DWORD processID ,int n)
{
char szProcessName = "unknown";

//取得进程的句柄
HANDLE hProcess=OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ,FALSE,processID);
//取得进程名称
if ( hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if(EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
//GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) );
//该函数得到进程文件名
GetModuleFileNameEx(hProcess,hMod,szProcessName, sizeof(szProcessName));
//该函数得到进程全文件名路径
//回显进程名称和ID
CString inf0,inf1,inf2,inf3;

CFile fp;
if(fp.Open(szProcessName,CFile::modeRead)){
        IMAGE_DOS_HEADER      dos_header;
        IMAGE_NT_HEADERS      nt_header;
        fp.Read(&dos_header,sizeof(dos_header));
        fp.Seek(dos_header.e_lfanew,CFile::begin);
    fp.Read(&nt_header,sizeof(nt_header));
        fp.Close();
    inf3.Format("%X",nt_header.OptionalHeader.ImageBase);

}
else inf3="unknown";

inf0.Format("%d",n);
inf1.Format("%s",szProcessName);
inf2.Format("%d",processID);
m_lCtrl.InsertItem(0,"");//插入行
m_lCtrl.SetItemText(0,0,inf0);
m_lCtrl.SetItemText(0,1,inf2);//设置该行的不同列的显示字符
m_lCtrl.SetItemText(0,2,inf1);
m_lCtrl.SetItemText(0,3,inf3);
CloseHandle( hProcess );
}
}

void CDoProcessDlg::OnGetProcess2()
{
//m_List.ResetContent();
//m_ListID.ResetContent();

CString inf;
HANDLE hProcessSnap = NULL;
PROCESSENTRY32 pe32= {0};
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == (HANDLE)-1)
{
AfxMessageBox("不能建立快照");
return ;
}
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32))
{
   do{
   inf.Format("%s",pe32.szExeFile);
//   m_List.AddString(inf);
   inf.Format("%d",pe32.th32ProcessID);
//   m_ListID.AddString(inf);

}
while (Process32Next(hProcessSnap, &pe32));
}
   else{
//   printf("\nProcess32Firstt() failed:%d",GetLastError());
   }
CloseHandle (hProcessSnap);
}

BOOL CDoProcessDlg::KillProcess(DWORD pid, BOOL bZap)
{
CString inf;
HANDLE hProcess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   AfxMessageBox("无法判断当前操作系统");
   return 0;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   AfxMessageBox("打开本进程访问令牌失败!");
return 0;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
    AfxMessageBox("设置权限错误!");
   return 0;
}

if((hProcess=OpenProcess(PROCESS_TERMINATE,FALSE,pid))==NULL)
{
m_list.AddString("打开进程失败");
return 0;
}
if(TerminateProcess(hProcess,1))m_list.AddString("杀死进程成功\n");
else m_list.AddString("不能杀死进程\n");
}
else{//是95,98操作系统
   hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, DWORD(pid));
if(TerminateProcess(hProcess,1))m_list.AddString("杀死进程成功\n");
else m_list.AddString("不能杀死进程\n");
}
   CloseHandle(hProcess);

return 1;
}

void CDoProcessDlg::OnKillProcess()
{
char path,pID;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       

DWORD processID=(DWORD)atoi((char*)pID);
KillProcess(processID,TRUE);
OnGetProcess2();
}

BOOL CDoProcessDlg::SetPrivilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege)
{
TOKEN_PRIVILEGES tp;//包含访问令牌的权限设置信息
LUID luid;//局部唯一ID值
//第一个参数是系统名,为NULL,表示在本地系统查询;
//第二个参数为要查询的权限名,定义在文件 Winnt.h 中
//如果成功,返回值为非0,其在系统中的 ID 值为第三个参数所指
if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid))
{
AfxMessageBox("查询权限值错误");
return FALSE;
}
tp.PrivilegeCount = 1; //权限列的个数
tp.Privileges.Luid = luid;
if (bEnablePrivilege)
tp.Privileges.Attributes = SE_PRIVILEGE_ENABLED; //使能权限
else
tp.Privileges.Attributes = 0;
//设置 luid 进程的权限
AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
if (GetLastError() != ERROR_SUCCESS)
{
AfxMessageBox("调整权限失败");
return FALSE;
}
return TRUE;
}

void CDoProcessDlg::OnScanProcess()
{
UpdateData();
if(m_Code==""){
        AfxMessageBox("请选择特征字符!");
        return;
}
char path,pID;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       

DWORD processID=(DWORD)atoi((char*)pID);

BYTE *ptr=NULL;

::EnableWindow(m_Scan.m_hWnd,FALSE);
HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}

    BOOL re=FALSE;
    DWORD base=0x400000,min=base,max=base;
        IMAGE_DOS_HEADER      dos_header;
        IMAGE_NT_HEADERS      nt_header;
    IMAGE_SECTION_HEADERsection_header;
    memset(&dos_header,0,sizeof(dos_header));
    memset(&nt_header,0,sizeof(nt_header));
    memset(section_header,0,16*sizeof(IMAGE_SECTION_HEADER));

        re=ReadProcessMemory(hprocess,(LPVOID)base,&dos_header,sizeof(dos_header),NULL);
        base+=dos_header.e_lfanew;
        ReadProcessMemory(hprocess,(LPVOID)base,&nt_header,sizeof(nt_header),NULL);

    if(re==FALSE||nt_header.FileHeader.NumberOfSections==0){
      base=max=min=0x1000000;//有的基本地址为0x400000,有的为0x1000000
      memset(&dos_header,0,sizeof(dos_header));
          re=ReadProcessMemory(hprocess,(LPVOID)base,&dos_header,sizeof(dos_header),NULL);
          base+=dos_header.e_lfanew;
          ReadProcessMemory(hprocess,(LPVOID)base,&nt_header,sizeof(nt_header),NULL);
        }
    if(re==FALSE||nt_header.FileHeader.NumberOfSections==0){
                AfxMessageBox("扫描失败");
                  ::EnableWindow(m_Scan.m_hWnd,TRUE);       
      return;                        }

    base+=sizeof(nt_header);
        ReadProcessMemory(hprocess,(LPVOID)base,§ion_header,\
                nt_header.FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER),NULL);

    min+=section_header.VirtualAddress;
    max+=section_header.VirtualAddress
                  +section_header.SizeOfRawData;

ptr=new BYTE;
if(!ptr){
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("内存不够");
    return;
}

if(!ReadProcessMemory(hprocess,(LPVOID)min,ptr,max-min,NULL)){
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
                  AfxMessageBox("读内存错误!");
                  return;    }

CString inf="";
CString inf2;
re=FALSE;
for(DWORD j=0;j<max-min-7;j++){
          if(!strcmp((char *)(ptr+j),(char*)m_Code.GetBuffer(0))){
                          inf="找到了:";
                          inf2.Format(" %8x,",min+j);
            inf+=inf2;
                          re=TRUE;
                  }
          }
if(re==FALSE)inf="没有找到";
AfxMessageBox(inf);
   if(hprocess)CloseHandle(hprocess);
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
}

void CDoProcessDlg::OnReadMem()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       
CString sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
DWORD processID=(DWORD)atoi((char*)pID);

HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}

    BOOL re=FALSE;
    DWORD base=0x400000;
        if(sbase=="400000")base=0x400000;
        if(sbase=="1000000")base=0x1000000;
    int len=m_Ebase.GetLength();
        m_Ebase.MakeUpper();
        DWORD data=0;
        for(int val=len-1;val>=0;val--){
          if(((char*)m_Ebase.GetBuffer(0))<=(char)'9')
                  data+=((DWORD)((char*)m_Ebase.GetBuffer(0)-0x30)<<((len-val-1)*4));
          else
                  data+=((DWORD)((char*)m_Ebase.GetBuffer(0)-0x41+10)<<((len-val-1)*4));
      }
        base+=data;
//   CString in;
//        in.Format("data=%X",data);
//        AfxMessageBox(in);

    BYTE *ptr=new BYTE;
        memset(ptr,0,1024);
        re=ReadProcessMemory(hprocess,(LPVOID)base,ptr,1024,NULL);
        if(re==FALSE){
      AfxMessageBox("读内存失败");
      return;
        }
    CFile fp;
        fp.Open("c:\\mem.dat",CFile::modeCreate|CFile::modeWrite);
    fp.Write(ptr,1024);
    fp.Close();
    if(hprocess)CloseHandle(hprocess);
}

void CDoProcessDlg::OnChangeCode()
{
UpdateData();
}

void CDoProcessDlg::OnChangeEbase()
{
UpdateData();
}

void CDoProcessDlg::OnChangeEsize()
{
UpdateData();
}

void CDoProcessDlg::OnDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)
{
/*
char lpszText;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, lpszText, 256 );
//   wsprintf(lpszText,"id=%d,%s",m_nIndex);
        AfxMessageBox(lpszText);
*/
*pResult = 0;
}

void CDoProcessDlg::OnChangeEaddress()
{
UpdateData();
}

void CDoProcessDlg::OnChangeEdata()
{
UpdateData();
}

void CDoProcessDlg::OnBWriteMem()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       
CString sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
DWORD processID=(DWORD)atoi((char*)pID);

HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}

    BOOL re=FALSE;
    DWORD base=0x400000;
        if(sbase=="400000")base=0x400000;
        if(sbase=="1000000")base=0x1000000;

    CString in;
    int len=m_Eaddress.GetLength();
        m_Eaddress.MakeUpper();
        DWORD data=0;
        for(int val=len-1;val>=0;val--){
          if(((char*)m_Eaddress.GetBuffer(0))<=(char)'9')
                  data+=((DWORD)((char*)m_Eaddress.GetBuffer(0)-0x30)<<((len-val-1)*4));
          else
                  data+=((DWORD)((char*)m_Eaddress.GetBuffer(0)-0x41+10)<<((len-val-1)*4));
      }
//   in.Format("data=%x,%u",data,data);
//        AfxMessageBox(in);
        base+=data;

    m_Edata.MakeUpper();
        len=m_Edata.GetLength();
    data=0;
        for(val=len-1;val>=0;val--){
          if(((char*)m_Edata.GetBuffer(0))<=(char)'9')
                  data+=((DWORD)((char*)m_Edata.GetBuffer(0)-0x30)<<((len-val-1)*4));
          else
                  data+=((DWORD)((char*)m_Edata.GetBuffer(0)-0x41+10)<<((len-val-1)*4));
      }
//   in.Format("data=%x,%u",data,data);
//        AfxMessageBox(in);
        re=WriteProcessMemory(hprocess,(LPVOID)base,&data,4,NULL);
        if(re==FALSE){
      AfxMessageBox("写内存失败");
      return;
        }
    if(hprocess)CloseHandle(hprocess);
}

void CDoProcessDlg::OnBEnumAllDLL()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
m_list.ResetContent();
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       

CString sbase;

sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
//AfxMessageBox(path);
DWORD processID=(DWORD)atoi((char*)pID);
HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}
//枚举内存
MEMORY_BASIC_INFORMATION mbi;
//typedef struct _MEMORY_BASIC_INFORMATION { /* mbi */
//PVOID BaseAddress; /* 区域的基本地址 */
//PVOID AllocationBase; /* 分配基本地址 */
//DWORD AllocationProtect; /* 初始访问保护 */
//DWORD RegionSize; /* 区域的字节大小 */
//DWORD State; /* 已提交的、保留的、自由的 */
//DWORD Protect; /* 当前访问保护 */
//DWORD Type; /* 页类型 */
//} MEMORY_BASIC_INFORMATION;
//这个结构,在我们的程序中,最关心的是AllocationBase,BaseAddress
//从代码中可以看出AllocationBase 相当于 HMODULE .
//RegionSize则表明了这一块内存的大小。
//ptr += mbi.RegionSize;
//通过者一句,我们接着获取下一个内存块的信息
//通过 GetModuleFileName 我们获取了模块的详细信息

PBYTE ptr = NULL;
DWORD dwBytesReturn = sizeof(MEMORY_BASIC_INFORMATION);
char szBuffer;
char szModuFile;
char szTmpBuffer;
memset(szBuffer,0,256*100);
memset(szModuFile,0,256);
memset(szTmpBuffer,0,256);
int n=1;CString din;
while( dwBytesReturn == sizeof(MEMORY_BASIC_INFORMATION) )
{
dwBytesReturn = VirtualQueryEx(hprocess,ptr,&mbi,sizeof(MEMORY_BASIC_INFORMATION) );
if(mbi.Type == MEM_FREE ) mbi.AllocationBase = mbi.BaseAddress;
//GetModuleFileName( (HINSTANCE)mbi.AllocationBase,szModuFile,256);
    GetModuleFileNameEx(hprocess,(HMODULE)mbi.AllocationBase,szModuFile,256);
switch(mbi.AllocationProtect){
case PAGE_READONLY:
   din="PAGE_READONLY";
break;
case PAGE_READWRITE:
   din="PAGE_READWRITE";
break;
case PAGE_WRITECOPY:
   din="PAGE_WRITECOPY";
break;
case PAGE_EXECUTE:
   din="PAGE_EXECUTE";
break;
case PAGE_EXECUTE_READ:
   din="PAGE_EXECUTE_READ";
break;
case PAGE_EXECUTE_READWRITE:
   din="PAGE_EXECUTE_READWRITE";
break;
case PAGE_EXECUTE_WRITECOPY:
   din="PAGE_EXECUTE_WRITECOPY";
       break;
default: din="OTHER";
}
wsprintf(szTmpBuffer,"%3d)模块名=%s,基地址=%x,大小=%x,属性=%s",n++,szModuFile,ptr,mbi.RegionSize,din);
m_list.AddString(szTmpBuffer);
//if(mbi.AllocationBase == mbi.BaseAddress && mbi.AllocationBase != NULL &&
//mbi.AllocationBase != GetModuleHandle(NULL) )strcat(szBuffer , szTmpBuffer);
ptr += mbi.RegionSize;
}

if(hprocess)CloseHandle(hprocess);        

int tnum=m_list.GetCount( );
if(tnum==LB_ERR)return;
CFile fp;
fp.Open("c:\\dat.txt",CFile::modeCreate|CFile::modeWrite);
for(int ii=0;ii<tnum;ii++){
    m_list.GetText(ii,din);
        din+="\r\n";
    fp.Write(din.GetBuffer(0),din.GetLength());
}
fp.Close();
}

void CDoProcessDlg::OnBChangeAttr()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
m_list.ResetContent();
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       
CString sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
DWORD processID=(DWORD)atoi((char*)pID);
HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}
      CString din;
      DWORD oldProtect;
    m_EAdd_Change.MakeUpper();
        int len=m_EAdd_Change.GetLength();
    DWORD data=0;
        for(int val=len-1;val>=0;val--){
          if(((char*)m_EAdd_Change.GetBuffer(0))<=(char)'9')
                  data+=((DWORD)((char*)m_EAdd_Change.GetBuffer(0)-0x30)<<((len-val-1)*4));
          else
                  data+=((DWORD)((char*)m_EAdd_Change.GetBuffer(0)-0x41+10)<<((len-val-1)*4));
      }
          
          BOOL re=VirtualProtectEx(hprocess,&data,10*1024,PAGE_EXECUTE_READWRITE,&oldProtect);
      if(re)din.Format("地址%X--大小%X :修改成功",data,10*1024);
          elsedin.Format("地址%X--大小%X :修改失败",data,10*1024);
      m_list.AddString(din);
if(hprocess)CloseHandle(hprocess);        

}

void CDoProcessDlg::OnChangeEAddChange()
{
UpdateData();
}

void CDoProcessDlg::OnBgetModule()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
m_list.ResetContent();
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       

CString sbase;

sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
//AfxMessageBox(path);
DWORD processID=(DWORD)atoi((char*)pID);
HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}
}

void CDoProcessDlg::OnBGetAllDLL()
{
char path,pID,based;
POSITION pos = m_lCtrl.GetFirstSelectedItemPosition();
if(pos==NULL){
        AfxMessageBox("请选择进程!");
        return;   
}
m_list.ResetContent();
int m_nIndex = m_lCtrl.GetNextSelectedItem(pos);// 得到项目索引
m_lCtrl.GetItemText(m_nIndex, 2, path, 256 );
m_lCtrl.GetItemText(m_nIndex, 1, pID, 18 );       
m_lCtrl.GetItemText(m_nIndex, 3, based, 20 );       

CString sbase;

sbase=based;
if(sbase=="unknown"){
        AfxMessageBox("超级进程,无法读!");
        return;   
}
//AfxMessageBox(path);
DWORD processID=(DWORD)atoi((char*)pID);
HANDLE hprocess=NULL,hProcessToken=NULL;
OSVERSIONINFO ver;
ver.dwOSVersionInfoSize=sizeof(ver);//必须的,否则不正确
if(!GetVersionEx(&ver)){
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("无法判断当前操作系统");
   return;    }

if(ver.dwPlatformId==VER_PLATFORM_WIN32_NT){//为NT,2000,XP
//杀死所有进程包括服务,在2000以上需要提升权限
//打开某个进程的访问令牌,第一个参数为进程句柄,第二个参数为访问权限,
//第三个参数为函数输出的用来调整权限的句柄
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hProcessToken))
{
   ::EnableWindow(m_Scan.m_hWnd,TRUE);       
   AfxMessageBox("打开本进程访问令牌失败!");
return;
}
//SE_DEBUG_NAME 为要求调试进程的权限
if(!SetPrivilege(hProcessToken,SE_DEBUG_NAME,TRUE))
{
          ::EnableWindow(m_Scan.m_hWnd,TRUE);       
    AfxMessageBox("设置权限错误!");
   return;
}
}
if((hprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,processID))==NULL)
{
    AfxMessageBox("打开进程失败");
                ::EnableWindow(m_Scan.m_hWnd,TRUE);       
        return;
}
//枚举内存
MEMORY_BASIC_INFORMATION mbi;
//typedef struct _MEMORY_BASIC_INFORMATION { /* mbi */
//PVOID BaseAddress; /* 区域的基本地址 */
//PVOID AllocationBase; /* 分配基本地址 */
//DWORD AllocationProtect; /* 初始访问保护 */
//DWORD RegionSize; /* 区域的字节大小 */
//DWORD State; /* 已提交的、保留的、自由的 */
//DWORD Protect; /* 当前访问保护 */
//DWORD Type; /* 页类型 */
//} MEMORY_BASIC_INFORMATION;
//这个结构,在我们的程序中,最关心的是AllocationBase,BaseAddress
//从代码中可以看出AllocationBase 相当于 HMODULE .
//RegionSize则表明了这一块内存的大小。
//ptr += mbi.RegionSize;
//通过者一句,我们接着获取下一个内存块的信息
//通过 GetModuleFileName 我们获取了模块的详细信息

PBYTE ptr = NULL;
DWORD dwBytesReturn = sizeof(MEMORY_BASIC_INFORMATION);
char szBuffer;
char szModuFile;
char szTmpBuffer;
memset(szBuffer,0,256*100);

memset(szTmpBuffer,0,256);
int n=1;CString din;
CString old;
while( dwBytesReturn == sizeof(MEMORY_BASIC_INFORMATION) )
{
memset(szModuFile,0,256);
dwBytesReturn = VirtualQueryEx(hprocess,ptr,&mbi,sizeof(MEMORY_BASIC_INFORMATION) );
if(mbi.Type == MEM_FREE ) mbi.AllocationBase = mbi.BaseAddress;
//GetModuleFileName( (HINSTANCE)mbi.AllocationBase,szModuFile,256);
    GetModuleFileNameEx(hprocess,(HMODULE)mbi.AllocationBase,szModuFile,256);
    //
//if(mbi.AllocationBase == mbi.BaseAddress && mbi.AllocationBase != NULL &&
//mbi.AllocationBase != GetModuleHandle(NULL) )strcat(szBuffer , szTmpBuffer);
ptr += mbi.RegionSize;
if(strlen(szModuFile)<=1)continue;   //不能是等于0,竟然有问号
CString mid=szModuFile;
mid.MakeLower();
if(old==mid)continue;
old=szModuFile;
old.MakeLower();
if(old.Find(".exe",0)!=-1)continue;
wsprintf(szTmpBuffer,"%3d)模块名=%s,开始地址=%8X",n++,szModuFile,ptr-mbi.RegionSize);
m_list.AddString(szTmpBuffer);

}

if(hprocess)CloseHandle(hprocess);        

int tnum=m_list.GetCount( );
if(tnum==LB_ERR)return;
CFile fp;
fp.Open("c:\\dat.txt",CFile::modeCreate|CFile::modeWrite);
for(int ii=0;ii<tnum;ii++){
    m_list.GetText(ii,din);
        din+="\r\n";
    fp.Write(din.GetBuffer(0),din.GetLength());
}
fp.Close();
}


作者:yincheng01 发表于2011-12-15 0:04:40 原文链接

页: [1]
查看完整版本: [原]VC++信息安全编程(13)实现扫描内存,实现内存读写