Skip to content

Instantly share code, notes, and snippets.

@caromdreamer
Created June 27, 2019 05:52
Show Gist options
  • Select an option

  • Save caromdreamer/84b6ec81ffcc392536cc1ad4d26df54c to your computer and use it in GitHub Desktop.

Select an option

Save caromdreamer/84b6ec81ffcc392536cc1ad4d26df54c to your computer and use it in GitHub Desktop.
// ChildView.cpp : CChildView 클래스의 구현
//
#include "stdafx.h"
#include "SearchM.h"
#include "ChildView.h"
#include "OpenDlg.h"
#include "FindDlg.h"
#include "ValueDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CChildView
CChildView::CChildView()
: m_hProcess(NULL)
{
}
CChildView::~CChildView()
{
OnFindClose();
if (m_hProcess)
CloseHandle(m_hProcess);
}
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_SIZE()
ON_COMMAND(ID_FILE_OPEN_PROCESS, OnOpenProcess)
ON_COMMAND(ID_MEM_FIRST, OnFindFirst)
ON_COMMAND(ID_MEM_NEXT, OnFindNext)
ON_COMMAND(ID_MEM_CANCEL, OnFindClose)
ON_LBN_DBLCLK(IDC_VALUELIST, OnSetValue)
END_MESSAGE_MAP()
// CChildView 메시지 처리기
BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CWnd::PreCreateWindow(cs))
return FALSE;
cs.dwExStyle |= WS_EX_CLIENTEDGE;
cs.style &= ~WS_BORDER;
cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS,
::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);
return TRUE;
}
void CChildView::OnPaint()
{
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
// 그리기 메시지에 대해서는 CWnd::OnPaint()를 호출하지 마십시오.
}
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
CRect rc;
GetClientRect(&rc);
if (m_ListBox.Create(WS_VISIBLE|WS_CHILD|WS_VSCROLL|LBS_NOTIFY, rc, this, IDC_VALUELIST) == FALSE)
return -1;
return 0;
}
void CChildView::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (m_ListBox.m_hWnd)
{
m_ListBox.SetWindowPos(NULL, 0, 0, cx, cy, 0);
}
}
void CChildView::OnOpenProcess()
{
COpenDlg dlg;
if (dlg.DoModal() == IDOK)
{
if (m_hProcess)
{
CloseHandle(m_hProcess);
}
m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dlg.m_SelProcessID);
}
}
void CChildView::OnFindFirst()
{
if (!m_hProcess)
return;
CFindDlg dlg;
if (dlg.DoModal() == IDOK)
{
int iCondition = dlg.m_iCondition;
int iCondValue = dlg.m_iCondValue;
if (iCondition == COND_KEEP || iCondition == COND_INCREASE || iCondition == COND_DECREASE)
{
AfxMessageBox("처음 조건으로는 쓸 수 없습니다.", 0, 0);
return;
}
FINDCONDPROC Procs[COND_CNT] = {FCAlways, FCKeep, FCIncrease, FCDecrease,
FCEqual, FCAboveEqual, FCBelowEqual, FCAbove, FCBelow};
FINDCONDPROC Proc = Procs[iCondition];
OnFindClose();
MEMORY_BASIC_INFORMATION mbi;
BYTE* pBaseAddr = NULL;
DWORD dwFoundCount = 0;
while ((int)pBaseAddr < 0x7FFF0000)
{
VirtualQueryEx(m_hProcess, pBaseAddr, &mbi, sizeof(mbi));
pBaseAddr += mbi.RegionSize;
if (mbi.State & MEM_COMMIT)
{
MEMORY_SECTION* pMS = new MEMORY_SECTION;
SAVED_SECTION* pSS = NULL;
BYTE* pReadMemory = new BYTE[mbi.RegionSize];
BYTE* pCurMemory = pReadMemory;
DWORD dwReadSize = 0;
DWORD dwOffset = 0;
DWORD dwSectionNo = 0;
pMS->pBaseAddress = (BYTE*)mbi.BaseAddress;
pMS->dwRegionSize = mbi.RegionSize;
pMS->dwFirstOffset = 0;
BOOL bRet = ReadProcessMemory(m_hProcess, pMS->pBaseAddress, pReadMemory, mbi.RegionSize, &dwReadSize);
if (!bRet || mbi.RegionSize != dwReadSize)
{
delete pMS;
delete []pReadMemory;
continue;
}
for (DWORD dwOff=0; dwOff<dwReadSize; ++dwOff)
{
if (Proc(0, *pCurMemory, iCondValue))
{
if (dwSectionNo == 0)
{
pMS->dwFirstOffset = dwOffset;
dwOffset = 0;
pSS = new SAVED_SECTION;
pSS->pSavedMemory = NULL;
pSS->dwSavedSize = 0;
pSS->dwOffsetToNext = 0;
++dwSectionNo;
}
else if (pSS->pSavedMemory) // 새로운 SAVED_SECTION 시작
{
pSS->dwOffsetToNext = dwOffset;
dwOffset = 0;
pSS = new SAVED_SECTION;
pSS->pSavedMemory = NULL;
pSS->dwSavedSize = 0;
pSS->dwOffsetToNext = 0;
++dwSectionNo;
}
++dwFoundCount;
}
else
{
if (dwSectionNo > 0 && pSS->pSavedMemory == NULL)
{
// dwOffset값은 복사시작부분부터의 거리, 즉 복사 크기
pSS->pSavedMemory = new BYTE[dwOffset];
pSS->dwSavedSize = dwOffset;
CopyMemory(pSS->pSavedMemory, pCurMemory-dwOffset, dwOffset);
pMS->vpSavedSection.push_back(pSS);
}
}
++dwOffset;
++pCurMemory;
}
if (dwSectionNo > 0 && pSS->pSavedMemory == NULL)
{
pSS->pSavedMemory = new BYTE[dwOffset];
pSS->dwSavedSize = dwOffset;
CopyMemory(pSS->pSavedMemory, pCurMemory-dwOffset, dwOffset);
pMS->vpSavedSection.push_back(pSS);
}
delete []pReadMemory;
if (pMS->vpSavedSection.size())
m_vpMemSection.push_back(pMS);
else
delete pMS;
}
}
if (dwFoundCount < 1000)
UpdateList();
if (dwFoundCount == 0)
{
AfxMessageBox("찾지 못 했습니다.", 0, 0);
OnFindClose();
}
}
}
void CChildView::OnFindNext()
{
if (!m_hProcess)
return;
CFindDlg dlg;
if (dlg.DoModal() == IDOK)
{
int iCondition = dlg.m_iCondition;
int iCondValue = dlg.m_iCondValue;
if (iCondition == COND_ALWAYS)
{
AfxMessageBox("처음 조건으로만 쓸 수 있습니다.", 0, 0);
return;
}
FINDCONDPROC Procs[COND_CNT] = {FCAlways, FCKeep, FCIncrease, FCDecrease,
FCEqual, FCAboveEqual, FCBelowEqual, FCAbove, FCBelow};
FINDCONDPROC Proc = Procs[iCondition];
DWORD dwFoundCount = 0;
DWORD dwMSCnt = m_vpMemSection.size();
for (DWORD dwMSNo=0; dwMSNo < dwMSCnt; ++dwMSNo)
{
MEMORY_SECTION* pMS = m_vpMemSection[dwMSNo];
DWORD dwSSCnt = pMS->vpSavedSection.size();
vector<SAVED_SECTION*> vpNewSavedSection;
SAVED_SECTION* pSS = NULL;
DWORD dwIncOffset = pMS->dwFirstOffset;
DWORD dwOffset = dwIncOffset;
DWORD dwPrevOffset = dwOffset;
DWORD dwSectionNo = 0;
for (DWORD dwSSNo=0; dwSSNo < dwSSCnt; ++dwSSNo)
{
SAVED_SECTION* pOldSS = pMS->vpSavedSection[dwSSNo];
BYTE* pReadMemory = new BYTE[pOldSS->dwSavedSize];
BYTE* pCurMemory = pReadMemory;
BYTE* pOldCurMemory = pOldSS->pSavedMemory;
DWORD dwReadSize = 0;
ReadProcessMemory(m_hProcess, pMS->pBaseAddress + dwIncOffset, pReadMemory, pOldSS->dwSavedSize, &dwReadSize);
dwIncOffset += pOldSS->dwOffsetToNext;
for (DWORD dwOff=0; dwOff<dwReadSize; ++dwOff)
{
if (Proc(*pOldCurMemory, *pCurMemory, iCondValue))
{
if (dwSectionNo == 0)
{
pOldSS->dwOffsetToNext -= dwOffset - dwPrevOffset;
pMS->dwFirstOffset = dwOffset;
dwOffset = 0;
pSS = new SAVED_SECTION;
pSS->pSavedMemory = NULL;
pSS->dwSavedSize = 0;
pSS->dwOffsetToNext = 0;
++dwSectionNo;
}
else if (pSS->pSavedMemory) // 새로운 SAVED_SECTION 시작
{
pOldSS->dwOffsetToNext -= dwOffset - dwPrevOffset;
pSS->dwOffsetToNext = dwOffset;
dwPrevOffset = 0;
dwOffset = 0;
pSS = new SAVED_SECTION;
pSS->pSavedMemory = NULL;
pSS->dwSavedSize = 0;
pSS->dwOffsetToNext = 0;
++dwSectionNo;
}
++dwFoundCount;
}
else
{
if (dwSectionNo > 0 && pSS->pSavedMemory == NULL)
{
// dwOffset값은 복사시작부분부터의 거리, 즉 복사 크기
pSS->pSavedMemory = new BYTE[dwOffset];
pSS->dwSavedSize = dwOffset;
CopyMemory(pSS->pSavedMemory, pCurMemory-dwOffset, dwOffset);
vpNewSavedSection.push_back(pSS);
}
}
++dwOffset;
++pCurMemory;
++pOldCurMemory;
}
if (dwSectionNo > 0 && pSS->pSavedMemory == NULL)
{
pSS->pSavedMemory = new BYTE[dwOffset];
pSS->dwSavedSize = dwOffset;
CopyMemory(pSS->pSavedMemory, pCurMemory-dwOffset, dwOffset);
vpNewSavedSection.push_back(pSS);
}
delete []pReadMemory;
pOldSS->dwOffsetToNext += dwPrevOffset;
dwPrevOffset = dwOffset = pOldSS->dwOffsetToNext;
delete []pOldSS->pSavedMemory;
delete pOldSS;
}
pMS->vpSavedSection.clear();
if (vpNewSavedSection.size())
{
pMS->vpSavedSection.insert(pMS->vpSavedSection.begin(), vpNewSavedSection.begin(), vpNewSavedSection.end());
}
else
{
m_vpMemSection.erase(m_vpMemSection.begin() + dwMSNo);
--dwMSCnt;
--dwMSNo;
}
}
if (dwFoundCount < 1000)
UpdateList();
if (dwFoundCount == 0)
{
AfxMessageBox("찾지 못 했습니다.", 0, 0);
OnFindClose();
}
}
}
void CChildView::OnFindClose()
{
if (!m_hProcess)
return;
while (m_vpMemSection.size())
{
MEMORY_SECTION* pMS = m_vpMemSection.back();
while (pMS->vpSavedSection.size())
{
delete []pMS->vpSavedSection.back()->pSavedMemory;
delete pMS->vpSavedSection.back();
pMS->vpSavedSection.pop_back();
}
delete pMS;
m_vpMemSection.pop_back();
}
}
void CChildView::UpdateList()
{
ClearList();
DWORD dwMSCnt = m_vpMemSection.size();
for (DWORD dwMSNo=0; dwMSNo < dwMSCnt; ++dwMSNo)
{
MEMORY_SECTION* pMS = m_vpMemSection[dwMSNo];
DWORD dwSSCnt = pMS->vpSavedSection.size();
DWORD dwIncOffset = pMS->dwFirstOffset;
for (DWORD dwSSNo=0; dwSSNo < dwSSCnt; ++dwSSNo)
{
SAVED_SECTION* pSS = pMS->vpSavedSection[dwSSNo];
for (DWORD dwOff=0; dwOff < pSS->dwSavedSize; ++dwOff)
{
CString str;
str.Format("%08x", pMS->pBaseAddress + dwIncOffset + dwOff);
int Index = m_ListBox.AddString(str);
FINDING_ADDRESS* pFA = new FINDING_ADDRESS;
pFA->pMS = pMS;
pFA->pAddress = pMS->pBaseAddress + dwIncOffset + dwOff;
m_ListBox.SetItemData(Index, (DWORD_PTR)pFA);
}
dwIncOffset += pSS->dwOffsetToNext;
}
}
}
void CChildView::ClearList()
{
DWORD dwItemCnt = m_ListBox.GetCount();
for (DWORD dwIndex=0; dwIndex < dwItemCnt; ++dwIndex)
{
FINDING_ADDRESS* pFA = (FINDING_ADDRESS*)m_ListBox.GetItemData(dwIndex);
delete pFA;
}
m_ListBox.ResetContent();
}
void CChildView::OnSetValue()
{
if (!m_hProcess)
return;
int Index = m_ListBox.GetCurSel();
if (Index != -1)
{
CValueDlg dlg;
if (dlg.DoModal() == IDOK)
{
FINDING_ADDRESS *pFA = (FINDING_ADDRESS*)m_ListBox.GetItemData(Index);
BYTE* pWritingMemory = new BYTE[dlg.m_ValueSize];
DWORD dwWrittenSize = 0;
DWORD dwProtect = 0;
BOOL bRet = TRUE;
CopyMemory(pWritingMemory, &dlg.m_WriteValue, dlg.m_ValueSize);
bRet = VirtualProtectEx(m_hProcess, pFA->pMS->pBaseAddress, pFA->pMS->dwRegionSize, PAGE_READWRITE, &dwProtect);
if (!bRet)
{
AfxMessageBox("VirtualProtect 실패", 0, 0);
}
bRet = WriteProcessMemory(m_hProcess, pFA->pAddress, pWritingMemory, dlg.m_ValueSize, &dwWrittenSize);
if (!bRet || dlg.m_ValueSize != dwWrittenSize)
{
AfxMessageBox("메모리 셋 실패", 0, 0);
}
VirtualProtectEx(m_hProcess, pFA->pMS->pBaseAddress, pFA->pMS->dwRegionSize, dwProtect, 0);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment