Snake内存贪吃蛇(逆向)

新160个CrackMe算法分析-060-snake_哔哩哔哩_bilibili

程序来源于上面这个链接

主要程序逻辑

为了方便分析,和虚拟运行,程序的输入步数全部为1步

简单代码实现,太忙了,准备打比赛,没时间精细修改,也没有去使用什么深度,广度..算法什么的,想到什么方法就随便写了一下

#include <iostream>
#include <Windows.h>
#include <vector>
#include <deque>
#include <string>
using namespace std;
char GameMm[0x120] = { 0 };

struct Path {
	char x;
	char y;
	char value;
	bool operator == (Path& other)const {
		return x == other.x && y == other.y;
	}
	void operator =(const Path& other) {
		x = other.x;
		y = other.y;
		value = other.value;
	}

	void operator -(const Path& other) {
		x - other.x;
		y - other.y;
	}

	void operator +(const Path& other) {
		x + other.x;
		y + other.y;
	}

	void operator +=(const Path& other) {
		x += other.x;
		y += other.y;
	}

	void operator -=(const Path& other) {
		x -= other.x;
		y -= other.y;
	}
};

struct Position
{
	char x;
	char y;
	char value;
	bool operator==(Position& other) const {	//去除值的等于,方便位置比较
		return x == other.x && y == other.y;
	}

	void operator=(const Position& other) {
		x = other.x;
		y = other.y;
	}

	void operator+=(const Position& other) {
		x += other.x;
		y += other.y;
	}

	void operator+=(const Path& Path) {
		x += Path.x;
		y += Path.y;
	}

	void operator+(const Path& Path) {
		x + Path.x;
		y + Path.y;
	}

	void operator-(const Path& Path) {
		x - Path.x;
		y - Path.y;
	}

	void operator-=(const Position& other) {
		x -= other.x;
		y -= other.y;
	}

	void operator-=(const Path& Path) {
		x -= Path.x;
		y -= Path.y;
	}
};

Path Right = { 1,0,'3' };
Path Left = { -1,0,'2' };
Path Up = { 0,-1,'1' };
Path Down = { 0,1,'0' };

//计算两点之间的距离
DWORD GetPosLength(const Position& start, const Position& end) {
	return (DWORD)(end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y);  //可以加abs
}
//vec中距离start最近点的索引
DWORD GetMinLength(vector<Position>& vec, const Position& start) {
	DWORD* arrSize = new DWORD[vec.size()];
	for (size_t i = 0; i < vec.size(); i++)
	{
		arrSize[i] = GetPosLength(vec[i], start);
	}
	DWORD min = 0;
	for (size_t i = 0; i < vec.size(); i++)
	{
		DWORD len = arrSize[i];
		if (len < arrSize[min]) {
			min = i;
		}
	}
	return min;
}
//对vec进行路径规划存放到list中
void Sort(vector<Position>& list, vector<Position> vec, Position start) {
	//可以加入去除重复
	do {
		int min = GetMinLength(vec, start);
		list.push_back(vec[min]);
		start = vec[min];
		vec.erase(vec.begin() + min);  // 删除vec中索引为min的元素
		if (vec.size() == 1) {
			list.push_back(vec[0]);
			break;
		}
	} while (true);
}
//判断start经过x,y是否路过point
bool InLine(Position& start, int x, int y, Position& point) {
	if (x == 0) {
		return point.y < max(start.y, start.y + y) && point.y > min(start.y, start.y + y);
	}
	if (y == 0) {
		return point.x < max(start.x, start.x + x) && point.x > min(start.x, start.x + x);
	}
	cout << "InLine参数错误" << endl;
	return false;
}
//判断point是否在start和end之间
bool InLinePoint(Position& start, Position& end, Position& point) {
	int x = end.x - start.x;
	int y = end.y - start.y;

	if (InLine(start, 0, y, point)) {
		return true;
	}

	if (InLine(start, x, 0, point)) {
		return true;
	}

	return false;
}
//修改路径重叠,list路径中去除point,举例终点
void ChangePass(vector<Position>& list, Position& point) {
	for (size_t i = 0; i < list.size() - 1; i++)
	{
		if (InLinePoint(list[i], list[i + 1], point)) {
			int x = point.x;
			int y = point.y;
			if (list[i + 1].x > 8) {
				x--;
			}
			if (list[i + 1].y > 8) {
				y--;
			}
			Position buf = { x,y,0 };
			list.insert(list.end() -1, buf);
		}
	}
}
//将list路径转换为字符串route			string& route
void PrintPass(vector<Position>& list, vector<Path>& path) {
	for (size_t i = 0; i < list.size() - 1; i++)
	{
		int x = list[i + 1].x - list[i].x;
		int y = list[i + 1].y - list[i].y;

		//判断四个方向  ->计算步长

		//上
		if (y < 0) {
			DWORD dwDis = abs(y);
			for (size_t i = 0; i < dwDis; i++)
			{
				//route.append("1");
				path.push_back(Up);
			}
		}
		//下
		if (y > 0) {
			DWORD dwDis = abs(y);
			for (size_t i = 0; i < dwDis; i++)
			{
				//route.append("0");
				path.push_back(Down);
			}
		}
		//左
		if (x < 0) {
			DWORD dwDis = abs(x);
			for (size_t i = 0; i < dwDis; i++)
			{
				//route.append("2");
				path.push_back(Left);
			}
		}
		//右
		if (x > 0) {
			DWORD dwDis = abs(x);
			for (size_t i = 0; i < dwDis; i++)
			{
				//route.append("3");
				path.push_back(Right);
			}
		}
	}
}
char* CalcAddress(Position& point) {
	return (GameMm + 0x10 + point.x + point.y * 0x10);
}

void DrawPoint(char* address, char value) {
	*address = value;
}

void DrawSnake(deque<Position>& snake) {
	for (size_t i = 0; i < snake.size(); i++)
	{
		DrawPoint(CalcAddress(snake[i]), 0x99);
	}
}

void ClearSnake(deque<Position>& snake) {
	DrawPoint(CalcAddress(snake[snake.size() - 1]), 0x00);
	snake.pop_back();
}

bool CheckSnake(deque<Position>& snake, const Path& path) {
	Position end = snake[0];
	end += path;

	//检查蛇是否重叠			重叠=false   不重叠=true
	for (size_t j = 0; j < snake.size() - 1; j++) {
		if (end == snake[j + 1]) {
			//重叠
			//printf("蛇重叠在X:%d Y:%d\n", end.x, end.y);
			return false;
		}
	}
	return true;
}

int main() {
	
	//char UserName[] = "sun";		//11111122222211113113000000033333
	//char UserName[] = "myself";	//03300000333111111111112222112222222
	//char UserName[] = "12345";	//0213333311111111111202222222211220000031111133333333333
	//char UserName[] = "OllyDBG";	//11112221112112222220000030333002033333333
	//char UserName[] = "wanao";	//11111222220333330000222222222221111112222131113300000022213010
	//char UserName[] = "AyinYyds";	//果实生成重复,不好计算

	//初始化内存
	memset(GameMm, 0xFF, 0x10);                     // 0x00 ~ 0x0F: 0xFF设置上边界
	memset(&GameMm[0x10], 0, 0x100);                // 0x10 ~ 0x10F: 0x00
	memset(&GameMm[0x110], 0xFF, 0x10);             // 0x110 ~ 0x11F: 0xFF

	/*	内存布局相当于这个   左上角为原点(不包括0xFF)    y=(address-基地址)/ 0x10    y=(address-基地址)mod 0x10
		FFFFFFFFFFFF
		000000000000
		000000000000
		............
		000000000000
		000000000000
		FFFFFFFFFFFF
	*/

	//记录字符求和
	byte sum = 0;
	for (int i = 0; UserName[i]; i++) {
		sum += UserName[i];
	}
	//生成果实0xCC
	byte al = 0;
	DWORD dwCount = 0;	//记录果实个数
	int i = 0;
	do
	{
		al = UserName[i];
		al = al xor sum;
		sum -= al;
		*(GameMm + 0x10 + al) |= 0xCC;	//标记0xCC
		i++;
		dwCount++;
	} while (UserName[i]);

	//生成终点0xDD
	sum = sum xor al;
	DWORD isCon = false;
	do
	{
		isCon = false;
		al -= sum;
		if (*(GameMm + 0x10 + al) == 0xCC) {	//防止覆盖0xCC
			isCon = true;
			sum--;
		}
	} while (isCon);
	*(GameMm + 0x10 + al) = 0xDD;

	//生成起点0x99
	al = sum;
	DWORD address = 0;		//起点内存偏移	
	do
	{
		if (*(GameMm + 0x10 + al) != 0xCC) {
			if (*(GameMm + 0x10 + al) != 0xDD) {
				address = al;
				*(GameMm + 0x10 + al) = 0x99;
				break;
			}
		}
		al--;
	} while (true);

	//遍历内存并添加果实到foods中
	int count = 0;
	Position start = { address % 0x10, address / 0x10,0x99 };	//起点
	vector<Position> foods;	//果实路径
	//vec.push_back(start);
	Position end = { 0,0,0xDD };	//终点
	for (int i = 0; i < sizeof(GameMm) - 0x20; i++) {
		byte value = GameMm[i + 0x10];

		if (value == 0xCC) {
			Position pos = { 0,0,0xCC };
			pos.x = i % 0x10;
			pos.y = i / 0x10;
			foods.push_back(pos);
			count++;
		}
		if (value == 0xDD) {
			end.x = i % 0x10;
			end.y = i / 0x10;
			end.value = 0xDD;
		}
	}
	//生成果实数量和真实找到的不一样,说明有位置重复生成
	if (count != dwCount || foods.size() != count) {
		cout << "果实数量不匹配!" << endl;
	}

	vector<Position> FoodRoute;	//蛇的运动路径:果实路径
	vector<Position> route;	//蛇的运动路径:->果实->终点
	Sort(FoodRoute, foods, start);
	route = FoodRoute;
	route.insert(route.begin(), start);	//添加起点
	route.push_back(end);				//添加终点


	//修改重叠路径
	ChangePass(route,end);	//终点在路径中间问题



	vector<Path> path;
	PrintPass(route, path);

	//蛇开始运动,进行动态校验
	int LenSnake = 1;
	deque<Position> snake;	//蛇
	FoodRoute.push_back(end);	//添加终点  这个也算到起点中去
	snake.push_front(start);				//添加起点
	for (size_t i = 0; i < path.size(); i++)
	{
		if (CheckSnake(snake, path[i])) {
			//不重叠
			start += path[i];
		}
		//重叠
		else {
			Path buf = path[i];
			path.erase(path.begin() + i);
			//换方向绕      
			if (snake[1].x== snake[0].x) {
				if (snake[0].x > 8) {
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + j, Left);
					}
					path.insert(path.begin() + i + dwCount, buf);
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + dwCount + j+1, Right);
					}
					i--;
					continue;
				}
				else {
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + j, Right);
					}
					path.insert(path.begin() + i + dwCount, buf);
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + dwCount + j+1, Left);
					}
					i--;
					continue;
				}
			}
			if (snake[1].y== snake[0].y) {
				if (snake[0].y > 8) {
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + j, Up);
					}
					path.insert(path.begin() + i + dwCount, buf);
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + dwCount + j+1, Down);
					}
					i--;
					continue;
				}
				else {
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + j, Down);
					}
					path.insert(path.begin() + i + dwCount, buf);
					for (size_t j = 0; j < dwCount; j++)
					{
						path.insert(path.begin() + i + dwCount + j+1, Up);
					}
					i--;
					continue;
				}
			}
		}



		if (FoodRoute.size() == 0)break;
		if (start == FoodRoute.at(0)) {
			//吃到果实,调整蛇的长度
			//snake.push_back(start);
			FoodRoute.erase(FoodRoute.begin());	//去除果实
			LenSnake++;
		}
		else {
			ClearSnake(snake);
		}
		//添加蛇位置
		//画蛇
		snake.push_front(start);
		DrawSnake(snake);


	}
	//输出passWord
	for (size_t i = 0; i < path.size(); i++)
	{
		cout << path[i].value;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值