Начинающий
- Статус
- Оффлайн
- Регистрация
- 13 Фев 2026
- Сообщения
- 201
- Реакции
- 5
Народ, кто сейчас ковыряет Arc Raiders, есть пара мыслей по поводу вашей проблемы с камерой. Сам вчера сидел, дампил структуры через ReClass и столкнулся с тем же мусором в логах.
Короче, по фактам: если у вас FOV адекватный, а позиция/ротация — полный рандом, значит, вы уперлись в UE4/UE5 CameraManager encryption или банальное смещение (alignment) структуры POV. В последних билдах движков разрабы стали часто кидать камеру не в открытый доступ, а в зашифрованные куски памяти, либо используют динамические офсеты, которые прыгают при каждом рендере.
Что по детектам: юзать SharpDX для оверлея в этой игре сейчас — это прямой путь к мануалбану, если не спрятали оверлей через Fuser или хотя бы не добавили рандомизацию отрисовки. OnPaint вызывается слишком часто и без задержек — античит такие "пульсирующие" окна палит на раз.
Братва, делитесь опытом: кто-то уже пробовал через DMA вытягивать вьюматрицу? Есть смысл переписывать под стрим на второй ПК или можно обойтись чистым экстерналом, если грамотно перехватить оффсеты?
Кидайте свои правки, если кто нашел актуальный адрес камеры в актуальном патче, а то у меня сейчас реверс встал на проверке целостности указателей.
Короче, по фактам: если у вас FOV адекватный, а позиция/ротация — полный рандом, значит, вы уперлись в UE4/UE5 CameraManager encryption или банальное смещение (alignment) структуры POV. В последних билдах движков разрабы стали часто кидать камеру не в открытый доступ, а в зашифрованные куски памяти, либо используют динамические офсеты, которые прыгают при каждом рендере.
- Проблема с оффсетами: Ваши 0x400/0x428 выглядят как стандарт, но в игре может быть кастомный MinimalViewInfo. Проверьте, не съехал ли структурный размер.
- Шифрование: Если данные выглядят как `1.25e-14` или вообще инты в стиле экспоненты, скорее всего, там накинута обфускация. Посмотрите в сторону DecryptPointerSIMD (у вас в коде есть задел), попробуйте прогнать через нее не только указатель, но и сами данные POV.
- LocalPlayer/Controller Sync: Иногда CameraManager берет данные из ViewTarget, который может быть не равен вашему `localPawn`. Попробуйте протрейсить GetCameraViewPoint, если есть возможность зацепиться отладчиком.
Код:
using SharpDX;
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox;
// Explizite Zuweisung für Enterprise-Stabilität:
using Color = System.Drawing.Color;
using Matrix = SharpDX.Matrix;
using Point = System.Drawing.Point;
using Timer = System.Windows.Forms.Timer;
using Vector2 = SharpDX.Vector2;
using Vector3 = SharpDX.Vector3;
namespace AmdHostService
{
public class Dx11Overlay : Form
{
// --- 1. Die Variablen (Deine Werkzeugkiste) ---
private readonly KernelIpc _ipc;
private readonly int _pid;
private readonly ulong _gameDataAddr; // Umbenannt für Klarheit
private bool _running = true;
private bool _showEsp = true; // Der Schalter für F9 (An/Aus)
private bool hasLogged = false;
private ulong _cachedActorList = 0;
private int _cachedActorCount = 0;
private long _lastCacheTime = 0;
private long _lastKeyCheckTime = 0; // Das hier hat gefehlt!
private string _lastLogMsg = "";
private bool hasLogged2 = false;
private ulong _cachedUWorld = 0;
private ulong _cachedPL = 0;
private long _lastPLTime = 0;
private long _lastUWorldTime = 0;
private ulong _cachedActors = 0;
private int _cachedCount = 0;
private ulong _lastLoggedUWorld = 0;
private System.Collections.Generic.Dictionary<ulong, string> _nameCache = new();
private bool _actorScanDone = false;
private bool _cameraScanDone = false;
// --- 2. Ressourcen Caching (Damit das Tool flüssig läuft) ---
private readonly Pen _espPen = new Pen(System.Drawing.Color.Red, 2);
private readonly Font _infoFont = new Font("Arial", 9, FontStyle.Bold);
private System.Windows.Forms.Timer? _renderTimer;
// --- 3. Windows-Schnittstellen (DllImports) ---
[DllImport("user32.dll")]
private static extern short GetAsyncKeyState(int vKey);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
const int GWL_EXSTYLE = -20;
const int WS_EX_LAYERED = 0x80000;
const int WS_EX_TRANSPARENT = 0x20;
const int WS_EX_NOACTIVATE = 0x08000000;
const uint LWA_ALPHA = 0x2;
// --- AB HIER FOLGT DEIN KONSTRUKTOR ---
public Dx11Overlay(KernelIpc ipc, int pid, ulong gameDataAddr)
{
_ipc = ipc;
_pid = pid;
_gameDataAddr = gameDataAddr;
this.FormBorderStyle = FormBorderStyle.None;
this.Text = "AmdSoftwareHost";
this.TopMost = true;
this.ShowInTaskbar = false;
this.DoubleBuffered = true;
this.StartPosition = FormStartPosition.Manual;
this.Width = Screen.PrimaryScreen!.Bounds.Width;
this.Height = Screen.PrimaryScreen!.Bounds.Height;
this.Location = new Point(0, 0);
this.BackColor = Color.Lime;
this.TransparencyKey = Color.Lime;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
SafeLog("OVERLAY GESTARTET");
int style = GetWindowLong(this.Handle, GWL_EXSTYLE);
style |= WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE;
SetWindowLong(this.Handle, GWL_EXSTYLE, style);
SetLayeredWindowAttributes(this.Handle, 0, 255, LWA_ALPHA);
System.Threading.Thread paintThread = new System.Threading.Thread(() =>
{
while (_running)
{
try
{
if (this.IsHandleCreated && !this.IsDisposed)
{
this.BeginInvoke((Action)(() => this.Invalidate()));
}
}
catch { }
System.Threading.Thread.Sleep(40);
}
});
paintThread.IsBackground = true;
paintThread.Priority = System.Threading.ThreadPriority.AboveNormal;
paintThread.Start();
SafeLog("Timer gestartet");
}
private long _lastUpdateTick = 0;
protected override void OnPaint(PaintEventArgs e)
{
SafeLog("OnPaint CALLED");
Graphics g = e.Graphics;
e.Graphics.Clear(Color.Lime);
g.FillRectangle(Brushes.Red, 200, 200, 40, 40);
if (!_showEsp || _ipc == null) return;
try
{
Vector3 camLoc = Vector3.Zero;
Vector3 camRot = Vector3.Zero;
float camFov = 0f;
ulong viewTarget = 0; // ✅ EINMAL global im Try
// === UWorld ===
ulong gworld_ptr = _ipc.Read<ulong>(_pid, _gameDataAddr + 0xDEEF8D8);
ulong uworld = _ipc.Read<ulong>(_pid, gworld_ptr);
if (uworld < 0x10000000000) return;
// === Level ===
ulong persistentLevel = _ipc.Read<ulong>(_pid, uworld + 0xF8);
if (persistentLevel < 0x10000000000) return;
ulong actorArray = _ipc.Read<ulong>(_pid, persistentLevel + 0x108);
int actorCount = _ipc.Read<int>(_pid, persistentLevel + 0x110);
if (actorArray < 0x10000000000 || actorCount <= 0 || actorCount > 10000)
return;
ulong localController = 0;
ulong localPawn = 0;
// === LOCAL CONTROLLER ===
for (int i = 0; i < actorCount; i++)
{
ulong actor = _ipc.Read<ulong>(_pid, actorArray + (ulong)(i * 8));
if (actor < 0x1000000) continue;
ulong controller = _ipc.Read<ulong>(_pid, actor + 0x3D0);
if (controller < 0x1000000) continue;
ulong ackPawn = _ipc.Read<ulong>(_pid, controller + 0x3D8);
if (ackPawn == actor)
{
localPawn = actor;
localController = controller;
SafeLog($"LOCAL FOUND: Pawn=0x{actor:X} Controller=0x{controller:X}");
break;
}
}
if (localController == 0)
{
SafeLog("NO LOCAL CONTROLLER");
return;
}
// === CAMERA MANAGER (LAUT FORUM POST) ===
ulong cameraManager = 0;
// Gehe durch alle Actors im Level
for (int i = 0; i < actorCount; i++)
{
ulong actor = _ipc.Read<ulong>(_pid, actorArray + (ulong)(i * 8));
if (actor < 0x1000000) continue;
// PCOwner zeigt auf deinen Controller
ulong owner = _ipc.Read<ulong>(_pid, actor + 0x3A8);
if (owner == localController)
{
cameraManager = actor;
SafeLog($"CAMERA MANAGER FOUND (via PCOwner): 0x{cameraManager:X}");
break;
}
}
if (cameraManager == 0)
{
SafeLog("NO CAMERA MANAGER FOUND IN ACTOR LIST");
return;
}
// === KAMERA DATEN LESEN ===
// POV-Struktur laut Dump: Location = 0x400, Rotation = 0x428, FOV = 0x450
camLoc = _ipc.Read<Vector3>(_pid, cameraManager + 0x400);
camRot = _ipc.Read<Vector3>(_pid, cameraManager + 0x428);
camFov = _ipc.Read<float>(_pid, cameraManager + 0x450);
if (!IsValidVec(camLoc) || !IsValidVec(camRot) || camFov < 10 || camFov > 170)
{
SafeLog("CAMERA DATA INVALID (verschlüsselt oder falsch gelesen)");
return;
}
SafeLog($"FOV: {camFov}");
SafeLog($"CamLoc: {camLoc.X} {camLoc.Y} {camLoc.Z}");
SafeLog($"CamRot: {camRot.X} {camRot.Y} {camRot.Z}");
if (cameraManager == 0)
{
SafeLog("NO CAMERA MANAGER FOUND");
return;
}
if (cameraManager == 0)
{
SafeLog("BAD CAMERA / VIEWTARGET");
return;
}
// === TEST CAMERA (JETZT RICHTIG) ===
bool camFound = false;
for (int offset = 0x0; offset < 0x1000; offset += 0x10)
{
try
{
Vector3 testLoc = _ipc.Read<Vector3>(_pid, cameraManager + (ulong)offset);
Vector3 testRot = _ipc.Read<Vector3>(_pid, cameraManager + (ulong)(offset + 0x10));
float testFov = _ipc.Read<float>(_pid, cameraManager + (ulong)(offset + 0x20));
if (IsValidVec(testLoc) && IsValidVec(testRot) && testFov > 60 && testFov < 120)
{
camLoc = testLoc;
camRot = testRot;
camFov = testFov;
SafeLog($"CAM FOUND @ 0x{offset:X}");
SafeLog($"FOV: {camFov}");
SafeLog($"CamLoc: {camLoc.X} {camLoc.Y} {camLoc.Z}");
SafeLog($"CamRot: {camRot.X} {camRot.Y} {camRot.Z}");
camFound = true;
break;
}
}
catch { }
}
if (!camFound)
{
SafeLog("NO VALID CAMERA DATA");
return;
}
if (!IsValidVec(camLoc))
{
SafeLog("CAMLOC INVALID");
return;
}
if (!IsValidVec(camRot))
{
SafeLog("CAMROT INVALID");
return;
}
if (camFov < 10 || camFov > 170)
{
SafeLog("BAD FOV");
return;
}
SafeLog($"FOV: {camFov}");
SafeLog($"CamLoc: {camLoc.X} {camLoc.Y} {camLoc.Z}");
SafeLog($"CamRot: {camRot.X} {camRot.Y} {camRot.Z}");
if (camFov < 10 || camFov > 170)
{
SafeLog("BAD FOV");
return;
}
// === MATRIX ===
Matrix viewMatrix = CreateMatrix(camLoc, camRot, camFov);
// === ACTORS ===
for (int i = 0; i < actorCount; i++)
{
ulong actor = _ipc.Read<ulong>(_pid, actorArray + (ulong)(i * 8));
if (actor < 0x1000000) continue;
if (actor == localPawn) continue;
ulong root = _ipc.Read<ulong>(_pid, actor + 0x190);
if (root < 0x1000000) continue;
// ComponentToWorld aus DEINEM Dump
ulong comp = root + 0x350;
// Translation aus FTransform (Position)
Vector3 pos = _ipc.Read<Vector3>(_pid, comp + 0x10);
if (!IsValidVec(pos))
continue;
SafeLog($"ACTOR POS: {pos.X} {pos.Y} {pos.Z}");
// === ACTOR SCAN (NUR EINMAL) ===
if (!_actorScanDone)
{
_actorScanDone = true;
SafeLog("=== ACTOR SCAN START ===");
for (int offset = 0x0; offset < 0x400; offset += 0x10)
{
try
{
Vector3 test = _ipc.Read<Vector3>(_pid, root + (ulong)offset);
if (IsValidVec(test))
{
SafeLog($"ACTOR OFFSET 0x{offset:X} -> {test.X} {test.Y} {test.Z}");
}
}
catch { }
}
SafeLog("=== ACTOR SCAN END ===");
}
SafeLog($"ACTOR POS: {pos.X} {pos.Y} {pos.Z}");
if (Math.Abs(pos.X) > 100000 || Math.Abs(pos.Y) > 100000)
continue;
Vector2 screen;
if (!WorldToScreen(pos, viewMatrix, this.Width, this.Height, out screen))
continue;
g.FillRectangle(Brushes.Red, screen.X, screen.Y, 6, 6);
}
}
catch (Exception ex)
{
SafeLog($"ERR: {ex.Message}");
}
}
private bool WorldToScreen(Vector3 world, Matrix m, int w, int h, out Vector2 s)
{
s = default;
float clipW = m.M14 * world.X + m.M24 * world.Y + m.M34 * world.Z + m.M44;
if (clipW < 0.1f) return false;
float invW = 1f / clipW;
float x = (m.M11 * world.X + m.M21 * world.Y + m.M31 * world.Z + m.M41) * invW;
float y = (m.M12 * world.X + m.M22 * world.Y + m.M32 * world.Z + m.M42) * invW;
s.X = (w / 2f) + (x * w / 2f);
s.Y = (h / 2f) - (y * h / 2f);
return true;
}
private bool IsValidVec(Vector3 v)
{
if (float.IsNaN(v.X) || float.IsNaN(v.Y) || float.IsNaN(v.Z))
return false;
if (Math.Abs(v.X) < 1 && Math.Abs(v.Y) < 1)
return false;
if (Math.Abs(v.X) > 1000000 || Math.Abs(v.Y) > 1000000)
return false;
return true;
}
public void RenderLoop() => Application.Run(this);
protected override void Dispose(bool disposing)
{
_running = false;
if (disposing)
{
_renderTimer?.Stop();
_renderTimer?.Dispose();
_espPen?.Dispose();
_infoFont?.Dispose();
}
base.Dispose(disposing);
}
private string _lastLoggedMessage = "";
private void SafeLog(string message)
{
if (message == _lastLoggedMessage) return;
_lastLoggedMessage = message;
try
{
string filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "debug_log.txt");
System.IO.File.AppendAllText(filePath, $"[{DateTime.Now:HH:mm:ss}] {message}{Environment.NewLine}");
}
catch (Exception ex) { Console.WriteLine($"Log-Fehler: {ex.Message}"); }
}
private Matrix CreateMatrix(Vector3 location, Vector3 rotation, float fov)
{
float pitch = rotation.X * (float)Math.PI / 180f;
float yaw = rotation.Y * (float)Math.PI / 180f;
float roll = rotation.Z * (float)Math.PI / 180f;
float sp = (float)Math.Sin(pitch);
float cp = (float)Math.Cos(pitch);
float sy = (float)Math.Sin(yaw);
float cy = (float)Math.Cos(yaw);
float sr = (float)Math.Sin(roll);
float cr = (float)Math.Cos(roll);
Vector3 axisX = new Vector3(cp * cy, cp * sy, sp);
Vector3 axisY = new Vector3(sr * sp * cy - cr * sy, sr * sp * sy + cr * cy, -sr * cp);
Vector3 axisZ = new Vector3(-(cr * sp * cy + sr * sy), cy * sr - cr * sp * sy, cr * cp);
Matrix m = new Matrix();
m.M11 = axisX.X; m.M12 = axisY.X; m.M13 = axisZ.X; m.M14 = 0;
m.M21 = axisX.Y; m.M22 = axisY.Y; m.M23 = axisZ.Y; m.M24 = 0;
m.M31 = axisX.Z; m.M32 = axisY.Z; m.M33 = axisZ.Z; m.M34 = 0;
m.M41 = -Vector3.Dot(axisX, location);
m.M42 = -Vector3.Dot(axisY, location);
m.M43 = -Vector3.Dot(axisZ, location);
m.M44 = 1;
float scale = 1.0f / (float)Math.Tan(fov * Math.PI / 360.0f);
m.M11 *= scale;
m.M22 *= scale;
m.M11 /= ((float)this.Width / this.Height);
return m;
}
private Vector128<byte> ReadVector128(ulong addr) => _ipc.Read<Vector128<byte>>(_pid, addr);
private ulong DecryptPointerSIMD(ulong encryptedValAddr)
{
try
{
var data = _ipc.Read<Vector128<byte>>(_pid, encryptedValAddr);
var xorKey = _ipc.Read<Vector128<byte>>(_pid, _gameDataAddr + 0xAAA18A0);
var shufKey = _ipc.Read<Vector128<byte>>(_pid, _gameDataAddr + 0xAAA18B0);
var xored = Sse2.Xor(data, xorKey);
var rotated = Sse2.Or(
Sse2.ShiftLeftLogical(xored.AsUInt64(), 0x22),
Sse2.ShiftRightLogical(xored.AsUInt64(), 0x1E)).AsByte();
var shuffled = Ssse3.Shuffle(rotated, shufKey);
return shuffled.AsUInt64().GetElement(0) ^ 0xAB8F9C79978619C2UL;
}
catch { return 0; }
}
private uint RotateLeft(uint value, int count) => (value << count) | (value >> (32 - count));
public string DecodePlayerName(byte[] buffer)
{
if (buffer == null || buffer.Length < 2 || buffer[0] == 0) return "";
uint prng = 0;
byte[] decoded = new byte[buffer.Length];
for (int i = 0; i < buffer.Length && buffer[i] != 0; i++)
{
uint v9 = prng + RotateLeft(16777619u * prng - 1584397723u, 27);
prng = 16777619u * v9;
int v10 = buffer[i] ^ (int)((-109 * (byte)v9) & 0x1F);
int v11 = 0;
if ((uint)(v10 - 80) < 0x2Fu) v11 = -47;
if ((uint)(v10 - 33) < 0x2Fu) v11 = 47;
int v14 = v10 + v11;
int v15 = (v14 - 53 >= 5) ? 0 : 5;
if (v14 - 48 < 5) v15 = 5;
int v16 = v14 + v15;
int v17 = 0;
if ((uint)(v16 - 110) < 0x0Du) v17 = -13;
if ((uint)(v16 - 97) < 0x0Du) v17 = 13;
int v18 = v16 + v17;
int v19 = 0;
if ((uint)(v18 - 78) < 0x0Du) v19 = -13;
if ((uint)(v18 - 65) < 0x0Du) v19 = 13;
int v22 = v18 + v19;
int v23 = 0;
if ((uint)(v22 - 80) < 0x2Fu) v23 = -47;
if ((uint)(v22 - 33) < 0x2Fu) v23 = 47;
decoded[i] = (byte)(v22 + v23);
}
return System.Text.Encoding.UTF8.GetString(decoded).TrimEnd('\0');
}
private ulong SafeGetUWorld()
{
try { return _ipc.Read<ulong>(_pid, _gameDataAddr + 0xDF80798); }
catch { return 0; }
}
}
}
Что по детектам: юзать SharpDX для оверлея в этой игре сейчас — это прямой путь к мануалбану, если не спрятали оверлей через Fuser или хотя бы не добавили рандомизацию отрисовки. OnPaint вызывается слишком часто и без задержек — античит такие "пульсирующие" окна палит на раз.
Братва, делитесь опытом: кто-то уже пробовал через DMA вытягивать вьюматрицу? Есть смысл переписывать под стрим на второй ПК или можно обойтись чистым экстерналом, если грамотно перехватить оффсеты?
Кидайте свои правки, если кто нашел актуальный адрес камеры в актуальном патче, а то у меня сейчас реверс встал на проверке целостности указателей.