Compare commits

..

No commits in common. "5be68642d073a98ebd12ca1bf244c7a4a3073c6c" and "6f436ead4d542c2483ed6656df1e4273b36f996f" have entirely different histories.

10 changed files with 31 additions and 584 deletions

View File

@ -4,7 +4,6 @@
#include "common.h"
#include "bitstream.h"
#include "packet.h"
#include <stdio.h>
__declspec(naked)
void __stdcall BitStream__ctor(
@ -45,61 +44,3 @@ int __stdcall BitStream__Read(struct CBitStream *this, char *out)
jmp eax
}
}
int __stdcall Hooked_BitStream__ReadCompressed(
char *out,
unsigned char a,
unsigned char unsignedData)
{
struct CBitStream *this;
unsigned char tmpa, tmpread;
int myReadOffset;
_asm mov this, ecx
tmpa = (a >> 3) - 1;
if (unsignedData) {
unsignedData = 0;
a = 0;
} else {
unsignedData = 0xFF;
a = 0xF0;
}
while (tmpa > 0) {
myReadOffset = this->readOffset + 1;
if (myReadOffset > this->numberOfBitsUsed) {
return 0;
}
if ((0x80 >> this->readOffset) == this->ptrData[myReadOffset]) {
this->readOffset = myReadOffset;
return (int) thiscall3(
(void*) 0x44DA70, this, (int) out, tmpa, 1);
}
this->readOffset = myReadOffset;
out[tmpa] = unsignedData;
tmpa--;
}
if (this->readOffset + 1 > this->numberOfBitsUsed) {
return 0;
}
if (!thiscall1((void*) 0x44D840, this, (int) &tmpread)) { /*readBit*/
return 0;
}
out += 0; /*? esi + ebx but esi should be always 0?*/
if (tmpread) {
if (!thiscall3((void*) 0x44DA70, this, (int) out, 4, 1)) {
return 0;
}
*out |= a;
} else {
if (!thiscall3((void*) 0x44DA70, this, (int) out, 8, 1)) {
return 0;
}
}
return 1;
}

View File

@ -21,7 +21,3 @@ void __stdcall BitStream__ctor(
void __stdcall BitStream__dtor();
int __stdcall BitStream__Read(struct CBitStream *this, char *out);
int __stdcall Hooked_BitStream__ReadCompressed(
char *out,
unsigned char,
unsigned char);

120
common.c
View File

@ -3,115 +3,6 @@
#include "common.h"
__declspec(naked)
void j__free(void *ptr)
{
_asm {
mov eax, 0x49AAA8
jmp eax
}
}
__declspec(naked)
void * __stdcall Queue_AtPosition_QWORD(struct CQueue *queue, int position)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45B690
jmp eax
}
}
__declspec(naked)
void __stdcall Queue_Push_QWORD(struct CQueue *queue, void *value)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45B5B0
jmp eax
}
}
/**
@param value a POINTER to the value (so for a queue of pointers, a **value)
*/
__declspec(naked)
void __stdcall Queue_Push_DWORD(struct CQueue *queue, void *value)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x450FA0
jmp eax
}
}
__declspec(naked)
void * __stdcall thiscall0(void *address, void *this)
{
_asm {
add esp, 0xC
mov ecx, [esp-0x4]
mov eax, [esp-0x8]
push [esp-0xC]
jmp eax
}
}
__declspec(naked)
void * __stdcall thiscall1(void *address, void *this, int a)
{
_asm {
add esp, 0xC
mov ecx, [esp-0x4]
mov eax, [esp-0x8]
push [esp-0xC]
jmp eax
}
}
__declspec(naked)
void * __stdcall thiscall2(void *address, void *this, int a, int b)
{
_asm {
add esp, 0xC
mov ecx, [esp-0x4]
mov eax, [esp-0x8]
push [esp-0xC]
jmp eax
}
}
__declspec(naked)
void * __stdcall thiscall3(void *address, void *this, int a, int b, int c)
{
_asm {
add esp, 0xC
mov ecx, [esp-0x4]
mov eax, [esp-0x8]
push [esp-0xC]
jmp eax
}
}
__declspec(naked)
void * __stdcall thiscall4(void *address, void *this,
int a, int b, int c, int d)
{
_asm {
add esp, 0xC
mov ecx, [esp-0x4]
mov eax, [esp-0x8]
push [esp-0xC]
jmp eax
}
}
__declspec(naked)
void __stdcall RangeList__ctor(struct CRangeList *this)
{
@ -148,17 +39,6 @@ int __stdcall BPlusTree__IsEmpty(void *this)
}
}
void RaknetTimeNS_Add(struct CRaknetTimeNS *this, unsigned int value)
{
unsigned int oldLo;
oldLo = this->lo32;
this->lo32 += value;
if (this->lo32 < oldLo) {
this->hi32++;
}
}
int RaknetTimeNS_IsBigger(
struct CRaknetTimeNS isbigger,
struct CRaknetTimeNS than)

View File

@ -6,9 +6,6 @@
#define STATIC_ASSERT(E) typedef char __static_assert_[(E)?1:-1]
#define EXPECT_SIZE(S,SIZE) STATIC_ASSERT(sizeof(S)==(SIZE))
#define DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE 0x200
#define NUMBER_OF_ORDERED_STREAMS 0x20
#pragma pack(push, 1)
struct PlayerID {
int binaryAddress;
@ -40,20 +37,6 @@ struct CRangeNode_Short {
};
EXPECT_SIZE(struct CRangeNode_Short, 0x4);
struct CListNode_DWORD {
void *value;
struct CListNode_DWORD *prev;
struct CListNode_DWORD *next;
};
EXPECT_SIZE(struct CListNode_DWORD, 0xC);
struct CCircularLinkedList {
unsigned int list_size;
void *root;
void *position;
};
EXPECT_SIZE(struct CCircularLinkedList, 0xC);
struct CRaknetTimeNS {
unsigned int lo32;
unsigned int hi32;
@ -62,19 +45,15 @@ EXPECT_SIZE(struct CRaknetTimeNS, 0x8);
struct CQueue {
void *array;
/*index of head element*/
int head;
/*index of tail element*/
int tail;
void *head;
void *tail;
int allocationSize;
};
EXPECT_SIZE(struct CQueue, 0x10);
struct CReliabilityLayer {
/*000*/ char _pad0[0xC];
/**packets ready for handling*/
/*00C*/ struct CQueue outputQueue;
/**this is acknowlegements to send on next update*/
/*01C*/ void *acknowlegements; // DataStructures::RangeList<short>
/*020*/ char _pad20[0x20];
/*040*/ void *resendList;
@ -114,16 +93,7 @@ struct CReliabilityLayer {
/*3EC*/ char _pad3EC[0x28];
/*414*/ int someCounter;
/*418*/ char _pad418[0xC];
/**
Queue that stores received packets with a higher message number than the first
next packet that we are supposed to receive. 0 values means the packet with that
number (the index == messagenumber) has been received, non-0 values are the
timeNS when this packet hole should be expired (removed).
*/
/*424*/ struct CQueue hasReceivedPacketQueue;
/**
Next message number that is needed.
*/
/*434*/ short receivedPacketsBaseIndex;
/*436*/ char resetReceivedPackets;
/*437*/ char _pad437[0x11];
@ -161,27 +131,9 @@ struct CInternalPacket {
EXPECT_SIZE(struct CInternalPacket, 0x38);
#pragma pack(pop)
#define QUEUE_SIZE(X) \
((X.tail > X.head) ? \
(X.tail - X.head) : (X.allocationSize - X.head + X.tail))
#define QUEUE_POP_IGNOREVALUE(X) \
(X.head = (X.head+1 == X.allocationSize) ? 0 : (X.head+1))
void j__free(void *ptr);
void * __stdcall Queue_AtPosition_QWORD(struct CQueue *queue, int position);
void __stdcall Queue_Push_QWORD(struct CQueue *queue, void *value);
void __stdcall Queue_Push_DWORD(struct CQueue *queue, void *value);
void * __stdcall thiscall0(void *address, void *this);
void * __stdcall thiscall1(void *address, void *this, int);
void * __stdcall thiscall2(void *address, void *this, int, int);
void * __stdcall thiscall3(void *address, void *this, int, int, int);
void * __stdcall thiscall4(void *address, void *this, int, int, int, int);
void __stdcall RangeList__ctor(struct CRangeList *this);
void __stdcall RangeList__dtor(struct CRangeList *this);
int __stdcall BPlusTree__IsEmpty(void *this);
void RaknetTimeNS_Add(struct CRaknetTimeNS *this, unsigned int value);
int RaknetTimeNS_IsBigger(
struct CRaknetTimeNS isbigger,
struct CRaknetTimeNS than);

View File

@ -2,11 +2,9 @@
/* vim: set filetype=c ts=8 noexpandtab: */
#include "common.h"
#include "bitstream.h"
#include "rakpeer.h"
#include "processnetworkpacket.h"
#include "uncompress.h"
#include "rangelist_deserialize.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
@ -26,6 +24,4 @@ void nethandler_init()
simple_redir_call(RP_PARSE_NETWORK_PACKET, ProcessNetworkPacket);
simple_redir_call(RP_PARSE_CONNECTION_REQ,
RakPeer__ParseConnectionRequestPacket);
//simple_redir_call((void*) 0x45F951, RangeList__Deserialize_hooked);
simple_redir_call((void*) 0x45E2EF, Hooked_BitStream__ReadCompressed);
}

View File

@ -1,50 +0,0 @@
/* vim: set filetype=c ts=8 noexpandtab: */
#include "common.h"
#include "rangelist_deserialize.h"
#include "bitstream.h"
__declspec(naked)
int __stdcall RangeList__Deserialize(
struct CRangeList *this,
struct CBitStream *bitStream)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45E2D0
jmp eax
}
}
int __stdcall RangeList__Deserialize_hooked(struct CBitStream *bitStream)
{
struct CRangleList *this;
short result;
char confusingVar;
int value, valueshr3;
_asm mov this, ecx
thiscall0((void*) 0x45D820, this);
thiscall3((void*) 0x44DB30, bitStream, (int) &result, 0x10, 1);
if (result == 0) {
return 1;
}
confusingVar = *((char*) bitStream); // ??
if (bitStream->readOffset + 1 <= bitStream->numberOfBitsUsed) {
value = (int) bitStream->ptrData;
valueshr3 = value >> 3;
value &= 0x8000007;
if (value & 0x80000000) {
}
}
return 0;
}

View File

@ -1,8 +0,0 @@
/* vim: set filetype=c ts=8 noexpandtab: */
int __stdcall RangeList__Deserialize(
struct CRangeList *this,
struct CBitStream *bitStream);
int __stdcall RangeList__Deserialize_hooked(struct CBitStream *bitStream);

View File

@ -1,8 +1,6 @@
/* vim: set filetype=c ts=8 noexpandtab: */
//#define CALL_ORIGINAL
#define RELIABILITY_PRINT
#ifdef RELIABILITY_PRINT
@ -15,7 +13,6 @@
#include "bitstream.h"
#include "rakpeer.h"
#include "reliability.h"
#include "rangelist_deserialize.h"
#include <stdio.h>
__declspec(naked)
@ -50,262 +47,14 @@ void SendAckForPacket(
RangeList_Short__Insert(&this->acknowlegements, packet->messageNumber);
}
static
void ResetReceivedPackets(struct CReliabilityLayer *this)
{
if (!this->resetReceivedPackets) {
return;
}
thiscall1((void*) 0x45B770, &this->hasReceivedPacketQueue,
DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE);
}
/**
@return 0 if packet should be discarded
*/
static
int HandlePacketHole(
struct CReliabilityLayer *this,
int holeSize,
struct CRaknetTimeNS time)
{
struct CQueue *queueptr;
struct CRaknetTimeNS *timeAt, timeTmp;
#define queue this->hasReceivedPacketQueue
queueptr = &this->hasReceivedPacketQueue;
if (holeSize == 0) {
if (QUEUE_SIZE(queue)) {
QUEUE_POP_IGNOREVALUE(queue);
}
this->receivedPacketsBaseIndex++;
return 1;
}
dprintf("packet hole is %d\n", holeSize);
if (holeSize > 0x8000) {
/*? underflow apparently*/
this->statistics_duplicateMessagesReceived++;
return 0;
}
if (holeSize < QUEUE_SIZE(queue)) {
timeAt = Queue_AtPosition_QWORD(queueptr, holeSize);
if (timeAt->lo32 == 0 && timeAt->hi32 == 0) {
/*was already received, so duplicate packet*/
this->statistics_duplicateMessagesReceived++;
return 0;
}
/*it was a hole that has just been filled*/
timeAt->lo32 = timeAt->hi32 = 0;
return 1;
}
/*add to queue, with holes in between*/
while (holeSize > QUEUE_SIZE(queue)) {
timeTmp = time;
RaknetTimeNS_Add(&timeTmp, this->timeoutTimeMS * 1000);
Queue_Push_QWORD(queueptr, &time);
}
timeTmp.lo32 = timeTmp.hi32 = 0;
Queue_Push_QWORD(queueptr, &timeTmp);
return 1;
}
static
void RemovePacketHolesNotReceivedInTime(
struct CReliabilityLayer *this,
struct CRaknetTimeNS time)
{
struct CQueue *queueptr;
struct CRaknetTimeNS *expireTime;
#define queue this->hasReceivedPacketQueue
queueptr = &this->hasReceivedPacketQueue;
while (QUEUE_SIZE(queue)) {
expireTime = Queue_AtPosition_QWORD(queueptr, queue.head);
if (!RaknetTimeNS_IsBigger(time, *expireTime)) {
return;
}
QUEUE_POP_IGNOREVALUE(queue);
this->receivedPacketsBaseIndex++;
}
}
static
void CompressMessageHoleQueue(struct CReliabilityLayer *this)
{
#define queue this->hasReceivedPacketQueue
if (queue.allocationSize <= DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE) {
return;
}
if (QUEUE_SIZE(queue) * 3 <= queue.allocationSize) {
return;
}
/*Queue::Compress*/
thiscall0((void*) 0x45B6C0, &this->hasReceivedPacketQueue);
}
static
void DiscardPacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet)
{
j__free(packet->pData);
thiscall1((void*) 0x44EBF0, &this->internalPacketPool, (int) packet);
}
static
int HandleSequencedPacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet)
{
char channel;
short waitingIndex;
short newIndex;
if (packet->packetReliability != RELIABLE_SEQUENCED ||
packet->packetReliability != UNRELIABLE_SEQUENCED)
{
return 0;
}
channel = packet->orderingChannel;
if (channel >= NUMBER_OF_ORDERED_STREAMS) {
DiscardPacket(this, packet);
return 1;
}
waitingIndex = this->waitingForSequencedPacketReadIndex[channel];
newIndex = packet->orderingIndex;
/*isOlderSequencedPacked*/
if (thiscall2((void*) 0x45B3D0, this, newIndex, waitingIndex)) {
this->statistics_sequencedMessagesOutOfOrder++;
DiscardPacket(this, packet);
return 1;
}
this->statistics_sequencedMessagesInOrder++;
/*ignoring split packet code @0x460098*/
this->waitingForSequencedPacketReadIndex[channel] = newIndex + 1;
Queue_Push_DWORD(&this->outputQueue, &packet);
return 1;
}
static
void OutputNowInOrderPackets(
struct CReliabilityLayer *this,
struct CCircularLinkedList *orderingList,
short *waitingForIndex)
{
struct CInternalPacket *packet;
struct CListNode_DWORD *node, *root;
int wasAtLeastOneRemoved;
wasAtLeastOneRemoved = 1;
while (wasAtLeastOneRemoved && orderingList->list_size) {
wasAtLeastOneRemoved = 0;
root = node = orderingList->position = orderingList->root;
do {
packet = node->value;
if (packet->orderingIndex == *waitingForIndex) {
dprintf("popped out of order packet\n");
Queue_Push_DWORD(&this->outputQueue, &packet);
/*CCircularLinkedList::PopCurrent_DWORD*/
thiscall0((void*) 0x44E750, orderingList);
*waitingForIndex++;
wasAtLeastOneRemoved = 1;
break;
}
node = node->next;
} while (node != root);
}
}
static
int HandleOrdenedPacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet)
{
char channel;
short newIndex;
short *waitingForIndex;
struct CCircularLinkedList *orderingList;
if (packet->packetReliability != RELIABLE_ORDENED) {
return 0;
}
channel = packet->orderingChannel;
if (channel >= NUMBER_OF_ORDERED_STREAMS) {
DiscardPacket(this, packet);
return 1;
}
newIndex = packet->orderingIndex;
waitingForIndex = &this->waitingForOrderedPacketReadIndex[channel];
if (newIndex != *waitingForIndex) {
/*not yet time to handle this one*/
dprintf("out of order packet\n");
/*do outOfOrderLimit here*/
this->statistics_orderedMessagesOutOfOrder++;
/*ReliabilityLayer__AddToOrderingList*/
thiscall1((void*) 0x45DEE0, this, (int) packet);
return 1;
}
this->statistics_orderedMessagesInOrder++;
Queue_Push_DWORD(&this->outputQueue, &packet);
orderingList = thiscall1((void*) 0x45C4C0, this, channel);
if (orderingList == NULL) {
return 1;
}
OutputNowInOrderPackets(this, orderingList, waitingForIndex);
return 1;
}
static
void HandlePacket(
struct CReliabilityLayer *this,
struct CInternalPacket *packet,
struct CRaknetTimeNS time)
struct CInternalPacket *packet)
{
short holes;
SendAckForPacket(this, packet);
ResetReceivedPackets(this);
holes = packet->messageNumber - this->receivedPacketsBaseIndex;
if (!HandlePacketHole(this, holes, time)) {
return;
}
RemovePacketHolesNotReceivedInTime(this, time);
this->statistics_messagesReceived++;
CompressMessageHoleQueue(this);
/*split packets are dropped, skipping 0x45FECE*/
if (HandleSequencedPacket(this, packet)) {
return;
}
if (HandleOrdenedPacket(this, packet)) {
return;
}
Queue_Push_DWORD(&this->outputQueue, &packet);
// here lol @45FC87
}
__declspec(naked)
@ -325,6 +74,21 @@ __stdcall ReliabilityLayer__CreateInternalPacketFromBitStream(
}
}
static
__declspec(naked)
int __stdcall RangeList__Deserialize(
struct CRangeList *this,
struct CBitStream *bitStream)
{
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45E2D0
jmp eax
}
}
/*ReliabilityLayer__RemovePacketFromResendListAndDeleteOlderReliableSequenced*/
__declspec(naked)
int __stdcall ReliabilityLayer__RemovePacketsConfirmedByAck(
@ -374,7 +138,7 @@ void HandleAcksForMessageRange(
/*messageholelimit checked here?*/
for (msgNum = minMessageNumber; msgNum <= maxMessageNumber; msgNum++) {
for (msgNum = minMessageNumber; msgNum < maxMessageNumber; msgNum++) {
ackedCounter = ReliabilityLayer__RemovePacketsConfirmedByAck(
this,
msgNum,
@ -406,17 +170,17 @@ int HandleAcks(
struct CRangeList incomingAcksList;
struct CRangeNode_Short *ranges;
int amountOfAckRanges, ackRangeIdx;
int numAcks, pos;
int containedValidAcks;
short minMsg, maxMsg;
pos = bitStream->readOffset;
dprintf("reading ackslist, position is %d\n", bitStream->readOffset);
RangeList__ctor(&incomingAcksList);
if (!RangeList__Deserialize(&incomingAcksList, bitStream)) {
dprintf("could not deserialize ackslist\n");
RangeList__dtor(&incomingAcksList);
return 0;
}
dprintf("read acks from %d to %d\n", pos, bitStream->readOffset);
dprintf("position after reading is %d\n", bitStream->readOffset);
amountOfAckRanges = incomingAcksList._._.list_size;
if (amountOfAckRanges == 0) {
@ -425,7 +189,7 @@ int HandleAcks(
return 1;
}
numAcks = 0;
containedValidAcks = 0;
ranges = (struct CRangeNode_Short*) incomingAcksList._._.values;
for (ackRangeIdx = 0; ackRangeIdx < amountOfAckRanges; ackRangeIdx++) {
minMsg = ranges[ackRangeIdx].minIndex;
@ -436,14 +200,14 @@ int HandleAcks(
continue;
}
numAcks += maxMsg - minMsg + 1;
containedValidAcks = 1;
HandleAcksForMessageRange(this, minMsg, maxMsg, timeNS);
/*ackslimit checked here*/
}
RangeList__dtor(&incomingAcksList);
return numAcks > 0;
return containedValidAcks;
}
/**
@ -469,9 +233,6 @@ void AddBitsReceivedStatistic(struct CReliabilityLayer *this, int bits)
}
}
#ifdef CALL_ORIGINAL
__declspec(naked)
#endif
int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
struct CReliabilityLayer *this,
char *buffer,
@ -481,21 +242,11 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
int MTUSize,
int *ptrOutIsPacketFlood)
{
#ifdef CALL_ORIGINAL
_asm {
pop eax
pop ecx
push eax
mov eax, 0x45F7E0
jmp eax
}
#else
struct CInternalPacket *packet;
struct CBitStream bitStream;
struct CRaknetTimeNS timeNS;
char hasAcks, wereAcksHandled;
int returnValue;
int packetCount;
dprintf("HandleSocketReceiveFromConnectedPlayerStart\n");
@ -514,23 +265,20 @@ int __stdcall ReliabilityLayer__HandleSocketReceiveFromConnectedPlayer(
wereAcksHandled = 0;
BitStream__Read(&bitStream, &hasAcks);
if (hasAcks) {
dprintf("has acks\n");
wereAcksHandled = HandleAcks(this, &bitStream, timeNS);
}
returnValue = wereAcksHandled;
packetCount = 0;
while (packet = ReliabilityLayer__CreateInternalPacketFromBitStream(
this, &bitStream, timeNS))
{
returnValue |= 0x10000000;
packetCount++;
HandlePacket(this, packet, timeNS);
returnValue = 1;
HandlePacket(this, packet);
}
this->receivePacketCount++;
BitStream__dtor(&bitStream);
dprintf("HandleSocketReceiveFromConnectedPlayerEnd acks=%d packets=%d\n",
returnValue & 0xFFFFFFF, packetCount);
dprintf("HandleSocketReceiveFromConnectedPlayerEnd\n");
return returnValue;
#endif
}

View File

@ -141,14 +141,6 @@
RelativePath=".\rakpeer.h"
>
</File>
<File
RelativePath=".\rangelist_deserialize.c"
>
</File>
<File
RelativePath=".\rangelist_deserialize.h"
>
</File>
<File
RelativePath=".\reliability.c"
>

View File

@ -1,7 +1,7 @@
/* vim: set filetype=c ts=8 noexpandtab: */
//#define COMPRESS_PRINT
#define COMPRESS_PRINT
#include "common.h"
#include "uncompress.h"