마비노기

마비노기 패킷 관찰

JunOnJuly 2024. 8. 21. 18:09
728x90

# 해당 글은 단순한 흥미를 위한 실험과 결과로 이루어진 글이며 정책에 위반될 시 수정 혹은 삭제하겠습니다.

마비노기는 어떤 방식으로 돌아갈까?


라는 생각을 가끔 하곤 합니다. 물론 마비노기 뿐 아닌 다른 게임도 마찬가지지만.

그래서 검색을 하던 중 싴갤러스 라는 페이지의 동작 방식을 흥미롭게 보게 되었습니다.

https://lute.fantazm.net/

 

마비노기 싴갤러스 류트

싴갤러스에서 마비노기 플레이에 있어 도움되는 정보와 함께 해보세요

lute.fantazm.net

아마 패킷 탐지용 캐릭터를 올려두고 패킷을 관찰할 것이라는 추측이 가득했는데, 몹시 흥미로워서 나도 한번 패킷을 관찰해보자 라고 생각하게 되었습니다.

우선 파이썬에서 사용할 수 있는  패킷 조작 프로그램인 scapy 를 설치해야 합니다. 물론 패킷 조작 프로그램이지만 관찰 기능만 사용할 것이므로 안심하셔도 괜찮습니다.

그리고 저는 jupyter notebook 을 사용했습니다.

!pip install scapy

주피터에서 ! 를 명령어 앞에 사용하면 셀 환경에서 사용하라는 말이 되므로 우리는 scapy 를 설치했습니다.

from scapy.all import *

import binascii

scapy 를 사용하기위해 import 해주고, 16진수 데이터를 텍스트로 변환해주기 위해 binascii 를 import 해줍니다.

# 마비노기 패킷 전송 아이피를 찾기 위한 함수
def find_ip(text_data, filter_list, src):
	# 패킷을 텍스트로 변환한 문장 중 특정 문장이 포함되면 아이피 특정
    if '<ALL_CHANNELS>' in text_data:
        filter_list.append('host')
        filter_list.append(src)


# 패킷을 분석해 텍스트로 변환하는 함수
def showPacket(packet):
	# 패킷 중 raw 데이터
    raw_data = raw(packet)
    # raw 데이터를 16 진수로 변환
    hex_data = raw_data.hex()
    
    # 패킷의 IP
    if (packet.getlayer(IP)):
        src = packet.getlayer(IP).src
    else: src = ''
    
    # 저장 할 텍스트 데이터
    text_data = ''
    
    # 16 진수 데이터를 텍스트로 치환
    for idx in range(0, len(hex_data), 2):
    	# 숫자나 알파벳이나 기호면 1 바이트
        try:
            text_data += binascii.unhexlify(hex_data[idx:idx+2]).decode('utf-8')
        # 아니면
        except UnicodeDecodeError:
        	# 한글은 3 바이트니까 확인
            try:
                text_data += binascii.unhexlify(hex_data[idx:idx+6]).decode('utf-8')
            # 아니면 뭔지 모름
            except UnicodeDecodeError:
                continue
    
    # 아직 ip 가 특정되지 않았다면 ip 찾기
    if len(filter_list) == 1:
        find_ip(text_data, filter_list, src)
    
    # 전체 메시지만 특정해서 출력 및 저장
    if '<ALL_CHANNELS>' in text_data:
    	# 앞 뒤에 쓸모없는 데이터는 자르기
        text_data = '<ALL_CHANNELS>' + ' ' + text_data.split('<ALL_CHANNELS>')[1][4:]
        text_data = text_data[:-11]
        print(text_data)
        with open('log.txt', 'a', encoding='utf-8') as f:
            f.write(text_data + "\n")
        
   
# 실행 함수
def main(filter_list):
    sniff(filter=' '.join(filter_list), prn=showPacket, count=0)

함수의 정의부 입니다.

1. 이더넷에 연결된 패킷을 탐색
2. 탐색된 패킷 중 마비노기 패킷의 ip 를 탐지
3. 마비노기 패킷의 ip 가 특정되었다면 해당 ip 를 필터로 탐색
4. 데이터를 정제 / 출력 및 저장

 

의 순서로 진행됩니다.

filter_list = ['tcp']
main(filter_list)

필터 리스트를 정의하고 함수를 실행시키면

와 같이 시스템 전체 메시지를 읽어올 수 있게 되었습니다.


한계


한계라고 한다면 패킷을 읽어오는 방식이라 모니터링 캐릭터를 항상 올려놔야 한다는 점이 있습니다. 또 다른 경매장이나 여타 정보를 읽어올 수 있는지는 좀 더 연구해봐야겠습니다. 또 이를 이용해 상용될 수 있는 서비스는 모두 싴갤러스에서 진행중이니 마비노기 api 가 나오기만을 기다려봐야겠습니다.

728x90