网页雷达:如何将web和逆向结合了

网页雷达


写在前面


本项目完成于2025年9月,但是由于某些原因没有写成博客发不出来。现在风头过去了可以发了,所以把这篇文章发出来,也是记录一下学习。今后可能会回归web安全相关内容,暂时不搞逆向了。

项目


这里用一个前几年比较火的游戏————荒野行动 作为例子

效果图:

cf4b5fc8db448713b1ce2573577cc9e5.png

目录


|—–GameMaps

|–ConnectController.py

|–hy_web.e

|–XLC.html

|–XLC.png

hy_web.e


本地端:hy_web.e

本地端用e语言,主要是有现成的驱动,本人也是很早学过的,正好能熟练运用

这里主要是两个额外线程:读取数据线程和矩阵线程

数据读取模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
.版本 2

PlayerControler = 读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (模块地址 + #PlayerAddr) + 88) + 192) + 984) + 96) + 56) + 984) + 96)
' 调试输出 (“playcontroler”, PlayerControler, 进制_十到十六 (PlayerControler))

.判断循环首 (真)
count = 读整数型 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (模块地址 + #PlayerAddr) + 88) + 192) + 984) + 96) + 56) + 984) + 104)
' 调试输出 (“count”, count, PlayerControler)

.计次循环首 (count, i)
playerOffset = 读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (读长整数 (PlayerControler + 0 + (i - 1) × 8) + 224) + 48) + 64) + 64) + 8) + 208)
' 调试输出 (“player”, playerOffset, 进制_十到十六 (playerOffset))

playerPos = GetPos (playerOffset)
' 调试输出 (“playerpos”, playerPos.x, playerPos.y, playerPos.z)



加入成员 (临时数组, playerOffset)

.计次循环尾 ()

全_对象数组 = 临时数组
' 调试输出 (全_对象数组)

清除数组 (临时数组)
延时 (1000)

.判断循环尾 ()

矩阵读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
.版本 2
.版本 2

.子程序 Matrix
.局部变量 head, 长整数型
.局部变量 矩阵集合, 字节集
.局部变量 临时矩阵, 小数型, , "4,4"
.局部变量 Martixaddr, 长整数型

.判断循环首 (真)
Martixaddr = 进制_十六到十 (“0C7EF728”)
矩阵集合 = 读字节集 (Martixaddr, 64)

临时矩阵 [1] [1] = 取字节集数据 (矩阵集合, #小数型, 1)
临时矩阵 [1] [2] = 取字节集数据 (矩阵集合, #小数型, 5)
临时矩阵 [1] [3] = 取字节集数据 (矩阵集合, #小数型, 9)
临时矩阵 [1] [4] = 取字节集数据 (矩阵集合, #小数型, 13)

临时矩阵 [2] [1] = 取字节集数据 (矩阵集合, #小数型, 17)
临时矩阵 [2] [2] = 取字节集数据 (矩阵集合, #小数型, 21)
临时矩阵 [2] [3] = 取字节集数据 (矩阵集合, #小数型, 25)
临时矩阵 [2] [4] = 取字节集数据 (矩阵集合, #小数型, 29)

临时矩阵 [3] [1] = 取字节集数据 (矩阵集合, #小数型, 33)
临时矩阵 [3] [2] = 取字节集数据 (矩阵集合, #小数型, 37)
临时矩阵 [3] [3] = 取字节集数据 (矩阵集合, #小数型, 41)
临时矩阵 [3] [4] = 取字节集数据 (矩阵集合, #小数型, 45)

临时矩阵 [4] [1] = 取字节集数据 (矩阵集合, #小数型, 49)
临时矩阵 [4] [2] = 取字节集数据 (矩阵集合, #小数型, 53)
临时矩阵 [4] [3] = 取字节集数据 (矩阵集合, #小数型, 57)
临时矩阵 [4] [4] = 取字节集数据 (矩阵集合, #小数型, 61)


矩阵数组 = 临时矩阵

延时 (1)

' 调试输出 (“矩阵”, 临时矩阵)

.判断循环尾 ()

主线程负责转换成json并分发数据,这里采用tcp连接。按照需求应该用udp更好,不过这里对udp不太支持,所以只能略微牺牲一下速度了。

主线程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.版本 2

.子程序 Drew
.局部变量 Aaary, 长整数型, , "0"
.局部变量 count, 整数型
.局部变量 i, 整数型
.局部变量 Object, 长整数型
.局部变量 pos, Vector3D
.局部变量 rect, Vector4D
.局部变量 数据, 类_json

' 绘制文本 (50, 50, “花蕊绘制-开源版”, #绿色, 30)
移动窗口 (句柄, 窗口矩形.左边, 窗口矩形.顶边, 窗口矩形.宽度 - 窗口矩形.左边, 窗口矩形.高度 - 窗口矩形.顶边, 假)
取窗口矩形_ (窗口句柄, 窗口矩形)

屏幕X = (窗口矩形.宽度 - 窗口矩形.左边) ÷ 2
屏幕Y = (窗口矩形.高度 - 窗口矩形.顶边) ÷ 2



Aaary = 全_对象数组
count = 取数组成员数 (Aaary)
.计次循环首 (count, i)
Object = Aaary [i]
pos = GetPos (Object)
数据.清除 ()
数据.置属性数值 (“id”, Object)
数据.置属性数值 (“x”, pos.x)
数据.置属性数值 (“y”, pos.y)

客户1.发送数据 (数据.取数据文本 () + #换行符)

.计次循环尾 ()

COnnectController.py


服务端,比较简陋,用ssti搭建,用于接受json并且返回给前端。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import asyncio
import json
import websockets


web_clients = set()

# === 1. WebSocket 服务器,给前端用 ===
async def websocket_handler(websocket):
print("前端连接成功")
web_clients.add(websocket)
try:
async for _ in websocket:
pass
finally:
web_clients.remove(websocket)
print("前端断开连接")


async def handle_tcp(reader, writer):
addr = writer.get_extra_info('peername')
print(f"TCP客户端连接: {addr}")

buffer = ""
try:
while True:
data = await reader.read(1024)
if not data:
break

buffer += data.decode()


while "\n" in buffer:
msg, buffer = buffer.split("\n", 1)
msg = msg.strip()
if not msg:
continue

print(f"收到 TCP 消息: {msg}")

try:
player_data = json.loads(msg) # JSON 格式: {"id":"p1","x":100,"y":200}

if web_clients:
await asyncio.gather(*[
ws.send(json.dumps(player_data))
for ws in web_clients
])

except json.JSONDecodeError:
print("收到的不是有效 JSON:", msg)

except Exception as e:
print("TCP错误:", e)
finally:
print("TCP客户端断开:", addr)
writer.close()
await writer.wait_closed()

# === 3. 主入口 ===
async def main():

ws_server = await websockets.serve(websocket_handler, "0.0.0.0", 8765)

tcp_server = await asyncio.start_server(handle_tcp, "0.0.0.0", 9000)

print("✅ WebSocket 服务器运行在 ws://0.0.0.0:8765")
print("✅ TCP 服务器运行在 tcp://0.0.0.0:9000")

async with ws_server, tcp_server:
await asyncio.gather(ws_server.wait_closed(), tcp_server.serve_forever())

if __name__ == "__main__":
asyncio.run(main())


前端


前端这一块主要使用leaflet.js作为地图引擎。这个还真挺不错的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>游戏实时地图</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css"/>
<style>
#map {
height: 100vh;
width: 100vw;
}
.player-marker {
width: 12px;
height: 12px;
background: red;
border-radius: 50%;
border: 2px solid white;
}
</style>
</head>
<body>
<div id="map"></div>

<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>

const minX = -3989, maxX = -3563;
const minY = -21, maxY = 405;


const map = L.map('map', {
crs: L.CRS.Simple,
minZoom: -2,
maxZoom: 4,
zoomSnap: 0.1,
});


const imageUrl = 'XLC.png';
const imageBounds = [[minY, minX], [maxY, maxX]];
L.imageOverlay(imageUrl, imageBounds).addTo(map);
map.fitBounds(imageBounds);


const players = {};
function updatePlayer(id, x, y) {
if (players[id]) {
players[id].setLatLng([y, x]);
} else {
const marker = L.marker([y, x], {
icon: L.divIcon({ className: 'player-marker' })
}).addTo(map);
players[id] = marker;
}
}



const ws = new WebSocket("ws://localhost:8765");

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// 例如: { "id": "player1", "x": 123, "y": 456 }
updatePlayer(data.id, data.x, data.y);
};


</script>
</body>
</html>

最后呈现效果如图:

s877a-5dme5.gif

写在后面


Q:为什么不用绘制,而是写成网页雷达呢?

A:因为弥赛亚引擎是闭源引擎,目前找到的矩阵是尼玛3*4矩阵,市面上没有开源的转屏幕算法。我们这种散修师傅只能另寻出路,搞点简单的。

另外感谢网友车神,我和他一起研究的弥赛亚引擎,也是交上共同学习的好友了哈哈