EMO Style ForumPro - Hos Geldiniz
Giriş yap

Şifremi unuttum

Istatistikler
Toplam 202 kayıtlı kullanıcımız var
Son kaydolan kullanıcımız: AnthonyFurey3

Kullanıcılarımız toplam 1186 mesaj attılar bunda 862 konu
Tarıyıcı
 Kapı
 Indeks
 Üye Listesi
 Profil
 SSS
 Arama
Arama
 
 

Sonuç :
 


Rechercher çıkıntı araştırma

RSS akısı


Yahoo! 
MSN 
AOL 
Netvibes 
Bloglines 


Kimler hatta?
Toplam 4 kullanıcı online :: 0 Kayıtlı, 0 Gizli ve 4 Misafir :: 1 Arama motorları

Yok

[ Bütün listeye bak ]


Sitede bugüne kadar en çok 92 kişi Paz Ağus. 28, 2016 6:58 am tarihinde online oldu.
En son konular
» İnternetten Para Kazandıran Oyun ! Ödeme Alt Limiti Yok ! DEV KONU
Cuma Ağus. 29, 2014 8:33 am tarafından Hello EMO

» goldenchase.net maden yaparak para kazanma
Cuma Ağus. 29, 2014 8:18 am tarafından Hello EMO

» etichal hacker görsel egitim seti
Çarş. Ağus. 06, 2014 4:57 am tarafından Hello EMO

» KO TBL Source C#
Ptsi Ara. 09, 2013 6:36 am tarafından Hello EMO

» x86 Registers
C.tesi Ağus. 24, 2013 5:02 am tarafından Hello EMO

» [Tutorial] Pegando Address, Pointers de WYD
Çarş. Tem. 10, 2013 7:25 am tarafından Hello EMO

» [Tutorial] Pegando Address, Pointers de CS Metodo²
Çarş. Tem. 10, 2013 7:23 am tarafından Hello EMO

» [Tutorial] Aprendendo basico deASM OLLYDBG
Çarş. Tem. 10, 2013 7:22 am tarafından Hello EMO

» Basic C# DLL injector
Ptsi Tem. 08, 2013 7:48 am tarafından Hello EMO

Reklam

[Guide] Client Based Packet Injection in Silkroad

Önceki başlık Sonraki başlık Aşağa gitmek

[Guide] Client Based Packet Injection in Silkroad

Mesaj tarafından Hello EMO Bir Ptsi Tem. 08, 2013 5:04 am

pushedx demiş ki:This article is a special one! Thanks to clockwork for letting me share some knowledge I learned from him in the past. This information is still relevant and useful for Silkroad, but as I will write about, might be too much work for the benefits.

[SIZE="5"]Client Based Packet Injection in Silkroad[/SIZE]

[SIZE="4"]I. Purpose[/SIZE]

Welcome to the fourth guide in my series! I would like to take this time to thank clockwork for allowing me to write a guide based on his approach for performing client based packet injections in Silkroad. This is an approach he came up with a number of years ago and it was used ever since in 0x33’s programs. The purpose of this guide is to show how to accomplish a creative yet simple approach to being able to inject packets from the client to the server using the client’s existing functions.

While the goal of this guide is to educate users on how this task was accomplished, I am not writing this guide solely so you can use it in your own programs. The method itself is very creative and works, but it is extremely limited and highly dependent on the client, which can be a good thing and a bad thing. While it certainly is one of the safest ways to go about injecting packets that always have the right security, I think using a proxy server is the better approach to take to complete control over the packet flow into and out of the client. I will cover that technique in a later guide, but for now I am glad to be able to share this method with anyone who is interested in it.

[SIZE="4"]II. Requirements[/SIZE]

This guide, just like the last, might be a little advanced for most readers at this stage again. I will try to make things as clear as possible and write towards an intermediate level, but some of the concepts used here just take time and experience to understand over a longer term. Some of the concepts here might also seem like they are not greatly explained either. This might be because this approach is being presented more for the educational value of knowing how it works rather than the benefits of being able to use it in your own programs. I think it would be more worth while to invest into a more powerful solution than can be accomplished easily using this method.

In order to be able to follow along this guide, you will need:
• OllyDbg 1.10 (or equivalent)
• Visual Studio 2008 (or equivalent)

Before you continue this guide, you will also need to have already read and understood the three previous guides! All of the guides build on one another in some shape or form, so it’s most beneficial to have read them all by now.

[SIZE="4"]III. Theory[/SIZE]

After we get our own DLL into a process, we might think to ourselves, “How can we send packets to the server?” Naturally, we might think we could make the client do the work for us and rightfully so since that’s the job of the client. However, actually coming up with a solution to accomplish this can be tricky. This is because the client is huge, there is a lot of code to go through and we will not even be able to trace through even a minor percentage of it. 

So, how do we stumble upon a solution like the one that is presented in this guide? Experience, intuition, and a whole lot of luck! I’ve noticed personally a lot of the things I’ve found in the client and have made use of were stumbled upon by chance. I was looking for something specific and was off target but instead found something more interesting instead. While I don’t know the original thought process that was used to come up with this method, you can be sure that it is not something that you can just look at code and do; it takes time.

If we think about the game client and how it works, the process might look something like this:
1. User interacts with the game client via mouse/keyboard.
2. Client processes input and determines what data to send the server.
3. Client formats data to send and applies any security packaging and finally sends it.

Naturally, we might want to just go to step 3 and figure out that process so we can inject packets manually. However, this is not always so easy, especially when the client has packet security like Silkroad does. In fact, trying to come up with our own packet injecting solution that does all the work might be infeasible.

As a result, we have to think of other methods of accomplishing the task. What if we were able to fake the step 1? In that case, we could get the client to send data, but it would be a packet based on whatever we were faking. Not entirely useful, but it is definitely a start.

What if we were able to fake step 1, and then modify step 2 a little to use our own data rather than the client data? In that case, the game client would then execute step 3 which it assumes is valid data and would take care of everything for us. That is what this client based injection process does. It simulates step 1 to get the client to send a packet, it then modifies the contents of that packet, and finally it lets the client take care of everything else.

As a result, packet security can be ignored as the client will always create the correct security information for the data. If the security process were to change, then everything would still be fine as the client would have been updated to accommodate that. In theory, it really is a nice idea. However, as mentioned earlier in this section, being able to come up with such a solution is not easy or even trivial. 

It really takes a lot of work, so it might not be practical to try on a new game. Trying to call functions in a client out of order is a really tricky process and there is a lot of things you have to take into considerations. Despite all of these obstacles, we still have a method available to us to use with Silkroad, so we can now get into the actual implementation of it.

[SIZE="4"]IV. Implementation[/SIZE]

Like the previous guide, the code for this guide will be placed at the end in a complete form so you have a compliable version. The code snippets shown will not be in order and a few things might be left out. This is done to try and make the guide more readable as trying to explain the code section by section can get tricky.

To get started, we will be reusing our WndProc codecave from the previous guide, Integrating AntTweakBar into Silkroad. We will be making a few modifications though. First, we will no longer be using AntTweakBar in the example so we need to clear out that logic. In addiction, I’ve changed a few minor things in how we use the codecave. Rather than placing the specific code in the UserOnInject, we now call a Setup function. Since there is nothing really new here, you can see the final code in the final code listing.

To create our GUI in Visual Studio, we will need to do the following:
1. Right click on the Resource Files folder in the Solution Explorer for the DLL project and choose Add -> Resource.
2. In the new Add Resource Dialog that pops up, highlight Dialog and press New.
3. Now that we have a new dialog, we need to change a few settings. Right click on the dialog in the form editor and choose Properties.
4. In the Properties Bar, change “Border” to “Thin”.
5. Next, change “Minimize Box” to “True”.
6. Finally, change “Visible” to “True”.
7. Save the current changes.

With our GUI made, we can now add a test button to drive our program. Click on the Toolbox window tab in Visual Studio to bring up a bar of components we can add to our dialog. Click on the Button component and click once on the dialog to place it. Right click on the button and choose properties. Change the “Caption” to “Sit” and hit enter in the field to update the value. We have two existing buttons on our dialog that we do not need. Select the “OK” and “Cancel” buttons and press delete to remove them from the form. Save again. Here is a screenshot of how the GUI looks for me.


Switch back to your DLL.cpp file so we can resume working with code. At this point, we need to add in the code for our GUI. If you have never done any Win32 GUI programming before, then I would suggest you Google some simple tutorials to get a feel for it. What will follow next is the GUI code; there is not much that needs to be explained here. There is one section that we have not gone over yet, but we will be getting to that soon. Here is the code:

Kod:
namespace Win32Gui
{
   INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   {
      switch(uMsg) 
      {
         case WM_INITDIALOG:
         {
         }
         break;

         case WM_COMMAND:
         {
            int button = LOWORD(wParam);
            switch(button)
            {
               case IDCANCEL:
               {
                  PostQuitMessage(0);
               } break;

               case IDC_BUTTON1:
               {
                  Packet::TPacket * sitPacket = new Packet::TPacket;
                  sitPacket->size = 1;
                  sitPacket->opcode = 0x7017;
                  sitPacket->data[0] = 0x04;
                  Packet::SendPacket(sitPacket);
               } break;
            }
         } break;

         default:
         {
            return FALSE;
         }
      }
      return TRUE;
   }

   DWORD WINAPI GuiThread(LPVOID lpParam)
   {
      HWND hwnd = CreateDialog(gInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
      MSG Msg = {0};
      while(GetMessage(&Msg, NULL, 0, 0) > 0)
      {
         if(!IsDialogMessage(hwnd, &Msg))
         {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
         }
      }
      return 0;
   }

   void Setup()
   {
      CreateThread(0, 0, GuiThread, 0, 0, 0);
   }
}

The reason we have our code setup this way is because we want our own GUI to run in a different thread than the main Silkroad thread. The reason for this is because if our GUI stalls or takes a while to process, the game is not affected. If we were to tie our GUI logic into the main Silkroad thread, which is possible, we can adversely affect the game. 

Next, I am going to skip slightly out of order and cover the higher level packet sending functionality that we will be using. The reason we need this functionality is because our GUI thread runs in a separate thread from the main client. As a result, if we were to simply inject packets from the second thread we would most likely crash our client or cause corruption and disconnect.

In order to implement a multithreaded safe solution, we must use a critical section to lock our data so threads can access the data in a serial form and not have any issues of overlapping each other and messing things up. Here is the code:

Kod:
namespace Packet
{
   struct TPacket
   {
      WORD size;
      WORD opcode;
      BYTE data[4096];
   };

   CRITICAL_SECTION cs = {0};
   TPacket * packetQueue[32] = {0};
   int packetQueueIndex = 0;

   void Setup()
   {
      InitializeCriticalSection(&cs);
   }

   void SendPacket(TPacket * p)
   {
      EnterCriticalSection(&cs);
      packetQueue[packetQueueIndex++] = p;
      if(packetQueueIndex >= 32)
         packetQueueIndex = 0;
      LeaveCriticalSection(&cs);
   }

   TPacket * GetNextPacket()
   {
      TPacket * p = 0;
      EnterCriticalSection(&cs);
      for(int x = 0; x < 32; ++x)
      {
         if(packetQueue[x])
         {
            p = packetQueue[x];
            packetQueue[x] = 0;
            break;
         }
      }
      LeaveCriticalSection(&cs);
      return p;
   }
}

Rather than using a vector, a list, or a queue, I opted to just do it the old fashion way because of how some troubles can arise when using those containers in a DLL that is used the way ours is setup. I noticed my overall code was crashing the Visual Studio linker often, so I’m not sure if I have memory corrupted on my system or the code just breaks the linker.

Finally we can get to the good stuff. What I will cover next is the client based injection approach clockwork came up with and what was used for a while in our programs. I will post the code and then start explaining what the comments don’t. Here it is:

Kod:
namespace CC_InjectPacket
{
   // The location of the hook
   // Binary Search pattern for Olly: 8B 11 8B 42 2C 57 
   // MOV EDX,[ECX]
   // MOV EAX,[EDX+2C] <- Patch
   // PUSH EDI
   #define SEND_HOOK 0x7418A2

   // The location of our packet sending code
   // Binary Search pattern for Olly: 00 75 0C 6A 04
   // PUSH 4
   // MOV ECX,00B36D5C <- SEND_ECX
   // CALL 006168B0 <- SEND_CALL
   #define SEND_ECX 0xD3B8E4
   #define SEND_CALL 0x7215E0

   // Holds the final bytes for the codecave
   BYTE toggleOn[6];

   // Holds the original bytes for the codecave
   BYTE toggleOff[6];

   // Data to be sent is stored in a static location so
   // we can access it easily from our codecave  
   char sendbuffer[8192] = {0};

   void Format(LPBYTE _edi)
   {
      // This function is called from our hook in the send procedure
      // and replaces the original packet data with our own

      LPBYTE pdata = _edi;   // packet struct
      pdata += 0x34;   // point to data

      // Read size from our sendbuffer
      WORD size = 0;
      memcpy((LPVOID)&size, sendbuffer, 2);
      size += 6;

      // Overwrite data in packet struct with data from sendbuffer
      memcpy(pdata, (LPVOID)&sendbuffer, size);
   }

   DWORD sendhook_retAddr1 = 0;
   __declspec(naked) void codecave_sendhook()
   {
      __asm 
      {
         pop sendhook_retAddr1
         mov eax,[edx + 0x2C] // original command from client
         pushad
         push edi      // packet struct
         call Format
         add esp, 4
         popad 
         push edi      // packet struct
         call eax      // finish client's send
         push sendhook_retAddr1
         ret
      }
   }

   // Sends a packet to the game server.
   void SendPacketRaw(WORD size, WORD opcode, LPBYTE data)
   {
      size += 6;
      memcpy(sendbuffer + 0, &size, 2);
      memcpy(sendbuffer + 2, &opcode, 2);
      sendbuffer[4] = 0;
      sendbuffer[5] = 0;
      memcpy(sendbuffer + 6, data, size - 6);

      // For debugging purposes
      for(int x = 0; x < size; ++x)
         printf("%.2X ", sendbuffer[x]);
      printf("\n");

      // Write out the codecave
      edx::WriteBytes(SEND_HOOK, toggleOn, 6);

      // Invoke a packet send
      __asm
      {
         push 4
         mov ecx, SEND_ECX
         mov eax, SEND_CALL
         call eax
      }

      // Restore original bytes
      edx::WriteBytes(SEND_HOOK, toggleOff, 6);
   }

   void Setup()
   {
      // Store the original client code
      edx::ReadBytes(SEND_HOOK, toggleOff, 6);

      // Write out the codecave and save the new code
      edx::CreateCodeCave(SEND_HOOK, 6, codecave_sendhook);
      edx::ReadBytes(SEND_HOOK, toggleOn, 6);

      // Restore the old code
      edx::WriteBytes(SEND_HOOK, toggleOff, 6);

      // For debugging purposes
      printf("Toggle On: ");
      for(int x = 0; x < 6; ++x)
         printf("%.2X ", toggleOn[x]);
      printf("\n");

      // For debugging purposes
      printf("Toggle Off: ");
      for(int x = 0; x < 6; ++x)
         printf("%.2X ", toggleOff[x]);
      printf("\n");
   }
}

That’s quite a big chunk of code, so I’ll try to go slow and cover everything. As explained in the theory section, we will want to trigger a packet to be sent by the client. In order to do this, we have to find 2 separate locations. First we need to find the packet sending call itself and the associated data pointer for it and then we have to find the location of the trigger function we are going to be using.

How do we find the trigger function? We can use the binary code snippet shown in OllyDbg to track down the location. How do we know this won’t change anytime soon? Well, that comment is from 2007, so I think we are pretty good for a while. Wink The function that was hooked was the function used during the character command actions, such as when you sit/stand. 

Once we have that trigger function and the associated data pointer, we can next find the location of the packet sending code. We can use the second binary snippet to do this. If we look above the code a little we will see the line, 0074182F                         |.  68 B0F9C400        PUSH sro_clie.00C4F9B0                   ;  UNICODE "(%03d) Message : 0x%04x". This line is actually a debug message that the client is set to not execute, but we could actually make the client show all of the opcodes it sends if we made the right changes!

Once we have our locations tracked down, we can move into the specific workings of the method. We want to simply perform a Kansas City Shuffle on the client. We make the client think we executed an action command. As a result, it sets up the packet and then goes to send it. However, when it does that, we quickly change the contents of the packet so it’s our own packet rather than the one the client build. As a result, the client performs the necessary security processing on the packet and dispatches it without even knowing we pulled a quick one on it.

The reason we have to toggle our codecave bytes is because we want the client to be able to send regularly, so only when we trigger the packet sending function does we want to hook the send call and change the contents. That’s all there is to it! It is a very creative approach and a lot easier to implement than trying to reconstruct a new packet sending function from scratch.

I am not going to paste the code for our new UserOnWndProc and UserOnInject functions because those will be in the final code listing. Aside from those two functions, we have everything we need to handle packet injection via the client. Here is our final DLL.cpp file:

Kod:
#include <windows.h>
#include "../common/common.h"
#include "resource.h"

// Global instance handle to this DLL
HMODULE gInstance = NULL;

// Function prototype
void UserOnInject();

// Main DLL entry point
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ulReason, LPVOID lpReserved)
{
   UNREFERENCED_PARAMETER(lpReserved);
   if(ulReason == DLL_PROCESS_ATTACH)
   {
      gInstance = hModule;
      // Do not notify this DLL of thread based events
      DisableThreadLibraryCalls(hModule);
   }
   return TRUE;
}

// This is the main function that is called when the DLL is injected into the process
extern "C" __declspec(dllexport) void OnInject(DWORD address, LPDWORD bytes)
{
   // Restore the original bytes at the OEP
   DWORD wrote = 0;
   WriteProcessMemory(GetCurrentProcess(), UlongToPtr(address), bytes, 6, &wrote);

   // Call our user function to keep this function clean
   UserOnInject();
}

//------------------------------------------------------------------------

struct tSilkroadWndProc
{
   HWND hWnd;
   UINT message;
   WPARAM wParam;
   LPARAM lParam;
};

tSilkroadWndProc SilkroadWndProc = {0};

DWORD UserOnWndProc();

namespace CC_WndProc
{
   DWORD codecave_WndProc_ReturnAddress = 0;
   DWORD codecave_WndProc_esp = 0;
   DWORD codecave_WndProc_result = 0;

   void OnWndProc()
   {
      memcpy(&SilkroadWndProc, ((LPBYTE)ULongToPtr(codecave_WndProc_esp)) + 4, 16);
      codecave_WndProc_result = UserOnWndProc();
   }

   __declspec(naked) void codecave_WndProc()
   {
      __asm pop codecave_WndProc_ReturnAddress
      __asm mov codecave_WndProc_esp, esp
      __asm pushad
      OnWndProc();
      __asm cmp codecave_WndProc_result, 0
      __asm jne LABEL_1
      __asm popad
      __asm xor EAX, EAX
      __asm ret 0x10
LABEL_1:
      __asm popad
      __asm CMP EAX, 0x496
      __asm push codecave_WndProc_ReturnAddress
      __asm ret
   }

   void Setup()
   {
      edx::CreateCodeCave(0x7324F4, 5, CC_WndProc::codecave_WndProc);
   }
}

//------------------------------------------------------------------------

namespace CC_InjectPacket
{
   // The location of the hook
   // Binary Search pattern for Olly: 8B 11 8B 42 2C 57 
   // MOV EDX,[ECX]
   // MOV EAX,[EDX+2C] <- Patch
   // PUSH EDI
   #define SEND_HOOK 0x7418A2

   // The location of our packet sending code
   // Binary Search pattern for Olly: 00 75 0C 6A 04
   // PUSH 4
   // MOV ECX,00B36D5C <- SEND_ECX
   // CALL 006168B0 <- SEND_CALL
   #define SEND_ECX 0xD3B8E4
   #define SEND_CALL 0x7215E0

   // Holds the final bytes for the codecave
   BYTE toggleOn[6];

   // Holds the original bytes for the codecave
   BYTE toggleOff[6];

   // Data to be sent is stored in a static location so
   // we can access it easily from our codecave  
   char sendbuffer[8192] = {0};

   void Format(LPBYTE _edi)
   {
      // This function is called from our hook in the send procedure
      // and replaces the original packet data with our own

      LPBYTE pdata = _edi;   // packet struct
      pdata += 0x34;   // point to data

      // Read size from our sendbuffer
      WORD size = 0;
      memcpy((LPVOID)&size, sendbuffer, 2);
      size += 6;

      // Overwrite data in packet struct with data from sendbuffer
      memcpy(pdata, (LPVOID)&sendbuffer, size);
   }

   DWORD sendhook_retAddr1 = 0;
   __declspec(naked) void codecave_sendhook()
   {
      __asm 
      {
         pop sendhook_retAddr1
         mov eax,[edx + 0x2C] // original command from client
         pushad
         push edi      // packet struct
         call Format
         add esp, 4
         popad 
         push edi      // packet struct
         call eax      // finish client's send
         push sendhook_retAddr1
         ret
      }
   }

   // Sends a packet to the game server.
   void SendPacketRaw(WORD size, WORD opcode, LPBYTE data)
   {
      size += 6;
      memcpy(sendbuffer + 0, &size, 2);
      memcpy(sendbuffer + 2, &opcode, 2);
      sendbuffer[4] = 0;
      sendbuffer[5] = 0;
      memcpy(sendbuffer + 6, data, size - 6);

      // For debugging purposes
      for(int x = 0; x < size; ++x)
         printf("%.2X ", sendbuffer[x]);
      printf("\n");

      // Write out the codecave
      edx::WriteBytes(SEND_HOOK, toggleOn, 6);

      // Invoke a packet send
      __asm
      {
         push 4
         mov ecx, SEND_ECX
         mov eax, SEND_CALL
         call eax
      }

      // Restore original bytes
      edx::WriteBytes(SEND_HOOK, toggleOff, 6);
   }

   void Setup()
   {
      // Store the original client code
      edx::ReadBytes(SEND_HOOK, toggleOff, 6);

      // Write out the codecave and save the new code
      edx::CreateCodeCave(SEND_HOOK, 6, codecave_sendhook);
      edx::ReadBytes(SEND_HOOK, toggleOn, 6);

      // Restore the old code
      edx::WriteBytes(SEND_HOOK, toggleOff, 6);

      // For debugging purposes
      printf("Toggle On: ");
      for(int x = 0; x < 6; ++x)
         printf("%.2X ", toggleOn[x]);
      printf("\n");

      // For debugging purposes
      printf("Toggle Off: ");
      for(int x = 0; x < 6; ++x)
         printf("%.2X ", toggleOff[x]);
      printf("\n");
   }
}

//------------------------------------------------------------------------

namespace Packet
{
   struct TPacket
   {
      WORD size;
      WORD opcode;
      BYTE data[4096];
   };

   CRITICAL_SECTION cs = {0};
   TPacket * packetQueue[32] = {0};
   int packetQueueIndex = 0;

   void Setup()
   {
      InitializeCriticalSection(&cs);
   }

   void SendPacket(TPacket * p)
   {
      EnterCriticalSection(&cs);
      packetQueue[packetQueueIndex++] = p;
      if(packetQueueIndex >= 32)
         packetQueueIndex = 0;
      LeaveCriticalSection(&cs);
   }

   TPacket * GetNextPacket()
   {
      TPacket * p = 0;
      EnterCriticalSection(&cs);
      for(int x = 0; x < 32; ++x)
      {
         if(packetQueue[x])
         {
            p = packetQueue[x];
            packetQueue[x] = 0;
            break;
         }
      }
      LeaveCriticalSection(&cs);
      return p;
   }
}

//------------------------------------------------------------------------

namespace Win32Gui
{
   INT_PTR CALLBACK DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   {
      switch(uMsg) 
      {
         case WM_INITDIALOG:
         {
         }
         break;

         case WM_COMMAND:
         {
            int button = LOWORD(wParam);
            switch(button)
            {
               case IDCANCEL:
               {
                  PostQuitMessage(0);
               } break;

               case IDC_BUTTON1:
               {
                  Packet::TPacket * sitPacket = new Packet::TPacket;
                  sitPacket->size = 1;
                  sitPacket->opcode = 0x7017;
                  sitPacket->data[0] = 0x04;
                  Packet::SendPacket(sitPacket);
               } break;
            }
         } break;

         default:
         {
            return FALSE;
         }
      }
      return TRUE;
   }

   DWORD WINAPI GuiThread(LPVOID lpParam)
   {
      HWND hwnd = CreateDialog(gInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
      MSG Msg = {0};
      while(GetMessage(&Msg, NULL, 0, 0) > 0)
      {
         if(!IsDialogMessage(hwnd, &Msg))
         {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
         }
      }
      return 0;
   }

   void Setup()
   {
      CreateThread(0, 0, GuiThread, 0, 0, 0);
   }
}

//------------------------------------------------------------------------

// The function where we place all our logic
void UserOnInject()
{
   // Create a debugging console
   edx::CreateConsole("SilkroadFramework Debugging Console");

   // Mutex for the launcher, no patches required to start Silkroad now
   CreateMutexA(0, 0, "Silkroad Online Launcher");
   CreateMutexA(0, 0, "Ready");

   CC_WndProc::Setup();
   CC_InjectPacket::Setup();
   Packet::Setup();
   Win32Gui::Setup();
}

// User function called on the WndProc
DWORD UserOnWndProc()
{
   static int MYTIMERID = 777;

   if(SilkroadWndProc.message == WM_CREATE)
   {
      // Attach a timer to our main window
      SetTimer(SilkroadWndProc.hWnd, MYTIMERID, 250, 0);
   }

   // If a timer triggers
   if(SilkroadWndProc.message == WM_TIMER)
   {
      // Check to see if it is ours
      if(SilkroadWndProc.wParam == MYTIMERID)
      {
         Packet::TPacket * p = Packet::GetNextPacket();
         while(p)
         {
            CC_InjectPacket::SendPacketRaw(p->size, p->opcode, p->data);
            delete p;
            p = Packet::GetNextPacket();
         }
         return 0;
      }
   }
   return 1;
}

And that’s all there is to it! We should be able to compile and run to start Silkroad and once we are in game, be able to click the Sit button to make the character sit and stand. It is nothing specular, but having this ability a few years back when there was no information like there is today made it great! Smile

[SIZE="4"]V. Conclusion[/SIZE]

Hopefully by now, you have a good idea of one way you can injects packets from the client to the server while in the client itself. As mentioned before, this approach does work out, but it is not the most ideal method nowadays. It is client dependent, subject to possible stability problems, and you have to take into consideration multithreaded issues if you do not inject packets while inside the main Silkroad thread. With that said though, this guide should show you just the things that are possible with a DLL injected in a process and how you can use a little creativity to do things that might otherwise be really tricky.

That wraps up this article. I will have a future guide that shows an alternative to this method based on my previously released sr33 and edx33 projects. Those articles will take some time to get done, so I will be working on others in the mean time. I hope you found this guide informational and beneficial. Stay tuned for future guides!

Drew “pushedx” Benton
edxLabs


Hello Kitty
vs
eMoStyLe



avatar
Hello EMO
EMO Team
EMO Team

Cinsiyet : Erkek
Burçlar : Yay
Yılan
Mesaj Sayısı : 935
Puan : 246043
Rep Puanı : 18
Doğum tarihi : 28/11/89
Kayıt tarihi : 21/07/09
Yaş : 27
Nerden : EMO WorlD
İş/Hobiler : RCE Student / Game Hacking / Learn Beginner C#,C++,Delphi
Lakap : EMO

Kullanıcı profilini gör http://emostyle.myforumpro.com

Sayfa başına dön Aşağa gitmek

Önceki başlık Sonraki başlık Sayfa başına dön

- Similar topics

 
Bu forumun müsaadesi var:
Bu forumdaki mesajlara cevap veremezsiniz