Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Help me understand the logic of this function

Joined
Jun 10, 2009
Messages
658
Reaction score
140
This is the logic how the server reads packets from the client taken from outdated server files released long back for the game Tantra Online. As I am trying to build emulator in C# for a client which is of later version, I would like to understand what exactly this code is doing so that I can code it in C#.

Code:
char* CPSock::ReadClientMessage(int* ErrorCode, int* ErrorType)
{
    *ErrorCode = 0;

    // Proc°¡ Recv¸¦ ÃÊ°úÇÑ °æ¿ì. (½É°¢ÇÑ ¿À·ù, ³ªÅ¸³¯¼ö ¾ø� °æ¿ì�Ù)
    if (nProcPosition >= nRecvPosition) {
        nRecvPosition = 0;
        nProcPosition = 0;
        return 0;
    }
    //  Init packet authentication
    if (Init == 0) {
        if (nRecvPosition - nProcPosition < 4)
            return 0;
        int InitCode = *((unsigned int*)(pRecvBuffer + nProcPosition));
        if (InitCode != INITCODE) {
            *ErrorCode = 2;
            *ErrorType = InitCode;
            CloseSocket(); //fors_debug ÌØÊâ�¦Àí
            return 0;
        }
        Init = 1;
        nProcPosition += 4;
    }
    //	Ccheck received message is larger than HEADER
    if (nRecvPosition - nProcPosition < sizeof(HEADER))
        return 0;
    //	Check full message arrived
    int sh = sizeof(HEADER);
    unsigned short Size = *((unsigned short*)(pRecvBuffer + nProcPosition + 4));
    Size = Size + sizeof(HEADER);
    unsigned char CheckSum = *((unsigned char*)(pRecvBuffer + nProcPosition + 3));
    unsigned int SockType = *((unsigned short*)(pRecvBuffer + nProcPosition));
    unsigned int ClentTick = *((unsigned int*)(pRecvBuffer + nProcPosition + 6));
    if (Size > MAX_MESSAGE_SIZE || Size < sizeof(HEADER)) {
        nRecvPosition = 0;
        nProcPosition = 0;
        *ErrorCode = 2;
        *ErrorType = Size;
        return 0;
    }

    unsigned short Rest = nRecvPosition - nProcPosition;
    if (Size > Rest)
        return 0;

    //	Get message
    char* pMsg = &(pRecvBuffer[nProcPosition]);
    nProcPosition = nProcPosition + Size;
    if (nRecvPosition <= nProcPosition) {
        nRecvPosition = 0;
        nProcPosition = 0;
    }

    // Compare check_sum in packet
    int KeywordFlag = oldRecvChecksum % 2;
    unsigned char Sum = 0;
    int pos = ucRecvSeq;
    for (int i = sizeof(HEADER); i < Size; i++, pos++) {
        int rst = pos % 256;
        unsigned char Trans = pKeyWord[rst][KeywordFlag];
        int mod = i & 0x3;
        if (mod == 0)
            pMsg[i] = pMsg[i] - (Trans << 2);
        if (mod == 1)
            pMsg[i] = pMsg[i] + (Trans >> 1);
        if (mod == 2)
            pMsg[i] = pMsg[i] - (Trans << 1);
        if (mod == 3)
            pMsg[i] = pMsg[i] + (Trans >> 2);
        Sum += pMsg[i];
    }

    ucRecvSeq++;
    oldRecvChecksum = CheckSum;

    // return packet, even check_sum not match
    if (Sum != CheckSum) {
        *ErrorCode = 1;
        *ErrorType = Size;
        return pMsg;
    }
    return pMsg;
}

Thanks in advance!
 
Joined
Nov 20, 2007
Messages
31
Reaction score
9
int nProcPosition = Processes Position
int nRecvPosition = Receive Position
int pRecvBuffer = Buffer containing received data
HEADER = Expected Size of Header (looks like its an buffer?) size is determined by sizeof()
const uint INITCODE = Expected first 4bytes as integer of data


The method 'ReadClientMessage' is probably called in a separate thread and operates on the 'pRecvBuffer', while the sockets will write data and increase 'nRecvPosition' count.
Code:
    if (nProcPosition >= nRecvPosition) {
        nRecvPosition = 0;
        nProcPosition = 0;
        return 0;
    }
This checks if we have processed as much data as we received, if so there is nothing to read for us so we return


Code:
    if (Init == 0) {
        if (nRecvPosition - nProcPosition < 4)
            return 0;
        int InitCode = *((unsigned int*)(pRecvBuffer + nProcPosition));
        if (InitCode != INITCODE) {
            *ErrorCode = 2;
            *ErrorType = InitCode;
            CloseSocket(); //fors_debug ÌØÊâ¦Àí
            return 0;
        }
        Init = 1;
        nProcPosition += 4;
    }
This checks if the beginning of the data stream, or packet (depends on when 'Init' is reset, not visible in this code) starts with an expected uint defined in 'INITCODE'. Usually this is done to check that the client speaks the same protocol as the server, and reject it quickly if not.


Only perform this check if we haven't done it ' (Init == 0)' {
if we have less than 4bytes to read '(nRecvPosition - nProcPosition < 4)' {
abort;
}
read 4bytes from the buffer and cast it to an unsigned int 'int InitCode = *((unsigned int*)(pRecvBuffer + nProcPosition));'
if the read 'InitCode' is not what we expect 'INITCODE' {
set some errors, close the connection and abort
}
Mark that we succesfully checked the first 4 bytes 'Init = 1;' so we don't need to check again (until init is reset?)
Advance the number of processed bytes by 4 ' nProcPosition += 4;'
}



Code:
  //    Ccheck received message is larger than HEADER
    if (nRecvPosition - nProcPosition < sizeof(HEADER))
        return 0;
This checks if we have enough data to read the header, if not we abort.

Code:
    //    Check full message arrived
    int sh = sizeof(HEADER);
    unsigned short Size = *((unsigned short*)(pRecvBuffer + nProcPosition + 4));
    Size = Size + sizeof(HEADER);
    unsigned char CheckSum = *((unsigned char*)(pRecvBuffer + nProcPosition + 3));
    unsigned int SockType = *((unsigned short*)(pRecvBuffer + nProcPosition));
    unsigned int ClentTick = *((unsigned int*)(pRecvBuffer + nProcPosition + 6));
    if (Size > MAX_MESSAGE_SIZE || Size < sizeof(HEADER)) {
        nRecvPosition = 0;
        nProcPosition = 0;
        *ErrorCode = 2;
        *ErrorType = Size;
        return 0;
    }
'unsigned short Size = *((unsigned short*)(pRecvBuffer + nProcPosition + 4));' This reads 2bytes after (last processed position + 4) from the buffer
The result tells us how much data we should read (so it should read position 8 and 9 if the buffer started at 0)


' Size = Size + sizeof(HEADER);' Add the header size itself.


' unsigned char CheckSum = *((unsigned char*)(pRecvBuffer + nProcPosition + 3));' This reads 1byte after (last processed position + 3) from the buffer
The name donates its used as a checksum (it should read position 6 if the buffer started at 0)


' unsigned int SockType = *((unsigned short*)(pRecvBuffer + nProcPosition));' This reads 2byte after (last processed position ) from the buffer
(it should read position 4 and 5 if the buffer started at 0)


' unsigned int ClentTick = *((unsigned int*)(pRecvBuffer + nProcPosition + 6));' This reads 2byte after (last processed position + 6 ) from the buffer
The name sounds like it synchronises the time (it should read position 9,10,11 and 12 if the buffer started at 0)


Code:
[4bytes|uint|InitCode]-[2bytes|ushort|SockType]-[1byte|char|Checksum]-[2bytes|ushort|PacketSize]-[4bytes|uint|ClentTick] <- Structure to read
{0, 1, 2, 3, ----------4,5----------------------6---------------------7,8------------------------9,10,11,12} <--------------Buffer Position


' if (Size > MAX_MESSAGE_SIZE || Size < sizeof(HEADER)) {'
If the packet size which the packet tells us to read, is bigger than the max message size we abort (because we can not trust the read value from a packet blindly)


Code:
 unsigned short Rest = nRecvPosition - nProcPosition;
    if (Size > Rest)
        return 0;
we calculate how much data we still have to read, and if we have more to read than we actually can abort.



Code:
    //    Get message
    char* pMsg = &(pRecvBuffer[nProcPosition]);
    nProcPosition = nProcPosition + Size;
we create a pointer to the area inside the buffer where our complete packet resides called 'pMsg'
we advance our processed position by the size we have just read 'nProcPosition = nProcPosition + Size;'


Code:
    if (nRecvPosition <= nProcPosition) {
        nRecvPosition = 0;
        nProcPosition = 0;
    }
if we have caught up with all the data we reset our counters (otherwise there might be another packet in the buffer, that will possibly be read on next calls?)




Im not to sure of the following it looks like it calculates the checksum of the data we just received, but it also looks like it is modifying the packet?


Code:
    // Compare check_sum in packet
    int KeywordFlag = oldRecvChecksum % 2;
    unsigned char Sum = 0;
    int pos = ucRecvSeq;
    for (int i = sizeof(HEADER); i < Size; i++, pos++) {
        int rst = pos % 256;
        unsigned char Trans = pKeyWord[rst][KeywordFlag];
        int mod = i & 0x3;
        if (mod == 0)
            pMsg[i] = pMsg[i] - (Trans << 2);
        if (mod == 1)
            pMsg[i] = pMsg[i] + (Trans >> 1);
        if (mod == 2)
            pMsg[i] = pMsg[i] - (Trans << 1);
        if (mod == 3)
            pMsg[i] = pMsg[i] + (Trans >> 2);
        Sum += pMsg[i];
    }
    ucRecvSeq++;
    oldRecvChecksum = CheckSum;



As you can see most of the code is just reading bytes in a correct order from a buffer and create a packet from it, i.e recovering the send data as packets.

Note: I don't know c++ so my understanding of the buffer and pointer instructions or data sizes could be off
 
Joined
Jun 10, 2009
Messages
658
Reaction score
140
Thanks for the explanation.
Actually HEADER is a 12 bytes structure. Something like this
Code:
struct HEADER {
    WORD wType;
    WORD wSeq;						
    WORD wPDULength;
    WORD wDummy;
    DWORD dwClientTick;  
}

INITCODE is sent by the client only for the 1st time.

I wanted to know if it was using some standard algorithm inside the checksum loop to manipulate data from the received bytes!
 
Last edited:
Joined
Nov 20, 2007
Messages
31
Reaction score
9
Ah a struct makes more sense :)
As noted early this code reads and parsed the header (12 bytes)
(EDIT: The header should only be 8bytes, as the INIT takes 4bytes and is not part of the header)
Code:
[COLOR=#666666][4bytes|uint|InitCode]-[2bytes|ushort|SockType]-[1byte|char|Checksum]-[2bytes|ushort|PacketSize]-[4bytes|uint|ClentTick] <- Structure to read
[/COLOR][COLOR=#666666]{0, 1, 2, 3, ----------4,5----------------------6---------------------7,8------------------------9,10,11,12} <--------------Buffer Position[/COLOR]
But only reads all the body and makes no sense of it (only uses it as checksum calculation here). This step happens probably later based on some ID.

From the code, the algorithm operates only on the data, not the header. (int i = sizeof(HEADER);)
Also it seems that the checksum is continuously based on the last checksum.
Code:
[COLOR=#666666]int KeywordFlag = oldRecvChecksum % 2;
[/COLOR]....
[COLOR=#666666]unsigned char Trans = [/COLOR][COLOR=#666666]pKeyWord[rst][KeywordFlag];[/COLOR]

So the only missing part to calculating the checksum is most likly the 'pKeyWord' variable.
it looks like it is some sort of JaggedArray that acts as a lookup table.

I would assume that it should be defined or build somewhere, also I would assume you can see how the checksum gets created by looking into the 'Send' part of the code.

I can't tell if its a well known algo, but since its coded like that and don't use a library I'd guess its custom.
 
Last edited:
Joined
Jun 10, 2009
Messages
658
Reaction score
140
If you want to take a look at the whole source then here is the link

TMSRV is actually the source of Zone Server where this code is available in the file named CPSock.cpp!
 
Initiate Mage
Joined
Apr 12, 2017
Messages
27
Reaction score
1
what version of visual studio do you actually used to build the source? i got lots of error in my compiler.
 
Initiate Mage
Joined
Jul 17, 2013
Messages
90
Reaction score
18
//snipit looks like it is some sort of JaggedArray that acts as a lookup table.
//snip
The table you requested is below.

Code:
unsigned char dTable[256][2] ={ 0xEB, 0x7D, 0xD7, 0x7C, 0x87, 0x69, 0xEB, 0x79, 0xEB, 0x79, 0xEB, 0x7F, 0x87, 0x7D, 0x87, 0x66, 0xCD, 0x7D, 0xEB, 0x7D, 0x73, 0x73, 0x23, 0x37, 0xD7, 0x91, 0xCD, 0x79, 0xE1, 0x7D, 0xEB, 0x73, 0x23, 0x7D, 0xE1, 0x7B, 0x87, 0x91, 0x87, 0xE5, 0x7D, 0xD7, 0x73, 0x2F, 0x87, 0x69, 0x23, 0x7C, 0xCD, 0x7B, 0xEB, 0x79, 0x23, 0x7D, 0x73, 0x7D, 0x20, 0xD4, 0xEB, 0x78, 0x83, 0xE1, 0xEB, 0x90, 0x23, 0xC3, 0x0F, 0x87, 0x91, 0x79, 0x23, 0x79, 0x87, 0x78, 0x87, 0x84, 0x1B, 0x7D, 0xEB, 0x80, 0x82, 0x6E, 0x91, 0x7C, 0x87, 0xBB, 0xEB, 0x79, 0xFF, 0x05, 0xEB, 0x69, 0x69, 0x6F, 0xEB, 0x79, 0xEB, 0x19, 0x05, 0x2F, 0xC2, 0x5F, 0x19, 0x41, 0xEB, 0x91, 0x71, 0x7B, 0xA7, 0x4B, 0xE6, 0x7D, 0xA4, 0x7D, 0x87, 0x19, 0x21, 0xC2, 0x87, 0x16, 0xEB, 0x70, 0xEB, 0x7D, 0x23, 0x7D, 0xEB, 0x7D, 0xEB, 0x17, 0x23, 0x80, 0xCD, 0x78, 0xEB, 0x7D, 0x87, 0x7D, 0xEB, 0x7B, 0x8B, 0xC3, 0xEB, 0x7A, 0x87, 0x7D, 0x70, 0x83, 0xD1, 0xDD, 0xEB, 0x78, 0xF6, 0x7E, 0x87, 0x7D, 0x88, 0x19, 0x87, 0xF5, 0x87, 0x7D, 0xD7, 0xE1, 0x9B, 0x87, 0xEB, 0x9B, 0xCD, 0x7B, 0x23, 0x6C, 0x83, 0x7F, 0xEB, 0x14, 0xEB, 0x7D, 0x1F, 0x73, 0xEB, 0x7D, 0xE9, 0x0F, 0x23, 0x16, 0xEB, 0x19, 0xD7, 0x9B, 0x8D, 0x9B, 0xA3, 0x7D, 0xCA, 0x73, 0x83, 0x7A, 0x87, 0x7D, 0xE7, 0x7D, 0xEB, 0x7D, 0xE7, 0x7D, 0xEB, 0x7D, 0xEB, 0x7D, 0xD7, 0x67, 0xEB, 0x7D, 0x87, 0x7D, 0xEB, 0x7D, 0xEB, 0x7D, 0x84, 0x7D, 0xEB, 0x7D, 0x87, 0x7D, 0xE7, 0x7D, 0x87, 0x79, 0xEB, 0x98, 0xF5, 0x66, 0xEB, 0x80, 0x87, 0x1A, 0x87, 0xE1, 0xE8, 0x6F, 0xD1, 0x79, 0x83, 0x9B, 0xE1, 0x85, 0x8D, 0x7B, 0x0F, 0x79, 0xE1, 0x79, 0xEB, 0x6B, 0x87, 0x7D, 0xEB, 0x7C, 0x2D, 0x7D, 0xD7, 0xDD, 0xE9, 0x73, 0xEB, 0x86, 0x0F, 0x79, 0xE8, 0x79, 0x05, 0x7D, 0xD7, 0xCD, 0xEB, 0xE1, 0x87, 0xDD, 0xD7, 0x8F, 0x05, 0x7D, 0xEB, 0x7A, 0xE7, 0x73, 0xEB, 0x9B, 0x6F, 0x87, 0xE9, 0x7C, 0xCD, 0x0F, 0xEB, 0x80, 0xEB, 0x79, 0x84, 0x87, 0x37, 0xD7, 0xEA, 0x79, 0x8D, 0x91, 0x0B, 0x73, 0x4B, 0x19, 0xEB, 0x69, 0x91, 0x23, 0x87, 0x81, 0xEB, 0xE0, 0x23, 0xE1, 0x4B, 0x83, 0xA3, 0xA1, 0xF5, 0x79, 0x21, 0x7D, 0xE6, 0x69, 0x23, 0x7E, 0xAE, 0x7C, 0x0F, 0xE1, 0x87, 0x6A, 0xE7, 0x79, 0x9B, 0x7D, 0x02, 0x91, 0xEB, 0x7B, 0x86, 0x71, 0xDD, 0x2D, 0x87, 0x6F, 0xE7, 0x79, 0xD7, 0x7C, 0x23, 0x1C, 0x23, 0x7D, 0xEB, 0x7F, 0xAF, 0x79, 0x37, 0x68, 0xC3, 0x79, 0xCD, 0x7D, 0xEB, 0x7A, 0x21, 0x7D, 0xEB, 0x19, 0xEB, 0x95, 0x87, 0x7D, 0xE1, 0x78, 0xCD, 0x7D, 0x87, 0x7D, 0xD7, 0x7D, 0x23, 0x7D, 0x87, 0x7C, 0xDD, 0x91, 0xEB, 0x7A, 0xEB, 0xAF, 0x87, 0x23, 0xEB, 0x10, 0xCD, 0xDF, 0x87, 0x86, 0x87, 0xA5, 0x87, 0x7C, 0x73, 0x7E, 0xED, 0x7D, 0xD7, 0x7D, 0xEB, 0x7D, 0x0F, 0x7D, 0xD7, 0x7D, 0xE1, 0x7A, 0x68, 0x79, 0xD6, 0x7E, 0xEB, 0x98, 0xEB, 0x79, 0xF5, 0x7D, 0xE1, 0x7A, 0xEB, 0x23, 0x37, 0x6F, 0x23, 0x7C, 0x87, 0x7B, 0xD7, 0x7A, 0x7D, 0x80, 0xE7, 0x67, 0xEB, 0x7A, 0x23, 0x7D, 0x87, 0x6A, 0xEB, 0xA5, 0x23, 0x7D, 0xEB, 0x7F, 0xAF, 0x79, 0x37, 0x7C, 0xC3, 0x79, 0xCD, 0x7D, 0xEB, 0x7A, 0x21, 0x7D, 0xEB, 0x19, 0xEB, 0x95, 0x23, 0x7D, 0x23, 0x79, 0xD5, 0x7D, 0x73, 0x7D, 0xE1, 0x7A, 0x87, 0x79, 0xEB, 0x7D, 0xEB, 0x7D, 0xCD, 0x7A, 0xEB, 0x37, 0xEB, 0x73, 0xD7, 0x87, 0xE7, 0xE3, 0xEB, 0x6C, 0x7C, 0x91, 0xEB, 0x7D };
 
Initiate Mage
Joined
Apr 12, 2017
Messages
27
Reaction score
1
I cannot compile this code. Some of the files are missing. I was trying to rewrite the whole logic by seeing this existing code!

What file you think that is missing? it's better to have both ZONESRV and HTLauncher source file so that we can rewrite the whole system of tantra..
 
Joined
Jun 10, 2009
Messages
658
Reaction score
140
All the source I have is of Tantra k3
SQLDAEMON:
DSRV and ZONESRV:
HTLauncher:

SQLDAEMON and DBSRV do compile but they do not work with k6 Tantra server exes!
 
Initiate Mage
Joined
Apr 12, 2017
Messages
27
Reaction score
1
All the source I have is of Tantra k3
SQLDAEMON:
DSRV and ZONESRV:
HTLauncher:

SQLDAEMON and DBSRV do compile but they do not work with k6 Tantra server exes!
Sadly all the source is already outdated. but thank you for sharing this cyberinferno, i will try to explore these files.
 
Joined
Jan 4, 2011
Messages
83
Reaction score
21
The table you requested is below.

Code:
unsigned char dTable[256][2] ={ 0xEB, 0x7D, 0xD7, 0x7C, 0x87, 0x69, 0xEB, 0x79, 0xEB, 0x79, 0xEB, 0x7F, 0x87, 0x7D, 0x87, 0x66, 0xCD, 0x7D, 0xEB, 0x7D, 0x73, 0x73, 0x23, 0x37, 0xD7, 0x91, 0xCD, 0x79, 0xE1, 0x7D, 0xEB, 0x73, 0x23, 0x7D, 0xE1, 0x7B, 0x87, 0x91, 0x87, 0xE5, 0x7D, 0xD7, 0x73, 0x2F, 0x87, 0x69, 0x23, 0x7C, 0xCD, 0x7B, 0xEB, 0x79, 0x23, 0x7D, 0x73, 0x7D, 0x20, 0xD4, 0xEB, 0x78, 0x83, 0xE1, 0xEB, 0x90, 0x23, 0xC3, 0x0F, 0x87, 0x91, 0x79, 0x23, 0x79, 0x87, 0x78, 0x87, 0x84, 0x1B, 0x7D, 0xEB, 0x80, 0x82, 0x6E, 0x91, 0x7C, 0x87, 0xBB, 0xEB, 0x79, 0xFF, 0x05, 0xEB, 0x69, 0x69, 0x6F, 0xEB, 0x79, 0xEB, 0x19, 0x05, 0x2F, 0xC2, 0x5F, 0x19, 0x41, 0xEB, 0x91, 0x71, 0x7B, 0xA7, 0x4B, 0xE6, 0x7D, 0xA4, 0x7D, 0x87, 0x19, 0x21, 0xC2, 0x87, 0x16, 0xEB, 0x70, 0xEB, 0x7D, 0x23, 0x7D, 0xEB, 0x7D, 0xEB, 0x17, 0x23, 0x80, 0xCD, 0x78, 0xEB, 0x7D, 0x87, 0x7D, 0xEB, 0x7B, 0x8B, 0xC3, 0xEB, 0x7A, 0x87, 0x7D, 0x70, 0x83, 0xD1, 0xDD, 0xEB, 0x78, 0xF6, 0x7E, 0x87, 0x7D, 0x88, 0x19, 0x87, 0xF5, 0x87, 0x7D, 0xD7, 0xE1, 0x9B, 0x87, 0xEB, 0x9B, 0xCD, 0x7B, 0x23, 0x6C, 0x83, 0x7F, 0xEB, 0x14, 0xEB, 0x7D, 0x1F, 0x73, 0xEB, 0x7D, 0xE9, 0x0F, 0x23, 0x16, 0xEB, 0x19, 0xD7, 0x9B, 0x8D, 0x9B, 0xA3, 0x7D, 0xCA, 0x73, 0x83, 0x7A, 0x87, 0x7D, 0xE7, 0x7D, 0xEB, 0x7D, 0xE7, 0x7D, 0xEB, 0x7D, 0xEB, 0x7D, 0xD7, 0x67, 0xEB, 0x7D, 0x87, 0x7D, 0xEB, 0x7D, 0xEB, 0x7D, 0x84, 0x7D, 0xEB, 0x7D, 0x87, 0x7D, 0xE7, 0x7D, 0x87, 0x79, 0xEB, 0x98, 0xF5, 0x66, 0xEB, 0x80, 0x87, 0x1A, 0x87, 0xE1, 0xE8, 0x6F, 0xD1, 0x79, 0x83, 0x9B, 0xE1, 0x85, 0x8D, 0x7B, 0x0F, 0x79, 0xE1, 0x79, 0xEB, 0x6B, 0x87, 0x7D, 0xEB, 0x7C, 0x2D, 0x7D, 0xD7, 0xDD, 0xE9, 0x73, 0xEB, 0x86, 0x0F, 0x79, 0xE8, 0x79, 0x05, 0x7D, 0xD7, 0xCD, 0xEB, 0xE1, 0x87, 0xDD, 0xD7, 0x8F, 0x05, 0x7D, 0xEB, 0x7A, 0xE7, 0x73, 0xEB, 0x9B, 0x6F, 0x87, 0xE9, 0x7C, 0xCD, 0x0F, 0xEB, 0x80, 0xEB, 0x79, 0x84, 0x87, 0x37, 0xD7, 0xEA, 0x79, 0x8D, 0x91, 0x0B, 0x73, 0x4B, 0x19, 0xEB, 0x69, 0x91, 0x23, 0x87, 0x81, 0xEB, 0xE0, 0x23, 0xE1, 0x4B, 0x83, 0xA3, 0xA1, 0xF5, 0x79, 0x21, 0x7D, 0xE6, 0x69, 0x23, 0x7E, 0xAE, 0x7C, 0x0F, 0xE1, 0x87, 0x6A, 0xE7, 0x79, 0x9B, 0x7D, 0x02, 0x91, 0xEB, 0x7B, 0x86, 0x71, 0xDD, 0x2D, 0x87, 0x6F, 0xE7, 0x79, 0xD7, 0x7C, 0x23, 0x1C, 0x23, 0x7D, 0xEB, 0x7F, 0xAF, 0x79, 0x37, 0x68, 0xC3, 0x79, 0xCD, 0x7D, 0xEB, 0x7A, 0x21, 0x7D, 0xEB, 0x19, 0xEB, 0x95, 0x87, 0x7D, 0xE1, 0x78, 0xCD, 0x7D, 0x87, 0x7D, 0xD7, 0x7D, 0x23, 0x7D, 0x87, 0x7C, 0xDD, 0x91, 0xEB, 0x7A, 0xEB, 0xAF, 0x87, 0x23, 0xEB, 0x10, 0xCD, 0xDF, 0x87, 0x86, 0x87, 0xA5, 0x87, 0x7C, 0x73, 0x7E, 0xED, 0x7D, 0xD7, 0x7D, 0xEB, 0x7D, 0x0F, 0x7D, 0xD7, 0x7D, 0xE1, 0x7A, 0x68, 0x79, 0xD6, 0x7E, 0xEB, 0x98, 0xEB, 0x79, 0xF5, 0x7D, 0xE1, 0x7A, 0xEB, 0x23, 0x37, 0x6F, 0x23, 0x7C, 0x87, 0x7B, 0xD7, 0x7A, 0x7D, 0x80, 0xE7, 0x67, 0xEB, 0x7A, 0x23, 0x7D, 0x87, 0x6A, 0xEB, 0xA5, 0x23, 0x7D, 0xEB, 0x7F, 0xAF, 0x79, 0x37, 0x7C, 0xC3, 0x79, 0xCD, 0x7D, 0xEB, 0x7A, 0x21, 0x7D, 0xEB, 0x19, 0xEB, 0x95, 0x23, 0x7D, 0x23, 0x79, 0xD5, 0x7D, 0x73, 0x7D, 0xE1, 0x7A, 0x87, 0x79, 0xEB, 0x7D, 0xEB, 0x7D, 0xCD, 0x7A, 0xEB, 0x37, 0xEB, 0x73, 0xD7, 0x87, 0xE7, 0xE3, 0xEB, 0x6C, 0x7C, 0x91, 0xEB, 0x7D };

That is not the array used to encrypt/decrypt, the one used start with:
0x28 0x3D 0x03 0xD2 0x9A 0x6A 0x6F (where the 6A6F is the famous "jo") and of course you have to search it with HexEditor because the one declare on 2003 source code is not the one used for v 6.9.0.6.

So the only missing part to calculating the checksum is most likly the 'pKeyWord' variable.
it looks like it is some sort of JaggedArray that acts as a lookup table.

It acts as an encryting/decrypting table

...... also I would assume you can see how the checksum gets created by looking into the 'Send' part of the code.
for (var i = 12; i < Size; i++, pos++)
{
CheckSum += pMsg; ........

checksum is the sum of all bytes values, of the packet, starting after the header (from byte 12 till the last byte of the packet)

I can't tell if its a well known algo, but since its coded like that and don't use a library I'd guess its custom.
You gess it right, it is a custom algo made by hanbit.
 
Last edited:
Joined
Oct 23, 2012
Messages
39
Reaction score
1
This is the only part you need for decrypt the socket message... well the structure too

for (int i = sizeof(HEADER); i < Size; i++, pos++) {
int rst = pos % 256;
unsigned char Trans = pKeyWord[rst][KeywordFlag];
int mod = i & 0x3;
if (mod == 0)
pMsg = pMsg - (Trans << 2);
if (mod == 1)
pMsg = pMsg + (Trans >> 1);
if (mod == 2)
pMsg = pMsg - (Trans << 1);
if (mod == 3)
pMsg = pMsg + (Trans >> 2);
Sum += pMsg;
}
 
Back
Top