-
Notifications
You must be signed in to change notification settings - Fork 1
/
suscheck.py
executable file
·123 lines (99 loc) · 3.34 KB
/
suscheck.py
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
# This script detects the identities of impostors in
# Among Us and outputs them for the user.
# To use it, simply leave the script running while you
# join games. At the start of each game, the script
# will notify you who the impostor(s) are.
#
# Please note that many assumptions and guesses were
# made while writing this. My conception of the packet
# structure may not be fully accurate. As a result,
# the script does not detect impostors 100% of the time.
# It's more like 90-95%. There is room for improvement.
#
# Requires scapy:
# python -m pip install scapy
#
# This program is Free Software, licensed under
# GPLv3. For more information, see LICENSE.txt.
import scapy.all
INFO_HEADER = b'p\x85\xc2\xce'
# check whether the specified packet is the Info Packet
# that we're interested in
def check_header(pkt):
if len(pkt) <= len(INFO_HEADER):
return False
for i in range(len(INFO_HEADER)):
if pkt[i] != INFO_HEADER[i]:
return False
return True
# parse data from each player from the info packet
# returns a list of tuples (name, data), or None
def parse_info(pkt):
plist = None
players = []
# scan for start of player list
for pidx in range(len(pkt) - 4):
if pkt[pidx] == 0x1e and pkt[pidx + 2] == 0 and pkt[pidx + 3] == 0:
plist = pkt[pidx + 1:]
break
pidx = pidx + 1
if plist is None:
return None
# parse name and data from each player until
# we have exhausted the list
while len(plist) > 0:
plist = plist[3:]
pname = plist[1:plist[0] + 1].decode("ascii")
plist = plist[plist[0] + 1:]
pdata = plist[:2 * plist[5] + 6]
players.append((pname, pdata))
plist = plist[2 * plist[5] + 6:]
return players
# takes a list of player tuples, and returns a list
# with all the non-impostor players removed
def get_impostors(players):
return [x for x in players if x[1][4] == 0x02]
# returns a comma-separated string of player names based
# on a player tuple list
def players_string(players):
result = ""
for i in range(len(players)):
result = result + players[i][0]
if i < len(players) - 1:
result = result + ", "
return result
# main packet handling function
def process_pkt(pkt):
pkt = bytes(pkt)
players = None
if check_header(pkt):
try:
players = parse_info(pkt)
except:
# fail silently - a lot of packets will
# not be what we want
return
if players is None:
return
impostors = get_impostors(players)
if len(impostors) == 0:
return
elif len(impostors) == 1:
print("IMPOSTOR: ", end='')
else:
print("IMPOSTORS: ", end='')
print(players_string(impostors))
if __name__ == "__main__":
print("\n ==============================")
print(" == ==")
print(" == I AM THE GREAT KORNHOLIO ==")
print(" == ARE U THREATENING ME?? ==")
print(" == ==")
print(" == SusCheck ==")
print(" == Impostor Detector ==")
print(" == ==")
print(" ==============================\n")
print("Scanning for impostors...")
print("(CTRL+C to exit)")
scapy.all.sniff(filter="udp", prn=process_pkt)