新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;
}
1万+

被折叠的 条评论
为什么被折叠?



