2021腾讯游戏安全技术复赛pc客户端安全浅析(一)

看到好多人都在做,菜鸟跟风,有错请指正
本系列分为三部分:
一、剥离dll 二、分析自瞄思路 三、自写代码

在这里插入图片描述
赛题下载地址: https://gslab.qq.com/html/competition/2021/race-final.htm ,选择 PC客户端安全 下载。

1.准备工作

  打开游戏,打开hack.exe,作弊功能未实现。

2.初步探索

  打开IDA,拉入hack.exe,看到15E0处有对文件进行读写的操作,判断此处为验证函数。
在这里插入图片描述

3.找到根源

  F5生成伪代码,可以看到在 CreateFileA 处有判断文件是否存在。
在这里插入图片描述

4.动态调试

  打开x64dbg,定位到15e0处动态调试得出文件名为 hack.dat。
在这里插入图片描述
  在根目录自己建立一个名为hack.dat的文件,在里面随便写点东西。

5.伪代码分析

  回到IDA,分析伪代码。GetFileSize函数返回了hack.dat文件的长度,通过长度来分配内存地址,通过ReadFile函数将hack.dat内容读取放到开辟的地址addrContent中。 在这里插入图片描述

6.首尾呼应

  跳过中间一大串的解密代码,直接来到最后的逻辑判断部分。
在这里插入图片描述

  LABEL16块可以看到了openprocess,不难看出接下来是内存操作,也就是要开始执行外挂功能。注意这里的v14 = pe.th32ProcessID,再通过下面的openprocess可以得出pe.szExeFile为游戏进程名,则ProcName解密后应该为游戏的进程名。

7.回溯解密

  回到中间的解密部分。
在这里插入图片描述
  可以看到ProcName是通过v6的偶数成员组成,而v6来源sub_7FF6E61F14D0,显然它是一个解密函数,在IDA中将其重命名为decode。进入decode函数,可以看到函数分为两块,上面那块是一大段操作块,不去管他,看下面的解密块。
在这里插入图片描述
  直接看v7 v5和v17的关系,不难看出他们都属于指向同一个空间的指针,所以看给v17赋值的最后一个操作,判断出加密操作为与0x3F异或然后减去0x13。

9.反向解码。

  已知目标值为ShooterClient.exe,比较值为0x3F,直接通过C写代码。

int main() {
	system("chcp 437>nul.");
	char a[]="ShooterClient.exe";
	int b[18];
	int c[18];
	for (int i = 0; i <= strlen(a); i++) {
		b[i] = a[i] + 0x13;
		for (int j = 0; j <= 0xff; j++) {
			if ((j ^ 0x3f) == b[i]) {
				c[i] = j;
				break;
			}
		}
	}
	for (int i = 0; i < 18; i++) cout << hex <<c[i] << " ";
	FILE *fp = fopen("hack.dat", "w");
	char t = 0x38;
	fwrite(&t, 1, 1, fp);
	fwrite(&t, 1, 1, fp);
	for (int i = 0; i <= strlen(a); i++) {
		fwrite(&c[i], 1, 1, fp);
		fwrite(&t, 1, 1, fp);
	}
}

  编译,放在根目录运行,生成hack.dat,这时候继续动态分析。

10.寻找flag。

  回到IDA,继续往下分析。可以看到两块循环和一个字符串类型的数据。在IDA中定位得到有字符串的地址为18AC
在这里插入图片描述在这里插入图片描述

  在循环头下断,可以看到是edx和“2RS……”比较,可以看到[rax+r8]的值也是偶数成员拼凑成“ShooterClient.exe”,于是猜测将2RSxx加密则为hack.dat真实数据。于是重写代码得:

int main() {
	system("chcp 437>nul.");
	char a[]="2RSRhrofoWtLeLrJCSlTireznrtx.oeLxuehyyAwbpCOZq0tsS7MZyVdOUoE8";
	int b[62];
	int c[62];
	for (int i = 0; i <= strlen(a); i++) {
		b[i] = a[i] + 0x13;
		for (int j = 0; j <= 0xff; j++) {
			if ((j ^ 0x3f) == b[i]) {
				c[i] = j;
				break;
			}
		}
	}
	for (int i = 0; i < 62; i++) cout << hex <<c[i] << " ";
	FILE *fp = fopen("hack.dat", "w");
	for (int i = 0; i <= strlen(a); i++) {
		fwrite(&c[i], 1, 1, fp);
	}
}

  打开游戏,再打开辅助可以看到功能成功开启,控制台也正确输出flag。
在这里插入图片描述

11.寻找作弊代码。

  回到IDA向下拉,可以看到有对内存进行读写的操作。在之前还进行了开辟内存空间和申请保护页的操作,于是猜测游戏是通过注入dll的方式实现作弊功能 在这里插入图片描述

  于是在WriteProcessMemory处下断,查看r8寄存器。看到r8寄存器中储存的是MZ开头的数据,于是猜测是通过将dll写入到内存,然后通过创建远程线程的方式运行dll。

  再通过上下文得到内存大小为0xFA00
在这里插入图片描述

  将r8处内存以0xfa00的大小dump出来,得到dumpHack.dll。利用CE将dll注入到游戏中,可以得到自瞄开启成功。
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值