zoukankan      html  css  js  c++  java
  • 逆向实战 | win7扫雷逆向&辅助实现

    win7扫雷逆向&辅助实现

    做这个事情是因为软件工程上机课太无聊了,就开始玩扫雷,但是觉得原版界面有点太丑了,就想自己改一改。

    参考的资料还挺多的,这个讲xp扫雷的讲的比较好(https://www.cnblogs.com/iBinary/p/7533292.html),但是不太适用于win7版本的扫雷。

    首先在win10上运行win7的扫雷需要patch一下程序最开头对信息的校验。

    然后使用ida分析的时候可以下载网络上的pdb进行分析。

    分析雷在内存中的存储

    首先通过的是Game::Load()这样一个函数来定位到对宽高雷数量的判定:
    image

    然后继续往下翻,发现Board::Board这样一个构造函数,应该是对扫雷的板子进行初始化了:
    image

    直接跟进去,在里面找到了对扫雷的板子的具体初始化函数:
    image

    最后定位到是一个二重循环对Array<UITile>类型的游戏板子进行了初始化!
    注:推测UITile继承了NodeBase。
    image

    之后的分析就采用动静结合的方式,有一个文章写得比较好:https://www.itdaan.com/blog/2017/05/06/d8daff1e0db2e3334cefc7aec9c0e351.html
    总的来说就是对创建雷的部分进行下断点然后往上层函数进行分析。
    关键部分:
    image

    上面这个部分为我们提供了关键判断,方便我们通过v3(this指针)去找到雷的位置。

    之后就写了一个测试脚本去提出雷(上面省略了用ce继续查基址的部分(很简单的))
    直接丢代码了:

    #include <windows.h>
    #include <stdio.h>
    #include <tlhelp32.h>
    #include <string.h>
    int main(){
    	// 获取pid
    	HWND hWnd = FindWindow(NULL, "扫雷");
    	DWORD pid = NULL;
    	GetWindowThreadProcessId(hWnd, &pid);
    	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
    	printf("hProcess: %p 
    ", hProcess);
    
    	// 获取模块地址
    	DWORD modaddr = NULL;
    	MODULEENTRY32 modentry;
    	memset(&modentry, 0, sizeof(modentry));
    	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,pid);
    	modentry.dwSize = sizeof(MODULEENTRY32);
    	Module32First(hSnapshot, &modentry);
    	do{
    		if (strcmp(modentry.szModule, "MineSweeper.exe") == 0)
    		{
    			modaddr = (DWORD)modentry.hModule;
    			CloseHandle(hSnapshot);
    			break;
    		}
    	}while(Module32Next(hSnapshot, &modentry));
    	printf("modaddr: %p 
    ", modaddr);
    
    	int a[16][16] = {0};
    	int x = 0;
    	int y = 0;
    
    	//[[[[[ecx+17*4]+12]+列index]+12]+行index]
    	//ecx = [[MineSweeper.exe+868B4]+0x10]
    	DWORD pObj = modaddr;
    	ReadProcessMemory(hProcess, (LPCVOID)(pObj+0x868B4), &pObj, 4, 0);
    	ReadProcessMemory(hProcess, (LPCVOID)(pObj+0x10), &pObj, 4, 0);
    	printf("ecx: %p 
    ", pObj);
    	ReadProcessMemory(hProcess, (LPCVOID)(pObj+17*4), &pObj, 4, 0);
    	ReadProcessMemory(hProcess, (LPCVOID)(pObj+12), &pObj, 4, 0);// 此时pObj指向列array
    
    
    	
    	DWORD lie;  // 一列一列处理
    	BYTE tmp = 0;
    	
    	for (y = 0; y < 16; y ++){
    		ReadProcessMemory(hProcess, (LPCVOID)(pObj+y*4), &lie, 4, 0);
    		ReadProcessMemory(hProcess, (LPCVOID)(lie+12), &lie, 4, 0);
    		for (x = 0; x < 16; x ++)
    		{
    			ReadProcessMemory(hProcess, (LPCVOID)(lie+x), &tmp, 1, 0);
    			//printf("%d ", tmp);
    			a[x][y] = tmp;
    		}
    	}
    	
    
    	
    
    	printf("下面是雷区:
    ");
    
    	// 输出雷区
    	for(x = 0; x < 16; x ++){
    		for (y = 0; y < 16; y ++){
    			printf("%d ", a[x][y]);
    		}
    		printf("
    ");
    	}
    
    	CloseHandle(hProcess);
    
    	return 0;
    }
    

    效果图:
    image

    接着就是实现一个外挂dll了(注入的部分就省略了反正怎么注入都一样):

    // apparent.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include <stdio.h>
    
    
    extern "C" __declspec(dllexport) VOID __stdcall haha(){
    	MessageBox(0,"hahaha",0,0);
    }
    
    
    DWORD WINAPI ThreadProc(LPVOID lpParameter){
    	char buf[1000] = {0};         // 输出缓冲区
        //MessageBox(0,"Mz1dll注入成功,enjoy it!", "Welcome",0);
    
    	DWORD pid = GetCurrentProcessId();
    	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);// 获取当前句柄
    	HMODULE hModule = GetModuleHandle(NULL);
    	//sprintf(buf, "hModule: %p", hModule);
    	//MessageBox(0, buf, 0, 0);
    	//sprintf(buf, "pid: %p
    句柄: %p", pid, hProcess);
    	//MessageBox(0,buf,"提示", 0);
    	while(1){
    		Sleep(2000);
    		int a[16][16] = {0};
    		int x = 0;
    		int y = 0;
    		
    		//[[[[[ecx+17*4]+12]+列index]+12]+行index]
    		//ecx = [[MineSweeper.exe+868B4]+0x10]
    		DWORD pObj = (DWORD)hModule;
    		ReadProcessMemory(hProcess, (LPCVOID)(pObj+0x868B4), &pObj, 4, 0);
    		ReadProcessMemory(hProcess, (LPCVOID)(pObj+0x10), &pObj, 4, 0);
    		printf("ecx: %p 
    ", pObj);
    		ReadProcessMemory(hProcess, (LPCVOID)(pObj+17*4), &pObj, 4, 0);
    		ReadProcessMemory(hProcess, (LPCVOID)(pObj+12), &pObj, 4, 0);// 此时pObj指向列array
    		
    		
    		
    		DWORD lie;  // 一列一列处理
    		BYTE tmp = 0;
    		
    		for (y = 0; y < 16; y ++){
    			ReadProcessMemory(hProcess, (LPCVOID)(pObj+y*4), &lie, 4, 0);
    			ReadProcessMemory(hProcess, (LPCVOID)(lie+12), &lie, 4, 0);
    			for (x = 0; x < 16; x ++)
    			{
    				ReadProcessMemory(hProcess, (LPCVOID)(lie+x), &tmp, 1, 0);
    				//printf("%d ", tmp);
    				a[x][y] = tmp;
    			}
    		}
    
    		// 展现图形化提示
    		int index = 0;
    		char tip[] = "下面是雷区提示:
    ";
    		sprintf(buf, tip);
    		index += sizeof(tip);
    		index -= 1;
    
    		for (x = 0; x < 16; x ++){
    			for (y = 0; y < 16; y ++){
    				//buf[index] = a[x][y]+'0';
    				sprintf(buf+index, "%d ", a[x][y]);
    				index += 2;
    			}
    			buf[index] = '
    ';
    			index ++;
    			buf[index] = '
    ';
    			index ++;
    		}
    		MessageBox(0, buf, "tip", 0);
    	}
        return 0;
    }
    
    
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
    	switch ( ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:
            // 执行需要的代码
    		CreateThread(NULL,0,
                (LPTHREAD_START_ROUTINE)ThreadProc,
                NULL, 0,NULL);//创建新线程执行代码
            break;
        case DLL_PROCESS_DETACH:
            break;
        case DLL_THREAD_ATTACH:
            break;
        case DLL_THREAD_DETACH:
            break;
        }
    	
        return TRUE;
    }
    

    这个dll会弹框显示雷区内存。
    做的比较粗糙,但是原理基本上就是这个亚子。

    演示:
    image

    差不多就这样~

    本文来自博客园,作者:Mz1,转载请注明原文链接:https://www.cnblogs.com/Mz1-rc/p/15396115.html

    如果有问题可以在下方评论或者email:mzi_mzi@163.com

  • 相关阅读:
    电脑常用快捷键
    k8s node 系统参数调整
    docker 制作镜像并上传
    php服务部署安装
    安装 Kuboard v2
    keepalive配置
    elasticsearch的segment详解
    grafana模板
    jenkins启动
    kubernetes 中文文档
  • 原文地址:https://www.cnblogs.com/Mz1-rc/p/15396115.html
Copyright © 2011-2022 走看看