C++基础之:扫雷破解

版权声明:

  • 本文原创发布于博客园"优梦创客"的博客空间(网址:http://www.cnblogs.com/raymondking123/)以及微信公众号"优梦创客"
  • 您可以自由转载,但必须加入完整的版权声明!

内存扫描

使用Cheat Engine这款软件对扫雷的进程的内存进行扫描。查找与游戏获胜相关的内存区域。
扫描结果如下:

<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="26">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"棋盘首地址"</Description>
      <LastState Value="15" RealAddress="01005361"/>
      <VariableType>Byte</VariableType>
      <Address>扫雷.exe+5361</Address>
    </CheatEntry>
    <CheatEntry>
      <ID>1</ID>
      <Description>"玩家未确定的地雷数"</Description>
      <LastState Value="10" RealAddress="01005194"/>
      <VariableType>Byte</VariableType>
      <Address>扫雷.exe+5194</Address>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
</CheatTable>

代码跟踪

使用x32dbg工具调试扫雷的进程,追踪扫雷代码。发现扫雷的判断条件是内存0x010057A4和0x010057A0值是否相等。
判定代码在代码段的0x0100359c区域。

破解

获取扫雷窗口句柄
获取扫雷进程号
获取扫雷进程句柄
修改代码段内存的保护属性
修改判定代码

详细代码
Injection.h

#pragma once

#include <string>
#include <Windows.h>
//#define ___DEBUG
class Injection
{
public:
	Injection(const char*);
	bool Init();
	bool DoInjection();
	void UnInit();
private:
	std::wstring className;
	HWND hw;
	DWORD pid; 
	HANDLE hp; 
	SIZE_T wr;
};

Injection.cpp

#include "stdafx.h"
#include "Injection.h"
#include <comutil.h> 
#pragma comment(lib, "comsuppw.lib")

Injection::Injection(const char * className)
	:hw(0), pid(0), hp(0), wr(0)
{
	_bstr_t tmp = className;
	this->className = (wchar_t*)tmp;
}

bool Injection::Init()
{
	hw = FindWindow(this->className.c_str(), NULL);
	if (hw) printf("找到目标进程窗口,窗口句柄:%X\n", hw);
	else return false;

	GetWindowThreadProcessId(hw, &pid);
	if(pid) printf("成功获取目标进程号:%d\n", pid);
	else return false;
	
	hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
	if (hp) printf("成功获取目标进程句柄:%X\n", hp);
	else return false;

	return true;
}
// 0x010057A4
// 0x010057A0

// 0x0100359c
bool Injection::DoInjection()
{
#ifndef ___DEBUG
	if (VirtualProtectEx(hp, (int*)0x0100359c, 5, PAGE_EXECUTE_READWRITE, &wr))
		printf("成功修改代码段内存保护属性\n");
	else return false;
	// mov eax, dword ptr ds : [0x010057A0]
	char a[] = { 0xA1, 0xA0, 0x57, 0x00, 0x01 };
	if (WriteProcessMemory(hp, (int*)0x0100359c, a, 5, &wr))
		printf("成功修改内存\n");
	else return false;
#endif
	return true;
}

void Injection::UnInit()
{
	CloseHandle(hp);
}

main.cpp

#include"Injection.h"

void main(int argc, char *argv[])
{
#ifndef ___DEBUG
	if (!argc)
		return;
	Injection inj(argv[1]);
#else
	Injection inj("扫雷");
#endif // !1
	if (inj.Init()) printf("Init Success!\n");
	else return;
	inj.DoInjection();
	inj.UnInit();
}
posted @ 2019-08-12 09:21  优梦创客  阅读(1854)  评论(0编辑  收藏  举报