Giter Site home page Giter Site logo

maplepacketpuller's Introduction

Maplestory Packet Puller

  • For a better experience using this, check out the SpiritIDAPlugin project!

Features:

  • Reads keywords from IDA-generated pseudocode, and formats them into a form that is friendly for server encodes
  • Options for varying the accuracy of packet structure pulls
  • Shows the structure of packets
  • Writes all packet structures to an identically named output file in MaplePacketPuller/IDA Maple Script/FuncOutput/
  • Ability to search for InHeader opcodes

Known Issues:

  • while() loops aren't properly handled, i.e. whether a decode is in the scope of one well
    • Possible circumvention: may be rectified if GET_ALL_DECODES = true
  • The constant GET_ALL_DECODES when set to True for increased accuracy, has major aesthetic drawbacks
  • This script assumes that you have named the disassembled function in IDA according to the function you want to pull packet structures from
  • This script does not display switch cases - can be added by user

Technical Stack

Target Tested
Python 3.8.5 3.6.12 & 3.8.6
IDA Pro 32-bit 7.0 7.0
Editor Atom Atom
CLI Interpretor cmd pwsh 7.0

Other variants for contributors to test:

  • Python 2.7
    • NOT COMPATIBLE: use of os.scandir() makes it non-backwards compatible with versions older than 3.6
  • Python 3.6
    • NOT COMPATIBLE: probably a result of how f-strings handle backslashes
    • Update: Fixed as of commit 10a9fd86c4da264ef6d1d73a6aca248343cf63f6
  • IDA 6.8
  • IDA 7.5
  • IDLE
  • PyCharm Community Edition 2020.1.1 (or later)
    • COMPATIBLE Tested as of commit dfef676d4897dbc8195120f6f803a8810420d319

How to use

INPUT: .txt file containing C-pseudocode from IDA disassembly

OUTPUT: .txt file containing packet structure & console output

  • NOTE: You will have to create a .txt file in the Functions directory with the copy-pasted pseudocode from IDA (examples in there)
    • MaplePacketPuller/IDA Maple Script/Functions
  1. Navigate to MaplePacketPuller/IDA Maple Script/src/main/python in CLI and run main.py

    • Alternatively use a Python IDE like PyCharm
  2. Input the type of Analysis you want to do

  3. Input the name of the file you want to analyze, i.e. the txt file you've just created

  4. Let the program analyze it.

  5. Now packet structure should be yours! :octocat:

    • see MaplePacketPuller/IDA Maple Script/FuncOutput/

The console output should look a little something like this:

OnSetField InHeader

maplepacketpuller's People

Contributors

bratah123 avatar kookiiestudios avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

maplepacketpuller's Issues

DRY Violation

Utility.py
image

These 2 functions are now exactly the same except for the fact that one (additionally) prints.
Since check_keyword_and_return(keyword) returns an empty string when false, we can make use of Python's duck/dynamic typing to do this:

elif Util.check_keyword_and_return(line):
    packet_struct += Util.check_keyword_and_return(line) + "\n"

Instead of this:
Analysis.py Line 78-79

elif Util.check_keyword_and_print(line):
    packet_struct += Util.check_keyword_and_return(line) + "\n"

Also, both functions have an obsolete condition.
They both check for if key in keyword.lower():, and then check for the the same condition again just 2 lines later:
elif key not in keyword.lower() and...
Suggestion: Consider removing and/or merging.
Merging:

def check_keyword_and_return(keyword):
    for key in KEYWORDS:
        if key in keyword.lower():
            if key != "if" and key != "else":
                Util.print_dbg(f"{KEYWORDS_PRINT[KEYWORDS.index(key)]}")
                return KEYWORDS_PRINT[KEYWORDS.index(key)]
        elif "decode" in keyword.lower() and GET_ALL_DECODES:
            Util.print_dbg(keyword)
            return keyword  # just in case our keywords array doesn't already have that Decode saved
    return ""

Consider Removing Global Constant

DirectoryConstants.py
image

While not marked as global, the variables PRINT and GET_ALL_DECODES effectively function as global variables.
This is compounded by the fact that they are not actually directory constants.

PRINT is fine for now, since it is a manually-set variable.
Perhaps we could consider removing GET_ALL_DECODES, and passing it as a boolean variable into the method that currently use it, to avoid having to handle its state (notably for any possible future expansion of functionality).
E.g.

def check_keyword_and_return(keyword, get_all_debug):
    ...

Class PacketAnalysis(Analyzer):
    ...
    def analyze_packet_structure(self), get_all_debug):
        ...
        if KEYWORDS[5] in line:
            if_or_else += "if " + Util.check_keyword_and_return(line, get_all_debug) + ":"
        ...
    def run(self, get_all_debug):
    ...

Consider Use of Top-level Functions

Python supports top-level functions, and does not require functions to be encapsulated within classes (unlike Java or C#).

Utility.py
image
An example is the Util class from Utility.py.
This is a class with only static methods and no class attributes and/or methods - and no instance methods either.
In this case, it would be safe to refactor these methods out into top level statements.

Improve Matching Algorithm

Not sure if I'm interpreting the code correctly, but the function is_decode_func(func_name) appears to check every element of a list of known decode functions against the provided line of pseudocode (i.e. func_name), in order to determine if that line contains a decode function.
This is quite an expensive operation, since you have to check every known decode function name AND other unrelated elements (.e. if, else, do, while, etc.).

Suggestion: generalise the search pattern into searching for signatures. Based on what little literature I can get, all known decode functions seem to (unsurprisingly) have the word "decode" in them. Hence, consider the following implementation instead:

def is_decode_func(func_name):
    if "decode" in func_name.lower():
        return True
    else:
        return False

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.