| 04-25-2008, 06:03 AM | #1 |
I've been looking into the packets sent during the game, and seeing what kind of things I can get away with if I inject custom ones. For example, there is a packet to fire triggers with a chat event. The packet is needed because other private chat couldn't trigger events for all players. An obvious side-effect of such a packet is that any map with a chat event with substring "" allows people to listen to private chat. But I don't want to listen in on private chat. I want to fire any trigger with a chat event at will (when I'm host). For example, this is useful if a host bot wants to set the game mode in DOTA. Here is an example packet: Code:
F7 0C 1B 00 FA 00 DB 08 02 10 00 60 26 03 00 00 26 03 00 00 2D 74 65 73 74 31 00
F7 - Game packet header
0C - Packet ID
1B 00 - Total size (27)
FA 00 - Tick time (250 milliseconds)
DB 08 - CRC of following data
02 - Player index (not equivalent to player 2, partially based on join order)
10 00 - Size of following chunk (16)
60 - Unknown constant (probably means chat trigger event)
26 03 00 00 - Event handle address
26 03 00 00 - Event handle address again
2D 74 65 73 74 31 00 - Chat string ("-test1")This will usually fire the event at 26 03 00 00. But if the player index doesn't match the event's player's index or the player index is the local player's index then it won't fire. I want to get around this (specifically the local player thing). Any suggestions? As a side note, sending the 'chat' packet (not this one) will cause the player to speak even if it's the local player. The potential abuse of that is... wow. Send instructions to the other team, seemingly in private chat from their own team member. |
| 05-19-2008, 01:02 AM | #2 |
Here's a lot more game lobby format... Code:
Private Const GAME_PACKET_PREFIX As Integer = &HF7
Private Enum GamePacket
'''<summary>
''' Keepalive packet. Players will respond with PONG with equivalent data.
''' Players will eventually disconnect if you don't send these periodically.
'''</summary>
'''<data>
''' 0 DWORD ping data
'''</data>
PING = &H1
'''<summary>
''' Greets players with information about the game state and their unique id.
''' This should be the first packet sent after KNOCK is received, or the player might disconnect.
'''</summary>
'''<data>
''' 0 [optional] game state data (see GAME_STATE)
''' 1 BYTE player index
''' 2 ADDRESS external
'''</data>
GREET = &H4
'''<summary>
''' Informs players of the existence of a player.
''' A name with more than 15 characters will cause players to disconnect.
''' Players will attempt to connect to the introduced player on the given address.
'''</summary>
'''<data>
''' 0 DWORD connection key
''' 1 BYTE index
''' 2 STRING name (max size 16, including terminator)
''' 3 WORD unkown(0x01)
''' 4 ADDRESS listen external (all 0x00 for host)
''' 5 ADDRESS listen internal (all 0x00 for host)
'''</data>
OTHER_PLAYER_JOINED = &H6
'''<summary>
''' Informs that a player disconnected from the game.
''' *unsure* Saying a non-existant players left will cause players to disconnect
'''</summary>
'''<data>
''' 0 BYTE player index
''' 1 DWORD unknown(07 00 00 00)
'''</data>
OTHER_PLAYER_LEFT = &H7
'''<summary>
''' Tells this player that another player is ready to start.
''' Players keep track of who is and isn't done loading, and start the game as soon as everyone is ready.
'''</summary>
'''<data>
''' 0 BYTE player index
'''</data>
OTHER_PLAYER_READY = &H8
'''<summary>
''' Sends the game state (who is in what slot, etc)
'''</summary>
'''<data>
''' 0 WORD size (not including this word)
''' 1 BYTE number of slots = N
''' 2 N * slot states
''' 2.0 BYTE player index (starts at 1) (default to 0 if not player)
''' 2.1 BYTE download percent (0 to 99 => "0" to "99", 100 => "", 255 => "?", 254 => "|CF", 101 to 253 unknown) (default to 255 if not player)
''' 2.2 BYTE state (0 = open, 1 = closed, 2 = occupied)
''' 2.3 BYTE isComputer (0 = false, 1 = true)
''' 2.4 BYTE team index (starts at 0)
''' 2.5 BYTE color (0, ..., 11) = (red, blue, teal, purple, yellow, orange, green, pink, grey, light blue, dark green, brown)
''' 2.6 BYTE race [flags] (Human = 1, Orc = 2, NightElf = 4, Undead = 8, Random = 32, Unlocked = 64) (unlocked allows modification, not sure what combinations do)
''' 2.7 BYTE difficulty (easy = 0, normal = 1, insane = 2) (default to normal if not computer)
''' 2.8 BYTE handicap (50,60,70,80,90,100)
''' 3 DWORD GetTickCount
''' 4 BYTE layout (0 = melee, 3 = custom with forces)
''' 5 BYTE number of slots (again)
'''</data>
GAME_STATE = &H9
'''<summary>
''' Tells the player to show the 5 second countdown.
''' The countdown is not directly linked to launching, it only shows 543210 and disables the cancel button.
''' Sending this packet more than once will cause the player to disconnect.
'''</summary>
'''<data>
''' (no data)
'''</data>
START_COUNTDOWN = &HA
'''<summary>
''' Tells the player to start loading the map.
''' Sending this packet before the countdown packet will make players instantly start loading the game.
'''</summary>
'''<data>
''' (no data)
'''</data>
START_LOADING = &HB
'''<summary>
''' Advances game time
''' Includes actions to perform at the current game time
'''</summary>
'''<data>
''' WORD game time delta
''' ... unsure ..., lots of different sub-packets
'''</data>
TICK = &HC 'more of a general game packet
'''<summary>
''' Sends a text message.
''' The byte list specifies the sender and receivers.
''' You can fake the receiver and make it appear that other people are talking.
'''</summary>
'''<data>
''' 0 LIST players
''' 1 STRING message
'''</data>
TEXT = &HF
'''<summary>
''' Tells this player who the new host should be.
'''</summary>
'''<data>
''' 0 BYTE player index
'''</data>
SET_HOST = &H14
P2P_UNKNOWN0_____ = &H15 'I am your new host, here is some data
P2P_UNKNOWN1_____ = &H16 'Here is the address of a player
CONFIRM_HOST = &H17
P2P_UNKNOWN2_____ = &H19 'It is good that you agree I am your new host
'''<summary>
''' This is the first packet sent by connecting players.
''' If this isn't the first packet, the server should kill the connection.
'''</summary>
'''<data>
''' 0 BYTE unknown(0b? 01?)
''' 1 DWORD unknown(0?)
''' 2 DWORD unknown(0?)
''' 3 WORD listen port
''' 4 DWORD player connection key
''' 5 STRING name
''' 6 WORD unknown(0x01)
''' 7 ADDRESS internal
'''</data>
KNOCK = &H1E
'''<summary>
''' Sent by players when they hit the cancel button, before they disconnect.
''' If this packet is not sent, then the player was forcefully disconnected (they were booted, net died, bot made a mistake, etc)
'''</summary>
'''<data>
''' 0 DWORD unknown(07 00 00 00)
'''</data>
LEAVING = &H21
'''<summary>
''' Sent when a player has finished loading and is ready to start playing.
'''</summary>
'''<data>
''' (no data)
'''</data>
READY = &H23
PLAY_PACKET_GUEST = &H27
'''<summary>
''' Specifies requested actions from players
'''</summary>
'''<data>
''' (Type 1: Action)
''' 1.0 BYTE unknown(0x01)
''' 1.1 BYTE action flag(0xFF)
''' 1.2 BYTE value type (0x11 = team, 0x12 = color, 0x13 = race, 0x14 = handicap)
''' 1.3 BYTE new value
''' (Type 2: Lobby Chat)
''' 2.0 SIZEDLIST receiving player indexes
''' 2.1 BYTE sending player index
''' 2.2 BYTE lobby flag (0x10) 0x20 = in game with slightly different format)
''' 2.3 STRING message
''' (Type 3: Game Chat) *won't fire triggers
''' 3.0 SIZEDLIST receiving player indexes
''' 3.1 BYTE sending player index
''' 3.2 BYTE game flag 0x20
''' 3.3 ...unsure...
''' 3.4 STRING message
'''</data>
CLIENT_COMMAND = &H28
P2P_UNKNOWN3_____ = &H2B 'I agree you are my new host, I bow to you
'''<summary>
''' *unsure*
''' Sometimes sent by new host in response to SET_HOST in order to confirm the switch
'''</summary>
'''<data>
''' (no data)
'''</data>
ACCEPT_HOST = &H2C
P2P_CHAT = &H34
P2P_PING = &H35
P2P_PONG = &H36
P2P_KNOCK = &H37 'hey guy, the connection works! (disconnect if other guy hasn't connected to you yet) (other info too?)
'''<summary>
''' Sent by players when the set of players they are connected to changes.
''' Connected players talk to each other, and so don't require the host to ferry some types of data.
''' For example, chat text is sent between players. If you ferry chat text for connected players they will see messages twice.
'''</summary>
'''<data>
''' 0 BITS[16] nth bit means connected to player n
'''</data>
PLAYERS_CONNECTED = &H3B
'''<summary>
''' Tells the player information about the map file, so they can find it if they have it.
'''</summary>
'''<data>
''' 0 WORD unknown(1)
''' 1 STRING relative map path
''' 2 DWORD map file size
''' 3 DWORD map CRC32
''' 4 DWORD map hex key
'''</data>
MAP_INFO = &H3D
'''<summary>
''' *unsure*
''' Tells a player who to dl from
'''</summary>
'''<data>
''' 0 DWORD unknown(0x01)
''' 1 BYTE sending player index
'''</data>
DL_START = &H3F
P2P_UNKNOWN4_____ = &H38 'who knows, new host number?
P2P_UNKNOWN5_____ = &H39 'what lovely data, the old host disconnected from me as well, what an ass
'''<summary>
''' *unsure*
''' Indicates how much of the map file this player has
''' The host should initiate DLs for players that have 0 map
'''</summary>
'''<data>
''' 0 DWORD unknown(0x01)
''' 1 BYTE dl state (0x01 = no dl, 0x03 = dling)
''' 2 DWORD downloaded file size
'''</data>
DL_TOTAL_RECEIVED = &H42
'''<summary>
''' Sends a chunk of the map file to the player
'''</summary>
'''<data>
''' 0 BYTE receiving player index
''' 1 BYTE sending player index
''' 2 DWORD unknown(0x01)
''' 3 DWORD file position
''' 4 DWORD crc32 of data
''' 5 DWORD data
'''</data>
DL_MAP_CHUNK = &H43
DL_RECEIVED_CHUNK = &H44
'''<summary>
''' Response to PING
''' Sent as soon as PING is received, making it a latency measure
'''</summary>
'''<data>
''' 0 DWORD ping data
'''</data>
PONG = &H46
End Enum |
| 06-01-2008, 03:39 PM | #3 |
Nice work, a few questions; How would you make a program send a packet, and how can u monitor them? Are these numbers n watnot in hex? Ive seen a host bot that can allow you to 'shuffle' all the players, this would be acheived using the packets right? (would be extremely useful to allow u to 'swap' with sum1 else) and, ive only heard parts of the packets refered to as 'header' and 'payload', does it mean the same thing as 'summary' and 'data' or is this a different type of packet? If i knew how to send packets i think i could make a script to allow you to send messages by pressing number keys to change (or ALT+number, or watever). Could be quite useful, although i hav no idea about firewalls and bliz hack detection and all that. very cool man, i wanna try use this some how =) |
| 06-02-2008, 06:59 PM | #4 | |
Quote:
There are ways to inject packets into a connection, but I work with a completely independent bot. You monitor them using a program like wireshark. Yes, the numbers are in hex. That bot most likely worked in memory, since clients can't give the host a 'swap' command. The meaning of header and payload vary depending on the context. One protocol's payload can easily contain another protocol's header. |
| 06-09-2008, 04:48 PM | #5 |
This code will "Say" a message in the game and/or lobby, it's crude to use SendKeys buy this will at least work without any packet injection.. C# Code:
public bool SayToSelf(string txt)
{
Process[] pids = Process.GetProcessesByName("war3");
int proc;
int hToken = 0;
LUID sedebugnameValue = new LUID();
TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();
OpenProcessToken(Process.GetCurrentProcess().Handle.ToInt32(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken);
LookupPrivilegeValue(null, SE_DEBUG_NAME, ref sedebugnameValue);
tkp.PrivilegeCount = 1;
tkp.TheLuid = sedebugnameValue;
tkp.Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, 0, ref tkp, Marshal.SizeOf(tkp), 0,0);
CloseHandle(hToken);
int byteswritten = 0;
Int32 ptr1;
Int32 ptr2;
Int32 ptr3;
Int32 ptr4;
if (pids.Length > 0)
{
proc = OpenProcess(PROCESS_ALL_ACCESS, 0, pids[0].Id);
ReadProcessMemory(proc, 0x00400000 + 0x00054320, out ptr1, 4, 0);
ptr1 += +0x34;
ReadProcessMemory(proc, ptr1, out ptr2, 4, 0);
ptr2 += 0x2EC;
ReadProcessMemory(proc, ptr2, out ptr3, 4, 0);
ptr3 += 0x1E4;
ReadProcessMemory(proc, ptr3, out ptr4, 4, 0);
WriteProcessMemory(proc, ptr4, txt + '\0', txt.Length + 1, ref byteswritten);
SendKeys.SendWait("{ENTER}");
}
if (byteswritten == 0 || pids.Length == 0)
return false;
return true;
} |
