Okay, so I made a pretty cool ESP/Aimbot for Valorant. However, whenever Brimstone activates his ultimate; Vanguard seems to place a hook on my radar to look for lost vectors.
I have logged the strange occurrance, I'm confident that I can fix the error if I can just view the radar before it crashes...
Background Knowledge
Not much background knowledge is required here! Just be able to read code at a decent level, and some very basic knowledge about file types and scripting.
Solution
The player is given an Aimbot.zip which contains the source code for an ESP coded in C# for Valorant.
Feel free to spend a bit of time looking into how the cheat works, and how it hooks onto the valorant process. We'll go straight to the main function located at "Program.cs".
Program.cs
using System;
using System.IO;
using System.Windows.Forms;
using Immortal.SDK.Extensions;
using Immortal.SDK.Extensions;
using ValorantColorAimbot;
namespace Immortal
{
internal static class Program
{
[STAThread]
private static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
File.Move(Application.ExecutablePath, Application.StartupPath + "\\" + new RandomGenerator().RandomString(8, true) + ".exe");
Application.Run(new SplashScreen());
}
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e, string message = "Crash has occurred.")
{
ValorantColorAimbot.Program.CrashHandler(message, e.ExceptionObject.ToString());
// Logger is located at Aimbot C#.cs :)
Logger(e.ExceptionObject.ToString());
}
}
}
The main thread spawns a new process and hooks into the Valorant exe and draws the ESP by creating a new object SplashScreen.
The challenge mentions that the solution is located somewhere related to the crashing of the game, which is handled by the CurrentDomain_UnhandledException function.
Exception Handler
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e, string message = "Crash has occurred.")
{
ValorantColorAimbot.Program.CrashHandler(message, e.ExceptionObject.ToString());
// Logger is located at Aimbot C#.cs :)
Logger(e.ExceptionObject.ToString());
}
And, the challenge author nicely told you where to locate the Logger function!
AimbotC#.cs
public static function Failure(RegionIn_Bitmap As Bitmap, RegionIn_BitmapData As BitmapData, Formatted_Color As Integer(), row As Byte(), x As Integer, y As Integer)
{
RegionIn_Bitmap.UnlockBits(RegionIn_BitmapData);
using (StreamWriter writer = new StreamWriter("crash_log.txt"))
{
int[] Formatted_Color = new int[3] { Pixel_Color.B, Pixel_Color.G, Pixel_Color.R }; //bgr
unsafe {
for (int y = 0; y < RegionIn_BitmapData.Height; y++) {
byte* row = (byte*)RegionIn_BitmapData.Scan0 + (y * RegionIn_BitmapData.Stride);
for (int x = 0; x < RegionIn_BitmapData.Width; x++) {
if (row[x * 3] >= (Formatted_Color[0] - Shade_Variation) & row[x * 3] <= (Formatted_Color[0] + Shade_Variation)) //blue
if (row[(x * 3) + 1] >= (Formatted_Color[1] - Shade_Variation) & row[(x * 3) + 1] <= (Formatted_Color[1] + Shade_Variation)) //green
if (row[(x * 3) + 2] >= (Formatted_Color[2] - Shade_Variation) & row[(x * 3) + 2] <= (Formatted_Color[2] + Shade_Variation)) //red
points.Add(new Point(x + rect.X, y + rect.Y));
// returns the current radar
}
}
}
RegionIn_Bitmap.Dispose();
byte[] bytes = new byte[RegionIn_BitmapData.Stride * RegionIn_BitmapData.Height];
Marshal.Copy(RegionIn_BitmapData.Scan0, bytes, 0, bytes.Length);
string hexStr = BitConverter.ToString(bytes);
for each (byte b in bytes)
{
hexStr += b.ToString("X2");
writer.Write(hexStr)
}
}
}
}
It seems like the StreamWriter loop iterates through the regions in the BitmapData and adds each stream to "crash_log.txt" in the event of a crash.
In the event of a game crash, the cheat quickly dumps the bitmap data to the crash_log.txt, this seems like a debugging function used by the Author to locate the exception causing the crash.
RegionIn_Bitmap.UnlockBits(RegionIn_BitmapData);
This function saves the last known bits in the RegionIn_BitmapData
And, the crash_logs.txt file contains a very interesting hex string near the bottom of the logfile.
RegionIn_Bitmap.X2.0.0.0 0x0000000000000000
BMP Begin
<a very long hex string>
BMP 2.0.0
The solution is converting this very long hex string to either a .png or a .bmp, the flag is located in the image produced.
solve.py
import binascii
from io import BytesIO
from PIL import Image
with open('dump.hex', 'r') as f:
hex_data = f.read()
binary_data = binascii.unhexlify(hex_data)
img = Image.open(BytesIO(binary_data))
img.save('final.png')