Changes on login sequence? 5018 - Now (5212)

02/05/2010 00:13 Trigorio#1
Hi, I have been on this forum since late 2005 but I've been away for about a year now. I recently came back and wondered what had been changed since then server-client wise. It would be nice if someone could fill me in :)

5018( after blowfish was implented)
Alot of packets must of obviously been changed and some even added, no doubt about that, but how is it with like the Login sequence?
Has anything changed in the Login sequence?
02/06/2010 18:23 gabrola#2
Nope, nothing has changed in the login sequence
02/07/2010 04:09 Trigorio#3
Well there is a "new" password cryptography that you failed to mention about and it looks like 0x43e is a bit changed. I'm going to take a look at it in the morning, going to sleep now..
02/07/2010 05:28 I.M.Real#4
Quote:
Originally Posted by Trigorio View Post
Well there is a "new" password cryptography that you failed to mention about and it looks like 0x43e is a bit changed. I'm going to take a look at it in the morning, going to sleep now..
[Only registered and activated users can see links. Click Here To Register...]
thers Korv's wiki might be some help
the auth server still uses the old keys,then the blowfish-DH starts
there is a padding on the packets tqserver tqclient shit
and some random type garbage that might show up aswell
but now as for A complete list of changes,I dont know when you quit
02/07/2010 06:30 gabrola#5
Quote:
Originally Posted by Trigorio View Post
Well there is a "new" password cryptography that you failed to mention about and it looks like 0x43e is a bit changed. I'm going to take a look at it in the morning, going to sleep now..
Well I never messed with the password at all tbh
02/08/2010 17:18 Trigorio#6
Allright so I got another problem now, I am trying to get my proxy to work with SocksCap so that I can force the connection from the Client to localhost.

This is my Idea:

Client 127.0.0.1 port: 2324(random) -> Proxy 127.0.0.1 port:5555, then process the information to AuthServer so, ExternalIpAddress(81.651.51.23) 2652(random) -> AuthserverIP(Let's say) 56.515.166.41(made up) 9958/9959

Is it right?
02/08/2010 17:40 gabrola#7
Quote:
Originally Posted by Trigorio View Post
Allright so I got another problem now, I am trying to get my proxy to work with SocksCap so that I can force the connection from the Client to localhost.

Let's say I use the port 5555 and localhost for SocksCap settings.

Then I make the proxy listen on port 5555 at localhost. Bingo it opens a connection on port 5555 and then this is were I get stuck. Shouldn't the Client open up a random port on local host that then connects to SocksCap on localhost 5555 that would then process the information to the Proxy? And If so then I have an issue, I can't seem to get the Client to open up a connection :S. Do I have to process something from the authserver to the Client to make it open a connection?

Edit:
This is my idea of it

Client 127.0.0.1 port: 2324(random) -> Proxy 127.0.0.1 port:5555, then process the information to AuthServer so, ExternalIpAddress(81.651.51.23) 2652(random) -> AuthserverIP(Let's say) 56.515.166.41(made up) 9958/9959

So are the ports that I marked as random really random or is there something that decides what they should be?
SocksCap connects using a socks4/5 connection so there's usually extra headers in the packet, the thing to do is that you can hook the connect function in the client and make it connect to the proxy instead, in my proxy here's my hooked function
Code:
int WINAPI __stdcall MyConnect(SOCKET s, const struct sockaddr_in *address, int namelen)
{
    if(address->sin_port == htons(9959))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 9958 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    }
    else if(address->sin_port == htons(5816))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 5816 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    }
    else
    {
	    return OrigConnect(s, address, namelen);
    }
}
Basically if it tries to connect to any host with port 9959 (auth server), it connects to my proxy on port 9958 (the port that handles auth server requests) and if tries to connect to any host with port 5816 (game server) it connects to my proxy on port 5816.
Current auth server my proxy connects to is 208.96.34.46 : 9959
To get the game server ip you either get it from the authentication reply from the auth server or from the server.dat file.
02/08/2010 18:09 Trigorio#8
Quote:
Originally Posted by gabrola View Post
SocksCap connects using a socks4/5 connection so there's usually extra headers in the packet, the thing to do is that you can hook the connect function in the client and make it connect to the proxy instead, in my proxy here's my hooked function
Code:
int WINAPI __stdcall MyConnect(SOCKET s, const struct sockaddr_in *address, int namelen)
{
    if(address->sin_port == htons(9959))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 9958 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    }
    else if(address->sin_port == htons(5816))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 5816 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    }
    else
    {
	    return OrigConnect(s, address, namelen);
    }
}
Basically if it tries to connect to any host with port 9959 (auth server), it connects to my proxy on port 9958 (the port that handles auth server requests) and if tries to connect to any host with port 5816 (game server) it connects to my proxy on port 5816.
Current auth server my proxy connects to is 208.96.34.46 : 9959
To get the game server ip you either get it from the authentication reply from the auth server or from the server.dat file.
Nice, what if I just want to use SocksCap, I could make it connect to port 5555, have a method in my Proxy that would reply to the client until the client sends the login 0x43e packet and process the packet to the Auth server at port 9959. Then I should recieve the Auth response 0x41f packet and I can read the IP and Port and proceed to connect to the Client?

Edit: God damn your way is waaaaayy better...

My concerns are can TQ Patch your method?

I mean in the long run, Sockscap or hooking to connect function?
02/08/2010 20:21 gabrola#9
Quote:
Originally Posted by Trigorio View Post
Nice, what if I just want to use SocksCap, I could make it connect to port 5555, have a method in my Proxy that would reply to the client until the client sends the login 0x43e packet and process the packet to the Auth server at port 9959. Then I should recieve the Auth response 0x41f packet and I can read the IP and Port and proceed to connect to the Client?

Edit: God damn your way is waaaaayy better...

My concerns are can TQ Patch your method?

I mean in the long run, Sockscap or hooking to connect function?
Well I hook the connect function by having the injected dll search for the address of the function so basically the dll should work on all patches, that's the function that gets the address

Code:
GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect")
The Bloodshed Dev C++ project is attached if you want to change the ports you want to use.
So in conclusion, it's much more efficient and convenient to use the hooking method while also it being patch proof.
02/08/2010 23:32 Trigorio#10
Nvm, unnecessary question.

But I get address 1906985479. Is that correct?
If I call MyConnect function once, then it should hook on WS2_32.DLL, force it to redirect all 9958 and 5816 port connections to the desired ports/ IP that I've set in the MyConnect function.

Also the best part is, this doesn't even touch Conquer at all, basicly no TOS Violations.

If I said something incorrect, then please do correct me, thanks :)
02/09/2010 00:43 gabrola#11
Well you don't call MyConnect what you do is hook the function so when conquer calls connect, it calls MyConnect instead so what you need to do is that once the dll is injected you used the APIHook function to hook the connect function like this

Code:
APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
or here's the whole bunch of code even though I attached the files.

Code:
//Needs -lws2_32 linker argument
#pragma comment(lib, "libws2_32.a")

#define	HAWK_WIN32
#define  LOGFILE "hook.log"
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <process.h>

typedef SOCKET (WINAPI *PSOCKET)(int af, int type, int protocol);
typedef int (WINAPI *PCONNECT)(SOCKET s, const struct sockaddr_in *address, int namelen);

PSOCKET  OrigSocket;
PCONNECT OrigConnect;

SYSTEMTIME st;
int conch; //0 = free, 1 = connect has it, 2 = send has it, 3 = recv has it
//4 = WSASend has it, 5 = WSARecv has it

void MessageFunc(void *msgbuf)
{
	#if defined(HAWK_WIN32)
	MessageBox(NULL, msgbuf, "Message", 0);
	#elif defined(HAWK_CONSOLE)
	printf("%s\n", msgbuf);
	#endif
}

//===========================CONNECT===========================
int WINAPI __stdcall MyConnect(SOCKET s, const struct sockaddr_in *address, int namelen)
{
    if(address->sin_port == htons(9959))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 9958 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    } else if(address->sin_port == htons(5816))
    {
        struct sockaddr_in clientService; 
        clientService.sin_family = AF_INET;
        clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );
        clientService.sin_port = htons( 5816 );
        return OrigConnect(s, &clientService, sizeof(clientService));
    }
    else
    {
	    return OrigConnect(s, address, namelen);
    }
}

DWORD APIHook(DWORD HookFunc, DWORD MyFunc, DWORD OrigFunc)
{
	unsigned char NewData[5], DetourJump[5], OldData[5];
	DWORD OldProtect;
	int i;
	unsigned char* HookFuncPtr = (unsigned char*) HookFunc;
	unsigned char* HookDetour = (unsigned char*) malloc(25);
	for(i = 0; i < 25; i++)
		HookDetour[i] = 0x90; //NOP
	NewData[0] = 0xE9; //JMP (near)
	*(PDWORD)&NewData[1] = (DWORD)((DWORD)MyFunc - ((DWORD)HookFunc + 5));
	DetourJump[0] = 0xE9;
	*(PDWORD)&DetourJump[1] = (DWORD)((DWORD)HookFunc - ((DWORD)HookDetour + 14 + 5));
	VirtualProtectEx(GetCurrentProcess(), (void*)HookFunc, 10, PAGE_EXECUTE_WRITECOPY, &OldProtect);
	for(i = 0; i < 5; i++)
	{
		OldData[i] = HookFuncPtr[i];
		HookFuncPtr[i] = NewData[i];
	}
	VirtualProtectEx(GetCurrentProcess(), (void*)HookFunc, 10, OldProtect, NULL);
	VirtualProtectEx(GetCurrentProcess(), (void*)HookDetour, 25, PAGE_EXECUTE_WRITECOPY, &OldProtect);
	for(i = 0; i < 5; i++)
		HookDetour[i] = OldData[i];
	HookDetour[24-5] = DetourJump[0];
	HookDetour[24-4] = DetourJump[1];
	HookDetour[24-3] = DetourJump[2];
	HookDetour[24-2] = DetourJump[3];
	HookDetour[24-1] = DetourJump[4];
	HookDetour[24] = 0xC3; //RET
	VirtualProtectEx(GetCurrentProcess(), (void*)HookDetour, 25, OldProtect, NULL);
	OrigFunc = (DWORD)HookDetour;
	return OrigFunc;
}

DWORD WINAPI Inject(HINSTANCE hInst /*LPVOID lparam*/)
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(1,1), &wsaData);
	//Create log file, existing log files will be deleted automatically with CREATE_ALWAYS
	HANDLE hdn = CreateFile(LOGFILE, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	CloseHandle(hdn);
	*(PDWORD)&OrigConnect = APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
	//FreeLibraryAndExitThread(hInst, 0);
}

BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
	switch(reason)
	{
		case DLL_PROCESS_ATTACH:
			Inject(hInst);
			break;
		default:
			break;
	}
	return TRUE;
}
02/09/2010 01:54 Trigorio#12
Yeah that is what I thought of in the begining. Isn't it the same using Winject to inject the dll?

But Winject didn't work so I thought that the APIHook shouldn't work either.

Also doesn't this function do the same as Winject would do?
Code:
DWORD WINAPI Inject(HINSTANCE hInst /*LPVOID lparam*/)
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(1,1), &wsaData);
	//Create log file, existing log files will be deleted automatically with CREATE_ALWAYS
	HANDLE hdn = CreateFile(LOGFILE, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	CloseHandle(hdn);
	*(PDWORD)&OrigConnect = APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
	//FreeLibraryAndExitThread(hInst, 0);
}
Is there something not working with the Inject function? Because Conquer crashes when pressing on Login after injecting the DLL.

Could we talk on msn? If so PM me your mail. Thanks!

Edit: This would be alot easier if I was using c++, but I am pInvoking this for c#
02/09/2010 05:59 Nullable#13
Quote:
Originally Posted by Trigorio View Post
Yeah that is what I thought of in the begining. Isn't it the same using Winject to inject the dll?

But Winject didn't work so I thought that the APIHook shouldn't work either.

Also doesn't this function do the same as Winject would do?
Code:
DWORD WINAPI Inject(HINSTANCE hInst /*LPVOID lparam*/)
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(1,1), &wsaData);
	//Create log file, existing log files will be deleted automatically with CREATE_ALWAYS
	HANDLE hdn = CreateFile(LOGFILE, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	CloseHandle(hdn);
	*(PDWORD)&OrigConnect = APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
	//FreeLibraryAndExitThread(hInst, 0);
}
Is there something not working with the Inject function? Because Conquer crashes when pressing on Login after injecting the DLL.

Could we talk on msn? If so PM me your mail. Thanks!

Edit: This would be alot easier if I was using c++, but I am pInvoking this for c#
If i had enough time to work on this.. anyhow in addition to Gabrola's technique (and since you are pinvoking to C#) you can:
1- Allocate space in conquer's p-memory
2- Write your delegate pointer to the allocated space ( Marshal.GetFunctionPointerForDelegate(Delegate d); )
3- Add some JMPs, OpenProcess, CreateRemoteThread and other win api used to call the delegate so that when conquer calls connect, your delegate gets called instead.
hope this helps.
UPDATE: by the way, the function doesn't do the same as Winject, this is basically a 'Thread' not a function to inject the dll
Mfg,
Nullable.
02/09/2010 15:20 gabrola#14
Quote:
Originally Posted by Trigorio View Post
Yeah that is what I thought of in the begining. Isn't it the same using Winject to inject the dll?

But Winject didn't work so I thought that the APIHook shouldn't work either.

Also doesn't this function do the same as Winject would do?
Code:
DWORD WINAPI Inject(HINSTANCE hInst /*LPVOID lparam*/)
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(1,1), &wsaData);
	//Create log file, existing log files will be deleted automatically with CREATE_ALWAYS
	HANDLE hdn = CreateFile(LOGFILE, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	CloseHandle(hdn);
	*(PDWORD)&OrigConnect = APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
	//FreeLibraryAndExitThread(hInst, 0);
}
Is there something not working with the Inject function? Because Conquer crashes when pressing on Login after injecting the DLL.

Could we talk on msn? If so PM me your mail. Thanks!

Edit: This would be alot easier if I was using c++, but I am pInvoking this for c#
No no no, you got it all wrong, Inject is supposed to be called when the DLL is injected, it doesn't inject it.
02/09/2010 19:22 Trigorio#15
Ah ok. I am going to use the COM Interop method to call the function Inject(); in C#. I am also going to see if I can put something together in C# that would inject the dll, so that I don't have to use winject for that.

Code:
DWORD WINAPI Inject()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(1,1), &wsaData);
	*(PDWORD)&OrigConnect = APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
}
Edit:
Hey do you know what this would correspond to in C#?

Code:
*(PDWORD)&OrigConnect = APIHook(
The first part. Also is PDWORD a uint just like DWORD in c#?
Just trying to understand the code better. Not that familar with C++ xD
Damn the code confuses me abit.. The function for APIHook has 3 arguments, (In C#) (UInt HookFunc, UInt MyFunc, UInt OrigFunc).
When this is called
Code:
 APIHook((DWORD)GetProcAddress(GetModuleHandle("Ws2_32.dll"), "connect"), (DWORD)MyConnect, (DWORD)OrigConnect);
It declares a value for argument HookFunc, but when does it declare a value for MyFunc(MyConnect) or a value for OrigFunc(OrigConnect)?