InfernoRose Packet - Using Script Breakpoint Handling

Share Your Own Code Samples With the World

Moderators: g3nuin3, SpeedWing, WhiteHat, mezzo

InfernoRose Packet - Using Script Breakpoint Handling

Postby Shynd » Tue Nov 20, 2007 10:46 pm

NOTE: This is a parallel thread to this one and is only a proof-of-concept. It is not useful as-is; you will have to edit it in order for it to be useful (and, I'm told, it is powerful enough to be very useful).


First, the ASM that we're going to bother with:
Code: Select all
00402D50 | 8BC1        | MOV     EAX, ECX                |
00402D52 | 56          | PUSH    ESI                     |
00402D53 | 8B7424 08   | MOV     ESI, DWORD PTR [ESP+8]  |
00402D57 | 8D48 78     | LEA     ECX, DWORD PTR [EAX+78] | ;<-----breakpointed
00402D5A | 8B40 74     | MOV     EAX, DWORD PTR [EAX+74] |
00402D5D | 50          | PUSH    EAX                     |
00402D5E | E8 BD220000 | CALL    00405020                |
00402D63 | 5E          | POP     ESI                     |
00402D64 | C2 0400     | RETN    4                       |
At line 402D53, the pointer to the packet is moved into ESI. I chose to breakpoint the line after ESI is changed (00402D57) so that I could access ESI after it is changed at line 402D53. See L. Spiro's reply to the thread for more information on which line to breakpoint and which function (Prolog, Callback, or Epilog) to use. My breakpoint looks like this:
Image
  • The black box is the address. Obviously, it's important that you breakpoint the correct address.
  • The red box is the type of breakpoint to apply. I chose hardware (causes no change in RAM, therefore CRC checks don't pick them up... I always use hardware BPs, if possible) and on Execute because this is a line of ASM that will be executed. If you were breakpointing for a change in a certain value--i.e. breakpoint whenever the value at address 0x65EB80 is changed--you'd use On Write, etc.
  • The blue box is telling the debugger which function to call before or after the line of ASM is executed. Prolog, Callback, and Epilog are fully documented in the MHS Help File AND in the third reply to this thread, where L. Spiro goes a little bit more into depth.

    If you want this breakpoint to be handled by a script function, be sure to choose Script Function from the dropdown, then set a unique Parm number. The Parm number is important as it tells the debugger WHICH script function is going to be handling this particular breakpoint. If you set Parm to 1, you'll need to write a function named On_BP_1(..); if you set Parm to 27, you'll need to write a function named On_BP_27(..). Process-specific breakpoint handlers--i.e. being able to write a function named On_BP_TROSE_EXE_1(..) and have it called only when TRose.exe is the current process--are coming in the 4.0.0.7 release of MHS, according to L. Spiro.

Now that that's explained, how do we go about handling the breakpoint? Simple! Open up your Script Editor and create a new script. Before you do anything, press CTRL+S to save it; after it's saved, click on the File menu and select Add to Scripts (or, alternatively, just press CTRL+D). This will make 'whatever_you_named_it.lss' show up in the Scripts toolwindow and add the script to the System, allowing it to execute and be compiled.

First things first, add a function like so: void On_BP_1(LPVOID lpvAddress, LPPROC_INFO_MHS lpProcInfo). This is the function that will handle the breakpoint. Depending on whether you chose Prolog or Callback, this function will be called either directly before or directly after the line on which you set the breakpoint is executed--in my case, since I chose Prolog, my BP handler is called before the line in question is executed.
Note: as explained above, in the 4.0.0.7 release of MHS, you will be able to use process-specific breakpoint handlers, i.e. void On_BP_TROSE_EXE_1(LPVOID lpvAddress, LPPROC_INFO_MHS lpProcInfo). Even if, for some reason, this doesn't get fully documented in the MHS 4.0.0.7 Help File, it acts exactly the same way as Hotkeys currently act, so look under how to handle a hotkey with a script function in the current help file.

Now that we have a function to handle it, let's do something inside the function, shall we? Well, let's declare our global variables first so that they don't have to be redeclared each time the breakpoint is hit:
Code: Select all
//##################################
//be extra sure to carefully name global variables
//these variables are global throughout all of MHS scripts
//not just this one.  for instance, if i were to name
//these without the bp_ header, i wouldn't be able to have
//a variable named 'shouldinject' anywhere in any other
//script, even as a local variable.
//##################################

//this is the packet for sending chat '123'
BYTE bp_comparepacket[10] = {0x0A, 0x00, 0x83, 0x07, 0x78, 0x01, 0x31, 0x32, 0x33, 0x00};
//this is the packet for sending chat '321'
BYTE bp_injectpacket[10] = {0x0A, 0x00, 0x83, 0x07, 0x78, 0x01, 0x33, 0x32, 0x31, 0x00};
//our packet buffer
BYTE bp_newpacket[255] = {0};
//string to display the outgoing packet
char bp_packet[1024] = {0};
//determines whether we change the outgoing packet or not
bool bp_shouldinject = false;
And NOW let's populate our function with what we want to happen with our breakpoint handler:
Code: Select all
//this is the function that will handle a breakpoint that has a Parm of '1'
void On_BP_1(LPVOID lpvAddress, LPPROC_INFO_MHS lpProcInfo)
{
   //lpvAddress (parameter 1) holds a pointer to the address at which the breakpoint was hit
   //obviously the user should already know where they set the breakpoint, but this
   //allows you to gather that information programmatically.  i suppose one could use this
   //for multiple breakpoints handled by the same function with a switch..case
   //used to determine at which address the breakpoint was hit, but i a) don't know if
   //that's possible and b) don't see the reason for doing that
   
   //lpProcInfo is a struct with all kinds of important information and resources
   //it allows us access to the process that hit the breakpoint, the thread that hit
   //the breakpoint, the context of the thread (registers, flags, etc), etc.
   //information on structs of type LPPROC_INFO_MHS can be found at this website:
   // http://www.memoryhacking.com/Misc/Tut/Disassembler%20-%20Debugger%20-%20Breakpoints.htm

   //ESI holds the pointer to the packet
   DWORD bp_ptr = lpProcInfo->pcContext->Esi;
   //the first byte of the packet pointed to by 'ptr' is the length
   extern BYTE bp_len = {"", bp_ptr};
   
   //optional verbose feedback to tell the user that the breakpoint was hit
   //MessageBox(MBS_OK, "Breakpoint!", "You just sent a packet!\n\nBreakpoint hit at 0x%08X\nLen: %i\nPtr: 0x%08X", (DWORD)lpvAddress, len, ptr);
   
   //read the packet out of memory
   if (!ReadProcessMemory(lpProcInfo->hProcess, (void *)bp_ptr, &bp_newpacket, bp_len, NULL))
      return;
   
   //initialize 'shouldinject' as true
   //we'll change 'shouldinject' to false as soon as a difference between
   //the packet we just read from memory and our compare packet is seen
   bp_shouldinject = true;
   
   //loop over the new packet
   for (int i = 0; i < bp_len; i++)
   {
      //populate the string with the bytes of the packet
      SPrintF(&bp_packet[i*3], "%02X ", bp_newpacket[i]);
      
      //if any single byte differs between the two packets
      //set boolean variable 'shouldinject' to false
      if (bp_comparepacket[i] != bp_newpacket[i]) bp_shouldinject = false;
   }
   
   if (bp_shouldinject) SPrintF(&bp_packet, "%s -- PACKET INJECTED!", bp_packet);
   
   //print out the packet string
   PrintF("Packet: %s", bp_packet);
   
   //if the two packets were the same
   if (bp_shouldinject)
      //write the changed packet over the current packet
      WriteProcessMemory(lpProcInfo->hProcess, (void *)bp_ptr, bp_injectpacket, sizeof(bp_injectpacket), NULL);
}
Click here to see the full script with syntax highlighting.

The big difference between this script and my previous thread (linked to at the top) is there is no need to loop and poll memory for changes. It's executed each time the game hits the breakpointed operation, therefore it's both event-driven AND we have full access to the context of the thread that hits the breakpoint--we have full access to the game's registers and flags and all of that stuff. We don't have to inject code to write ESI to a static address, read ESI from memory, etc. We simply set DWORD bp_ptr = lpProcInfo->pcContext->Esi;. lpProcInfo is the struct of information that is passed to the breakpoint handler function, ->pcContext is a thread context struct INSIDE lpProcInfo, and ->Esi is a DWORD representing the register ESI INSIDE lpProcInfo->pcContext.

Now we simply read the packet from memory at the address contained in ESI (which is also in 'bp_ptr' now), loop through it and compare it to our compare packet / output it to the console. If 'bp_shouldinject' remains true after the loop, we simply inject our packet by writing it over the current packet in memory.

Voila! Now, again, every time your character chats '123' it will be sent to the server as '321.'

Image

-Shynd
Last edited by Shynd on Wed Nov 21, 2007 10:45 am, edited 1 time in total.
User avatar
Shynd
Acker
 
Posts: 68
Joined: Fri Jan 05, 2007 2:11 am

Postby mezzo » Wed Nov 21, 2007 5:00 am

very nice indeed ! learned a lot from both posts !!

keep 'm coming :-)
- No thanks, I already have a penguin -
User avatar
mezzo
El Mariachi
 
Posts: 739
Joined: Mon Apr 30, 2007 10:27 pm
Location: Antwerp

Postby L. Spiro » Wed Nov 21, 2007 10:29 am

Keep them coming.


A point about Prolog and Callback functions though:
A breakpoint hit happens in 3 steps (as per the 3 types of callbacks there are).
#1: The 0xCC instruction is hit, or with hardware breaks it is just a stop.
#2: The 0xCC must be removed and the thread EIP set back (since it will be on the instruction after the 0xCC at this time. For hardware breaks, the hardware flags simply need to be reset without changing the EIP.
#3: The thread is resumed for one instruction. After it does one instruction the 0xCC needs to be written back or the hardware flags need to be set again.


The Prolog comes after #1. The break has just been hit but neither the EIP nor the hardware flags have been altered.
The Callback comes after #2. The EIP has been adjusted or the hardware flags have been removed. With hardware breakpoints, #1 and #2 are exactly the same except that the Dr* registers in the thread context are different.
The Epilog comes after #3, after the process is resumed but before the breakpoint is set back. The game is no longer paused at this point, but since the game thread is set to move only one instruction and then come back to the debugger (to allow the break to be set again) the Epilog is guaranteed to be called before the next instruction finishes (the debugger can not handle the single-step until the Epilog function finishes).



The Prolog and Callback functions will both be called before the current instruction is executed, but with differences in the state of the current thread. Since Callback comes after the EIP has been fixed, Callback is usually the most useful.

There is an important difference between software and hardware.
Hardware breaks happen after the specified address has been executed, while software breaks happen before.

So if you have a software breakpoint on 00402D57, 00402D57 will be the next instruction to execute when the breakpoint resumes.
A hardware breakpoint on 00402D57 means that 00402D5A will be the next instruction executed when the break resumes.


L. Spiro
User avatar
L. Spiro
L. Spiro
 
Posts: 3129
Joined: Mon Jul 17, 2006 10:14 pm
Location: Tokyo, Japan

Postby Shynd » Wed Nov 21, 2007 11:51 am

Thanks for the better understanding of how breakpoints work. I updated the post so that it's not too misleading, referring readers to your reply for further information.

As I said yesterday, I'll attempt to write a slightly more accessible tutorial (or two) over the next few days. I appreciate that you, L. Spiro, as well as the rest of the community have at least sorta enjoyed the tutorials and will be sure to 'keep them coming.' :)
User avatar
Shynd
Acker
 
Posts: 68
Joined: Fri Jan 05, 2007 2:11 am

Postby robrave » Tue Nov 27, 2007 3:16 pm

nice tutorial, I learned other ways of using MHS 8)
User avatar
robrave
Hacker Smacker
 
Posts: 41
Joined: Sat Sep 15, 2007 3:27 pm
Location: Philippines

Postby g3nuin3 » Tue Dec 25, 2007 5:43 am

Good work mate, this should really give MHS an edge over the other softwares.
g3nuin3
Acker
 
Posts: 96
Joined: Tue Jul 18, 2006 10:53 am

Postby don » Fri May 02, 2008 3:36 pm

Thanks for the tutorial Shynd, very informative, however I've a question, sorry if this has been asked but is there a way to modify your script to make it so if I send a packet, I can make it send multiple times at once?

Here's what I'm trying to do, send a packet (trade an item) in a trade window with 10 slots, then inject and send multiple packets at once telling the server to put the same item in the trade window but on different slots or fill the remaining 9 slots, thus duplicating it (well hopefully).

I already know how to change the item's position in the packet btw.

Thanks in advance! :D
don
I Have A Question
 
Posts: 1
Joined: Fri May 02, 2008 2:09 pm

Re: InfernoRose Packet - Using Script Breakpoint Handling

Postby patrickthom » Sat May 22, 2010 11:30 am

it is very tough to edit for using ..........
http://www.mcpddumps.com mcpd certification
http://www.ccnptests.net ccnp practice test
http://www.mcdbadumps.com mcdba certification
http://www.cciepapers.com ccie braindumps
patrickthom
I Have A Question
 
Posts: 1
Joined: Thu May 20, 2010 11:52 am

Re:

Postby Shynd » Sun May 23, 2010 12:37 am

don wrote:Thanks for the tutorial Shynd, very informative, however I've a question, sorry if this has been asked but is there a way to modify your script to make it so if I send a packet, I can make it send multiple times at once?

Here's what I'm trying to do, send a packet (trade an item) in a trade window with 10 slots, then inject and send multiple packets at once telling the server to put the same item in the trade window but on different slots or fill the remaining 9 slots, thus duplicating it (well hopefully).

I already know how to change the item's position in the packet btw.

Thanks in advance! :D

You would be better off writing that script from scratch instead of modifying an existing one. You can definitely take some of the things learned from this example and put them to practice in your script, but you would have to do a few things differently (calling a remote function with different parameters, instead of filtering a single send call). Perhaps learning basic programming practices instead of trying to jump in the deep end too quickly would help.
User avatar
Shynd
Acker
 
Posts: 68
Joined: Fri Jan 05, 2007 2:11 am


Return to Code Submissions

Who is online

Users browsing this forum: No registered users and 0 guests

cron