zoukankan      html  css  js  c++  java
  • 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
    ", hw);
    	else return false;
    
    	GetWindowThreadProcessId(hw, &pid);
    	if(pid) printf("成功获取目标进程号:%d
    ", pid);
    	else return false;
    	
    	hp = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    	if (hp) printf("成功获取目标进程句柄:%X
    ", 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("成功修改代码段内存保护属性
    ");
    	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("成功修改内存
    ");
    	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!
    ");
    	else return;
    	inj.DoInjection();
    	inj.UnInit();
    }
    
  • 相关阅读:
    OpenSSH免密码登录SSH2
    mysql_init调用卡住原因分析
    磁盘文件读性能测试
    madvise、fadvise、posix_madvise和posix_fadvise函数的使用
    进程间传递文件描述符fd
    Orace开源的异步IO编程库,特点是接口非常简单
    爱奇艺视频窗口显示不出来解决办法
    brk/sbrk和mmap行为分析程序
    编译boost,去掉不使用的组件
    第24课 经典问题解析二
  • 原文地址:https://www.cnblogs.com/raymondking123/p/11337854.html
Copyright © 2011-2022 走看看