How do speed hacks work? -- The client dictates how quickly the character can switch between two positions and relays that information to the server accordingly. The server performs ZERO verifications against the values provided.
How do position hacks work? -- The client lets the server know the coordinates that the character is positioned at and the server treats it as such, once again, without any validation.
This isn't anything special to FFXI, most MMOs are designed like this because of the amount of overhead that adding server side position syncing causes. All major MMOs are designed this exact same way.
However, what isn't true in your post is that there is no validation. There is. FFXI has multiple levels of movement validation, it's just not used as a means to sync your position or enforce it. SE has added multiple different forms of this over the years. The first main/major ones were:
1. Position warping was monitored heavily in certain zones. FFXI has sub-regions within zones that the client uses to tell the server where you are in a zone, beyond just your XYZ coords. This is sent via the outgoing packet: 0x0F2 SE used this to track warp hacks back during the early CoP era to catch people in zones like Newton/Oldton Movalpolos. There are many sub-regions within each zone that are used for various triggers, shared resources to tell the server which subset of a trigger to use, etc. (An example of this is the docks in Port Jeuno, each desk is a separate subregion.)
2. Position warping was (and still is) monitored for zone trasitions happening too fast. If you warp between two zone lines too fast, the server will reject your zone request and say you failed to enter the next area.
3. Speed hacking was monitored at varying times/degrees since the early CoP era of the game. Just before Abyssea came out as well, SE implemented an auto-jailer system that would immediately jail you if you went over a certain speed amount. This was fairly short lived and only turned on for short bursts of time. When Abyssea came out and the additional level cap increases, new gear, and such were added, they stopped using this system for the most part because it was causing a lot of false positive jailing due to the conditional setup it had.
How did the HQ crafting exploit work? -- The client let the server know that the craft result was an HQ item, so of course, the server respected it and populated an HQ item into the character's inventory.
If you're starting to see a pattern here then you're not alone, the client is king in all things related to cheating.
This is not at all how synthing works. And is completely wrong with how this exploit worked.
Firstly, crafting is nothing more than you telling the server what set of materials you are trying to combine together and with what crystal. (Outgoing packet 0x096 for anyone that wants to validate that.) The client does not have any handling of the synth that will be performed or what the result will be. The server handles all of that.
Once you click ok to begin the synth, the server will immediately send back the response which contains the result of the craft. This is used to tell the client which animation to load and play. (Incoming packet 0x030, 0x06F and 0x070 are used for results.) This is how addons can see what the result will be before you even start to kneel down.
The client does not tell the server the result at all, it has never worked that way for synthing.
As for the actual exploit that happened, it was performed by cancelling the synth.
Not altering/affecting the end result. Since I know this will be a 'not true' moment, here's the exact function that is used to send the synth request/attempt packet:
Code
char __cdecl FUNC_Synthesis_PrepareIngrediants(int a1)
{
int i; // eax
int v2; // edx
int v3; // esi
unsigned __int16 v4; // di
char v5; // dl
unsigned __int16 v6; // ax
int v7; // eax
unsigned int v8; // et2
char result; // al
for ( i = *(unsigned __int8 *)(a1 + 9) - 1; i > 0; --i )
{
v2 = 0;
v3 = i;
v4 = *(_WORD *)(a1 + 2 * i + 10);
if ( i > 0 )
{
do
{
if ( *(_WORD *)(a1 + 2 * v2 + 10) > v4 )
{
v3 = v2;
v4 = *(_WORD *)(a1 + 2 * v2 + 10);
}
++v2;
}
while ( v2 < i );
if ( v3 != i )
{
*(_WORD *)(a1 + 2 * v3 + 10) = *(_WORD *)(a1 + 2 * i + 10);
*(_WORD *)(a1 + 2 * i + 10) = v4;
v5 = *(_BYTE *)(a1 + v3 + 26);
*(_BYTE *)(a1 + v3 + 26) = *(_BYTE *)(a1 + i + 26);
*(_BYTE *)(a1 + i + 26) = v5;
}
}
}
v6 = *(_WORD *)(a1 + 6);
if ( v6 < 0x196Au || v6 >= 0x1972u )
{
if ( v6 < 0x108Eu || v6 >= 0x1096u )
v7 = *(unsigned __int16 *)(a1 + 6);
else
v7 = *(unsigned __int16 *)(a1 + 6) - 142;
}
else
{
v7 = *(unsigned __int16 *)(a1 + 6) - 2410;
}
v8 = (v7 + 3) * (*(unsigned __int16 *)(a1 + 10) + 7) * ((unsigned int)*(unsigned __int8 *)(a1 + 9) + 5) % 0x7F;
result = 1;
*(_BYTE *)(a1 + 4) = v8;
return result;
}
char __cdecl FUNC_Synthesis_StartSynth(int a1)
{
__int16 *v1; // esi
char v3; // al
int v4; // edi
_BYTE *v5; // eax
_WORD *v6; // ecx
v1 = FUNC_BuildOutgoingPacket(0x96, 0, 0);
if ( !v1 )
return 0;
FUNC_Synthesis_PrepareIngrediants(a1);
*((_BYTE *)v1 + 4) = *(_BYTE *)(a1 + 4);
v1[3] = *(_WORD *)(a1 + 6);
*((_BYTE *)v1 + 8) = *(_BYTE *)(a1 + 8);
v3 = *(_BYTE *)(a1 + 9);
*((_BYTE *)v1 + 9) = v3;
if ( v3 )
{
v4 = a1 - (_DWORD)v1;
v5 = v1 + 13;
v6 = v1 + 5;
do
{
*v6 = *(_WORD *)((char *)v6 + v4);
*v5 = v5[v4];
++v6;
++v5;
}
while ( (int)&v5[-26 - (_DWORD)v1] < *((unsigned __int8 *)v1 + 9) );
}
*(_DWORD *)(dword_104CD388 + 0x15818) = 1;
FUNC_QueueOutgoingPacket_Wrap((int)v1, 34, 0);
return 1;
}
Again, no where in this is the client telling the server the result. (And yes, this is dumped from FFXiMain.dll BEFORE SE was aware of the issue. If you want the current one to compare to, I'll post it as well, it's exactly the same.)
Now there's another factor that Thorny has alluded to in previous posts that we can dive into a little deeper. Packet size.
First, this person would have you believe that the server itself uses a "3999 byte buffer for outgoing packets". Sorry, but that is not how computers work. When you see a storage capacity that dictates 1MB, it actually means 1024 kilobytes. How many people here have 3999 MB of RAM? Raise your hands. Zero, of course. You have 4.294 GB of RAM or some other exponential factor of 2.
If you are going to try and insult people and then correct them, at least have valid information.
'3999 byte buffer' does not equal 3999MB. Do you even know what a byte is? 3999 bytes doesn't even equal a single MB.
RAM is also not required to be a divisible of 2 and your operating system does not require that either. Windows, Linux, etc. will all happily support non-divisible-by-two amounts of RAM. You can run with 5, 7, 9, 13, 15, etc. gigs of RAM.
Let's assume that this person was somehow correct and the maximum packet size was "3999 bytes".
There is no need to assume when we can pull it from the client. He also didn't say the maximum packet size was 3999, he said the buffer was 3999 bytes. It is not the same thing.
The client queues packets to be chunked together. This queue can hold up to 30 packets at once. (It is an array limited to a maximum of 30 packets, if all 30 slots are filled currently, the clients request to queue a new packet will fail.) Each of those packets can have a maximum of 508 bytes of packet data. (Due to how the id/size are packed together, the maximum size of a packets data is 508 bytes.)
However, the client limits the uncompressed maximum chunk size to 4000 as seen via:
Code
v14 = FUNC_Huffman_EncodeLength((int)v9, v11, a6);
if ( v14 + v23 + 4 >= (unsigned int)(*(_DWORD *)(dword_104CE0E4 + 0x448) - 0x31) || (v15 = 4 * (*v9 >> 9), v15 + v24 >= 4000) )
{
Again, that is uncompressed. This is not what is actually sent to the server. FFXI has a flow of building chunks that are sent to the server. Basic jist, as I am not going to waste the time explaining it here knowing it's just going to be ignored, is that each client 'tick' will prepare the send queue, then the client will construct a compressed 'chunk' that has a maximum compressed size of 1360 bytes. That limit can be seen here:
Code
v11 = sub_100FA8F0((int)v19, a1 + 4, *((_WORD *)a1 + 3), *((_WORD *)a1 + 4), *((_WORD *)a1 + 5), dword_104CD384 + 252028);
v12 = *((_BYTE *)a1 + 12);
if ( v12 == 1 || v12 == 2 )
{
v20 = 0;
v8 = FUNC_EncryptBuffer((char *)(v9 + 4), 1360u, 0, v19, (int)v11, dword_104CD384 + 252028);
}
else
{
v13 = a1[4186];
v21 = a1[4185];
v22 = v13;
v20 = 1;
v8 = FUNC_EncryptBuffer((char *)(v9 + 4), 1360u, (int)(a1 + 0xC30), v19, (int)v11, dword_104CD384 + 252028);
}
The call to sub_100FA8F0 here is where the client is testing the 'best' optimial size packet that can be build, up to that uncompressed 3999 size. (Which is where that first chunk above showing that limit is from.)
The remaining part is then compressing and encrypting the queued data that will fit into the buffer of 1360 bytes. (Compression is done via a Huffman tree table implementation, encryption is done via Blowfish. A hash is also appended before encryption as a anti-tamper measure, which is done via MD5.) The 1360 size is designed to help prevent / limit fragmentation. This is the lower bounds MTU of standard networks. (1400-1500 generally, not including Jumbo-Packet support.) The 1360 here is just the data chunk size as well, it does not account for the packet header data for the IP header, UDP header, etc. which are added after the fact.
So yes, the 3999 byte buffer Thorny mentioned is correct.
Well guess what, these are UDP packets and as such they don't need to be confirmed by the recipient before the next one is sent. Transmission rate is just as important as packet size and completely eliminates the need for a throttled stream of inventory packets.
The reason that the *4096* kb packets are throttled is because the network routers and firewall that Square Enix uses check for duplicate packets before transmitting anything. This prevents item duplication and a number of other exploits from being allowed through.
Again this is misleading and wrong. The first part is misleading. You make the assumption that just because FFXI uses a UDP socket for its general traffic, that it just accepts the fact that packets are not guaranteed to be sent/received or in a specific order. It does not. Not even close either. XI has its own mini-protocol ontop of UDP. Packets include a sync counter that is used to ensure that you and the client are in proper sync of the packet flow for your socket. Both the incoming and outgoing packets have their own sync count. As well as an expected sync count that is stored in the client (and one on the server) to ensure that you are remaining in the expected range of incoming data. (The server has the same on their end for sending.)
FFXI uses a priority system for certain packets as well, this is used to ensure that you send and receive 'critical' / 'important' packets. (ie. chat, monster pops, direct actions to you/your party, etc.) SE already confirmed this exists in a news post a while back. (I don't have it onhand to link to, but you can go look for it if you want in their news archive.) If your client fails to receive a critical chunk within a given timeframe/sync attempt, you'll be considered link-dead and be disconnected from the server. You can also see how this works in the client if you understand how the packet queue system works.
Your second half of this is just completely wrong and makes absolutely no sense. '4096 kb' isn't even a valid size for UDP packets. They have a maximum of 65,535 bytes or 65.535kb. Not 4096kb like you are saying.
As for your nonsense about firewalls, what the hell are you even saying at this point? Do you even know what a firewall is? What you are thinking of/speaking of is an ALG, not a firewall. And no, that makes absolutely no sense to make use of in this situation. Why would SE spend money/time on high-end, use-specific, expensive hardware rather than just add a simple 'if/then' statement to some code to block an exploit? What mental state do you live in to think that makes any sense at all?
FFXI's packets are chunked, compressed and encrypted. What you are implying is that SE has special hardware that does the following:
- Tracks every connections current blowfish key state. (required to decrypt the packet chunks for every connection.)
- Tracks every connections current sync count. (required to validate things are in sync.)
- Decrypt every chunk for every connection via their unique individual blowfish keys.
- Decompress every decrypted chunk.
- Look for 'exploits' in said chunks.
- Filter out said bad/invalid packets from each chunk.
- Rebuild each chunk with said 'bad' packets removed.
- Recompress, rehash, reencrypt each chunk.
- etc.
Like seriously..? You really think this is how they would approach an exploit instead of just checking a few extra conditions in the source code of the game? The amount of money this type of hardware costs, and the amount of overhead added to the network makes literally 0 sense to do for an MMO.
It's disgusting how much misinformation is being peddled in this thread. *All* manipulation of data comes from the client
Edit: FYI, what Thorny is doing is using buzzwords and partially correct information to troll people who don't have the knowledge to fully comprehend their posts. It's juvenile and easily seen through by anyone who is actually in the industry.
The only thing you've done in this topic, as well as in the past with the interactions I have had with you, are show how disconnected from reality you are. And how little you understand any of this subject material at all. There is a reason no one wants to interact with you. And a reason why no one looks at you as anything other than an annoying man-child.
Yes, I am fully aware of who you are.
Need a refresher on that? This is what you said to me the last time I ignored your attempts to play 'buddy' with me after your last nonsense and psychotic outburst where you tried to doxx Thorny to me and threaten his life.
Code
I love how everyone try’s to act like I’m not one of the Software Elites cod
I seriously recommend you seek actual in-real-life mental health help. This is not to be a troll or for a meme.
You literally need it.