- Published on
Chessato
- Authors
- Name
- Cappybara
The game is about beating a chess that follows a specific rules, like when we move some pawn, it imediately is taken by black pawn, so it basically teleports.
In the challenge description we can read that we have to beat black player in one move, obviously we can't do that in normal chess, so we have to cheat.
Game is made in popular Unity Engine
, with Mono
build, that means, we can recover source code stored in Assembly-CSharp.dll
located in Chessato\Chess_2025_Data\Managed\
To decompile this .dll we can Use dnSpy
tool.
After importing Assembly-CSharp
to dnSpy
, we can see some Classes, let's open Game class first.
Let's check this Game methods, We'll start with exploring Start()
and Winner()
.
public void Start()
{
this.playerWhite = new GameObject[]
{
this.Create("white_rook", 0, 0),
this.Create("white_knight", 1, 0),
this.Create("white_bishop", 2, 0),
this.Create("white_queen", 3, 0),
this.Create("white_king", 4, 0),
this.Create("white_bishop", 5, 0),
this.Create("white_knight", 6, 0),
this.Create("white_rook", 7, 0),
this.Create("white_pawn", 0, 1),
this.Create("white_pawn", 1, 1),
this.Create("white_pawn", 2, 1),
this.Create("white_pawn", 3, 1),
this.Create("white_pawn", 4, 1),
this.Create("white_pawn", 5, 1),
this.Create("white_pawn", 6, 1),
this.Create("white_pawn", 7, 1)
};
this.playerBlack = new GameObject[]
{
this.Create("black_rook", 0, 7),
this.Create("black_knight", 1, 7),
this.Create("black_bishop", 2, 7),
this.Create("black_queen", 3, 7),
this.Create("black_king", 4, 7),
this.Create("black_bishop", 5, 7),
this.Create("black_knight", 6, 7),
this.Create("black_rook", 7, 7),
this.Create("black_pawn", 0, 6),
this.Create("black_pawn", 1, 6),
this.Create("black_pawn", 2, 6),
this.Create("black_pawn", 3, 6),
this.Create("black_pawn", 4, 6),
this.Create("black_pawn", 5, 6),
this.Create("black_pawn", 6, 6),
this.Create("black_pawn", 7, 6)
};
for (int i = 0; i < this.playerBlack.Length; i++)
{
this.SetPosition(this.playerBlack[i]);
this.SetPosition(this.playerWhite[i]);
}
}
We can see pawns being created here, could be useful later.
Winner()
method is much longer, but we can see that there is some logic for winning for white player, let's add a line at the end of Start()
, with Winner("white");
Right click on Start()
, Edit method, add Winner("white");
after the loop and click Compile
. Also save Assembly-CSharp.dll
and run the game.
It didn't work, let's find out why, let's go back to Winner()
method.
public void Winner(string playerWinner){
<------------------------------------->
int[,] matrix = this.RM(array2);
byte[] key = this.F1(array);
byte[] iv = this.F2(matrix);
string cipherText = "LlfqPs1MOul1Jr09d6dZditrkXUgIfMDc3Lh6/z5Ufv6E2G8ARHNvE7xQ9jrGBRg";
string text = this.FW(cipherText, key, iv);
GameObject.FindGameObjectWithTag("WinnerText").GetComponent<Text>().fontSize = 24;
GameObject.FindGameObjectWithTag("WinnerText").GetComponent<Text>().text = text;
GameObject.FindGameObjectWithTag("RestartText").GetComponent<Text>().text = "Check your clipboard!";
GUIUtility.systemCopyBuffer = text;
}
We can see that this section of code, should give us flag, there is cipherText encoded in base64
, and then decrypted using AES
cipher, using key for white's pawn positions, and iv for black position.
This whole code, could be rewritten in python, but we can get a quicker solution with only one change. As we recall earlier, we have to beat the Black with only one move, Black wins by taking White King with a Black one (yeah not possible in real chess), so let's do the same with our White King.
Let's go back to our Start()
method where, all pawns are declared, and change position of White King, to the same as Black King.
public void Start()
{
this.playerWhite = new GameObject[]
{
this.Create("white_rook", 0, 0),
this.Create("white_knight", 1, 0),
this.Create("white_bishop", 2, 0),
this.Create("white_queen", 3, 0),
this.Create("white_king", 4, 7), # Was 4, 0
this.Create("white_bishop", 5, 0),
this.Create("white_knight", 6, 0),
this.Create("white_rook", 7, 0),
this.Create("white_pawn", 0, 1),
this.Create("white_pawn", 1, 1),
this.Create("white_pawn", 2, 1),
this.Create("white_pawn", 3, 1),
this.Create("white_pawn", 4, 1),
this.Create("white_pawn", 5, 1),
this.Create("white_pawn", 6, 1),
this.Create("white_pawn", 7, 1)
};
this.playerBlack = new GameObject[]
{
this.Create("black_rook", 0, 7),
this.Create("black_knight", 1, 7),
this.Create("black_bishop", 2, 7),
this.Create("black_queen", 3, 7),
this.Create("black_king", 4, 7),
this.Create("black_bishop", 5, 7),
this.Create("black_knight", 6, 7),
this.Create("black_rook", 7, 7),
this.Create("black_pawn", 0, 6),
this.Create("black_pawn", 1, 6),
this.Create("black_pawn", 2, 6),
this.Create("black_pawn", 3, 6),
this.Create("black_pawn", 4, 6),
this.Create("black_pawn", 5, 6),
this.Create("black_pawn", 6, 6),
this.Create("black_pawn", 7, 6)
};
for (int i = 0; i < this.playerBlack.Length; i++)
{
this.SetPosition(this.playerBlack[i]);
this.SetPosition(this.playerWhite[i]);
}
this.Winner("white");
}
And here is our flag!