Before everything i must emphasize, I created this project JUST FOR LEARNING PURPOSES, I never used this either to gain an unfair advantage or to profit from it! For this reason, the patterns won't be available. This is an old project and I was learning while developing, thus some code parts are a bit messy and is missing function documentation. And currently my focus is on other projects so that's something i am not gonna change anytime soon. This project is not supported anymore.
This is probably my biggest project yet, it took more then 2 years of my free time to reach the current state and much more of learning. But the knowledge that i gathered from this project was like no other, thanks to this i got to learn a lot mainly on the following areas:
- Reverse Engineering (Static analysis, dinamyc analysis)
- C++/Python/ASM programming (and Cython based modules)
- Software architecture
- Sockets communication
- Path-planning/path-finding algorithms
- REST API's
- Windows Operating System
- Process security and injection vulnerabilites
- OS Memory management
I created this just for the fun of learning, testing and understanding how a game works and can be exploited.
This project was made for Metin2, a MMORPG game from 2007. It creates a DLL that will hook multiple game functions and creates Python bindings that can be used to create complex automation scripts with the game memory. Since the game itself already has multiple bindings to Python, this library enhances it and allows to inject python scripts into the game memory.
With this library is possible to:
- Gather information from players or instances arround
- Find a path between points with state of the art algorithms (ANYA)
- Send attacks
- Move the main player
- Walk trough walls
- Make requests to HTTP server
- Create Websockets
- Pickup items with filters
- And much more...
All from a python script! An example of the usage of this library can be found here MetinPythonExtension.
In addition to this, it's possible to load patterns from a remote server and not include them inside the produced DLL, this was a usecase that i thought in the begging about update configuration remotely and uploading data from multiple clients into a central server, but it never took off completly.
- MetinPythonLib -> The main DLL
- PatternScanner -> Project that attempts to find the offsets needed by running a memory scan for specific patterns
- PacketSniffer -> Will hook specific network functions and dump every unencrypted communication to specific files.
The PacketSniffer was the last addition that i made and is the only project that doesn't make use of the common
folder, because of compiler related issues, just for sake of simplicity I just copy the files directly into the project.
- Module net_packet
-
Get(<string> filePath) returns <bytearray>
Similar to old app.Get, allows to extract any file encrypted. -
IsPositionBlocked(<int>x,<int>y) returns <boolean>
Allows to check if a map position is walkable(mobs don't count), true if is walkable or false if is not walkable.
Note: For better pathfinding, unblocked points that are close(1 unit) to a blocked point, are considered blocked too.
There is a bug with objects, since i can't figure out how to load the objects. -
FindPath(<int>x_start,<int>y_start,<int>x_end,<int>y_end) returns <tuple>(x,y)
Finds a path between 2 points.
The path will not contain the current point.
It's possible to edit the maps, by changing the files in Resources/Maps, 0 represents a blocked location and the 1 represents a walkable position. The module will generate a new map if the same does not exist. -
SendPacket(<int>size,<bytearray>buffer) return None
Sends a packet to the server bypassing any encryption set. -
SendAttackPacket(<int>vid,<byte>type)
Sends an attack packet to the server, the type is usually 0. -
SendStatePacket(<float>x,<float>y,<float>rotation_angle,<byte>eFunc, <byte>uArgs)
Sends a packet containing the current state of the main player, can be used to change position,rotation and attack state on server side only. The value eFunc can take the fallowing values: CHAR_STATE_ATTACK,CHAR_STATE_STOP,CHAR_STATE_WALK
If eFunc == CHAR_STATE_ATTACK then the uArgs value can take one of the following values: -
CHAR_STATE_ARG_HORSE_ATTACK1
- CHAR_STATE_ARG_HORSE_ATTACK2
- CHAR_STATE_ARG_HORSE_ATTACK3
- CHAR_STATE_ARG_COMBO_ATTACK1
- CHAR_STATE_ARG_COMBO_ATTACK2
- CHAR_STATE_ARG_COMBO_ATTACK3
- CHAR_STATE_ARG_COMBO_ATTACK4
otherwise the value can be NULL or CHAR_STATE_ARG_NONE
All this constants are defined in the module.
-
<dict>InstancesList
-> Is a dictionary containing all vids currently in sight as keys and values
Note: Use the keys as vids, the values may be changed on a new version -
IsDead(<int>vid) returns 1 or 0
Returns 1 if the instance with the vid provided is dead or doesn't exist and returns 0 otherwise -
SendStartFishing(<word>direction)
Sends a packet to the server to start fishing, the direction parameter is a word only understandable by the server(will be converted in the future). -
SendStopFishing(<byte>type,<float>timeLeft)
Sends a packet to the server to stop fishing, the type can be any of the following parameters:- SUCCESS_FISHING -> The mini game was solve successfully.
- UNSUCCESS_FISHING -> The mini game was not solve.
The timeLeft represents the time left to fish.
-
SendAddFlyTarget(<int>vid,<float>x,<float>y)
Sends a packet to send an arrow at an enemy. -
SendShoot(<byte>uSkill)
Sends an attack packet to the current selected enemy (should be used after SendAddFlyTarget).
uSkill can be:- COMBO_SKILL_ARCH -> Normal attack.
-
BlockFishingPackets()
Blocks client from sending fishing packets (this module will still be able to send) -
UnblockFishingPackets()
Unblocks client from sending fishing packets. -
DisableCollisions()
Disable client colisions with objects and the terrain (Wallhack). -
EnableCollisions()
Enable client colisions. -
RegisterNewShopCallback(<callable_function>callback)
Sets a callback function, that will be called whenever a new private shop is created arround.
That callback will be called with the shop vid as the first argument. -
RegisterDigMotionCallback(<callable_function>callback)
Sets a callback function, that will be called whenever a dig motion(mining packet) is called.
The callback function will be called with the following arguments (player_vid,ore_vid,count) -
<string>PATH
Path of the location where the library was injected -
GetCloseItemGround(<int>x,<int>y) returns a tupple (<int>vid,<int>x,<int>y)
Returns the closest pickable item in the ground relative to the position given.
The items will be fitler acording to the pickup filter (see below).
Also, it will ignore items owned by other player. -
SendPickupItem(<int>itemVID)
Sends a packet to pickup an item from the ground -
SetMoveSpeedMultiplier(<float> speed)
Set the character movement boosting movement speed. -
SendUseSkillPacket(<int> skillIndex, <int> vid)
Uses a skill by providing a skillIndex and a target vid without doing the animation. -
SendUseSkillPacketBySlot(<int> skillSlotIndex, <int> vid)
The same as SendUseSkillPacket but the first argument is a slot index instead of the skill index
And also sets the cooldown of the skill on the client. -
IsPathBlocked(<int>x_start,<int>y_start,<int>x_end,<int>y_end)
Returns false if none of the points is blocked in a straight line other, if any of the points is blocked returns true. -
BlockAttackPackets()
Blocks all attack packets sent from the client, the only attack packets allowed are the ones sent by this module. -
UnblockAttackPackets()
Unblocks all attack packets. -
SkipRenderer()
Instruct the client to skip the drawing process, this can save CPU. -
UnskipRenderer()
Instruct the client to start drawing again. -
SyncPlayerPosition(<list>victims)
This is part of an exploit that allows to teleport other players.
The argument victims is a list of lists, each row containing vid victim, x coordinates and y coordinates.
As far as analyzed, for this to work, a special state packet need to be sent with the following argumentsnet_packet.SendStatePacket(mx,my,0,3,17)
where mx and my are the mob coordinates. -
SetRecvChatCallback(<function>callbackFunction)
Sets a callback function that will be called with the following arguments:int vid,int type,int empire,string msg,string locale
.
This function will be called whenever the client recives a chat message or command from the server. vid is the vid that send the message or 0 if is a command message. type is the type of message and can take the following valuesCHAT_TYPE_TALKING,CHAT_TYPE_INFO,CHAT_TYPE_NOTICE,CHAT_TYPE_PARTY,CHAT_TYPE_GUILD,CHAT_TYPE_COMMAND,CHAT_TYPE_SHOUT,CHAT_TYPE_WHISPER
that can be found on the chat module. msg is the message content. empire is the empire of the player. locale is the region from the player that send the message or empty if was not a player.
-
Communication with the outside world. All functions are asynchronous.
-
GetRequest(<string> url,<callable_function>callback) returns <int>
Sends a async GET request to the specified url. The callback is called when the response arrives from the server, it will be called with 2 arguments, the ID of the request and a string message respectively. If the request is successful it returns an ID of the request otherwise returns -1. -
OpenWebsocket(<string> url,<callable_function>callback) returns <int>
Opens a websocket to the specified url. The callback is responsible for handling the receive messages. It will be called every time a message is received, with 2 arguments, the ID of the socket and a string containing the message respectively . If the request is schedule successfully it returns an ID of the socket otherwise returns -1. -
SendWebsocket(<int> id,<string>message) returns <int>
Sends a message to the socket with the specified id. If the message is schedule successfully it returns 1 otherwise returns 0. -
CloseWebsocket(<int> id) returns <int>
Closes a socket with the specified id. If the message is schedule successfully it returns 1 otherwise returns 0.
A filter o be applied when calling GetCloseItemGround, by default the filter is set to pick items not present in filter.
-
ItemGrndDelFilter(<int> index)
Deletes an item id from the filter. -
ItemGrndAddFilter(<int> index)
Adds an item id to the filter. -
ItemGrndOnFilter()
Changes the filter mode, to only return items in the filter. -
ItemGrndNotOnFilter()
Changes the filter mode, to ignore all items present in the filter. -
ItemGrndFilterClear()
Deletes every item in the filter. -
GetItemGrndID(<int> VID)
Return the ID of an item in the ground with the specified VID -
ItemGrndSelectRange(<float> range)
Set's the maximum range to pick items -
ItemGrndItemFirst()
Makes the function GetCloseItemGround return the closest item if there is no item returns the closest yang -
ItemGrndNoItemFirst()
Makes the function GetCloseItemGround return the closest item or yang closest -
ItemGrndInBlockedPath()
Ignore items items that are in a blocked path -
ItemGrndNotInBlockedPath()
Allow to return items that are in a blocked path -
SetRecvAddGrndItemCallback(<function>callbackFunction)
Sets a callback function that will be called with the following arguments:int vid, int itemIndex, long x, long y, string owner
.
This function will be called whenever the server sends a new ground item. -
SetRecvChangeOwnershipGrndItemCallback(<function>callbackFunction)
Sets a callback function that will be called with the following arguments:int vid, string owner
.
This function will be called whenever the server sends a change in a ground item ownership (every item that is dropped with an owner will also recive this packet after the append) If the owner argument is an empty string then the item doesn't have an owner. -
SetRecvDelGrndItemCallback(<function>callbackFunction)
Sets a callback function that will be called with the following arguments:int vid
.
This function will be called whenever the server sends the command to delete a current item on the ground (this includes, the items being out of range and the item disappearement) WARNING: If you are trying are creating a list with items on the ground it might be needed to manually clear all items on phase change (Not tested)
These simulates the functions that were removed in recent versions of the game.
-
GetPixelPosition(<int>vid) returns a tupple (x,y,z)
Returns the position of the player by vid -
MoveToDestPosition(<float> x,<float> y)
Moves to a destination. -
SetMoveSpeed(<float> speed)
Set the character movement speed. The client might change the speed again need to be called constantly for now. If speed bigger then 2.0, the client will disconnect.
By default every packet will be shown.
-
LaunchPacketFilter()
Launches a console to print the packets. -
ClosePacketFilter()
Closes the console from packet filter. -
StartPacketFilter()
Start filtering packets. -
StopPacketFilter()
Stop filtering packets. -
SkipInHeader(<int>packet header)
Skips a packet coming from the server. -
SkipOutHeader(<int>packet header)
Skips a packet going to the server. -
DoNotSkipInHeader(<int>packet header)
Removes a packet coming from the server from the skipped packets. -
DoNotSkipInHeader(<int>packet header)
Removes a packet going to the server from the skipped packets. -
ClearOutput()
Clear what's in the console. -
ClearInFilter()
Clear all headers from the filter coming from the server. -
ClearOutFilter()
Clear all headers from the filter going to the server. -
SetOutFilterMode(<int>mode)
Changes filter mode for outgoing packets, if set to 1, it will shows all packets that correspond to the filter, if set to 0 it will show all packets that are not within the filter. -
SetInFilterMode(<int>mode)
Changes filter mode for incoming packets, if set to 1, it will shows all packets that correspond to the filter, if set to 0 it will show all packets that are not within the filter
Python 2.7 (32 bits) needs to be installed in the system (C:/Python27) by default.
- Dependencies using vcpkg:
cpprestsdk ->
vcpkg install --recurse cpprestsdk[default-features,websockets]:x86-windows-static
curl ->vcpkg install curl[core,openssl]:x86-windows-static
jsoncpp ->vcpkg install jsoncpp:x86-windows-static
websocketpp ->vcpkg install websocketpp:x86-windows-static
boost ->vcpkg install boost:x86-windows-static
Also the project is using SimpleIni to parse the .ini configuration file and Date to format date.