Jump to content

PeterLudolf

Members
  • Posts

    2
  • Joined

  • Last visited

Posts posted by PeterLudolf

  1. I wrote a little dll to dump all packet information.

    Spoiler
    
    #include <Windows.h>
    #include <iostream>
    #include <fstream>
    #include <iomanip>
    
    #include <stdio.h>  /* defines FILENAME_MAX */
    #include <direct.h>
    
    #define PUSH_B 0x6A
    #define PUSH 0x68
    #define CALL 0xE8
    #define RETN 0xC3
      
      namespace Memory {
    	bool bDataCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) {
    		for(;*szMask;++szMask,++pData,++bMask)
    			if(*szMask=='x' && *pData!=*bMask ) 
    				return false;
    		return (*szMask) == NULL;
    	}
    
    	DWORD dwFindPattern(DWORD dwAddress,DWORD dwLen,BYTE *bMask,char * szMask) {
    		for(DWORD i=0; i < dwLen; i++)
    			if( bDataCompare( (BYTE*)( dwAddress+i ),bMask,szMask) )
    				return (DWORD)(dwAddress+i);
        
    		return 0;
    	}
    };
    
    DWORD getFunctionStart() {
    	PBYTE signature = (PBYTE)"\x52\xE8\x00\x00\x00\x00\x83\xC4\x04\xE8\x00\x00\x00\x00\x83\xC4\x1C";
    	char* mask = "xx????xxxx????xxx";
    	int offset = 0x1C;
    	DWORD patternAddress = Memory::dwFindPattern(0x400000, 0x00FFFFFF, signature, mask);
    	patternAddress += offset;
    	DWORD functionOffset = *(DWORD*)patternAddress;
    	return patternAddress + functionOffset + 4;
    }
    
    BYTE* getNextPushedValue(BYTE* EIP, DWORD* out) {
    	 int i = 0;
    	do {
    		switch (*EIP) {
    		case CALL:
    			EIP += 5;
    			break;
    		case PUSH_B:
    			EIP += 1;
    			*out = *EIP;
    			return EIP + 1;
    		case PUSH:
    			EIP += 1;
    			*out = *(DWORD*)EIP;
    			return EIP + 4;
    		case RETN:
    			std::cout << "END OF FILE" << std::endl;
    			throw std::exception();
    		default:
    			EIP++;
    			break;
    		}
    		i++;
    	} while (i < 20);
    	return EIP;
    }
    
    void dumpPacketInfo(DWORD functionStart, std::ostream& out) {
    	//push1 : packet size
    	//push2 : packet header
    	//call
    	//push1 : char* name
    	//push1 : packet header
    	//call
    	//... repeat
    	BYTE* EIP = (BYTE*)functionStart;
    	DWORD packetSize = 0;
    	DWORD packetHeader1 = 0;
    	DWORD packetHeader2 = 0;
    	DWORD packetName = 0;
    	try {
    		while (true) {
    			EIP = getNextPushedValue(EIP, &packetSize);
    			EIP = getNextPushedValue(EIP, &packetHeader1);
    			EIP = getNextPushedValue(EIP, &packetName);
    			EIP = getNextPushedValue(EIP, &packetHeader2);
    
    			if (packetHeader1 != packetHeader2) {
    				out << "HEADER1 != HEADER2" << std::endl;
    				out << packetHeader1 << " != " << packetHeader2 << std::endl;
    				break;
    			}
    			out << (char*)packetName << " 0x" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase << packetHeader1 << " " << std::dec << std::nouppercase << packetSize << std::endl;
    		}
    	} catch (std::exception e) {
    	}
    }
    
    void extraThread() {
    	char cCurrentPath[FILENAME_MAX];
    	_getcwd(cCurrentPath, sizeof(cCurrentPath));
    	cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */
    	printf("The current working directory is %s\n", cCurrentPath);
    
    	DWORD functionStart = getFunctionStart();
    	std::cout << "Function start: " << functionStart << std::endl;
    
    	std::fstream fs;
    	fs.open("packetinfo.txt", std::fstream::out);
    	dumpPacketInfo(functionStart, fs);
    	fs.close();
    }
    
    BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID) {
    	if (reason == DLL_PROCESS_ATTACH) {
    		CreateThread(0, 0, (LPTHREAD_START_ROUTINE)extraThread, 0, 0, 0);
    	}
    	return 1;
    }

     

    Output is a file in TreeOfSavior\data named packetinfo.txt containing all Packet Information in the following format:

    <PacketName> <OpCode> <Size>

    Size=0 means a variable size

    There is no specific order apart from occurrence in the function. 

     

    I also added the compiled dll :)

    PacketDump.dll

    • Like 1
  2. Hi,

    I just started reverse engineering the TOS network protocol and your project has been a huge help with that. So I thought about also contributing a bit. :)

    I noticed that your ZC_DEAD Packet is not correct.

    I program in Java and I don't know how to do stuff in C# so I don't want to create a pull-request, but here is the Structure of the Packet

    public class Dead {  
      private short size;
      private int handle;
      private byte unk1;
      private byte killCount;
      private byte unk3;
      private byte unk4;
      private Killer[] killer;
    
      private static class Killer {
        private int handle;
        private int xp;
        private int classXp;
      }
    }

    I hope this will be useful for you.

    • Like 1
×
×
  • Create New...