Help File:Basic packet editing

From Cheat Engine
Revision as of 04:24, 8 March 2017 by TheyCallMeTim13 (talk | contribs) (Created page with '== Basic packet editing == Basic Packet editing with Cheat Engine This is just an example tutorial describing how to do basic packet editing with Cheat Engine. It's main purp…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Basic packet editing

Basic Packet editing with Cheat Engine

This is just an example tutorial describing how to do basic packet editing with Cheat Engine. It's main purpose is to show that you don't have to use other tools when packet editing. (Sure, it helps and is easier, but CE can do it as well)

Let's say you want to change in outgoing packet data the word "hello" with the word "idiot". First gather all needed information and discuss some basic api calling mechanics: Packet data is sent using ws2_32.dll's send api . To target this api's location you have to use ws2_32!send as name, else ce will pick winsock32's send export, which is not what you want Next you have to know that the 2nd parameter contains the pointer to the buffer that is being sent. Let's first get into windows api calling mechanics. Parameter passing is done by pushing the parameters in reverse order on the stack, followed by a call to the send api., which pushes the next instruction's address on the stack as well. Because each push decreases esp with 4 bytes, the parameters will actually appear in the correct order, making it [esp] point to the return address, [esp+4] holds the first parameter (socket), [esp+8] holds the 2nd parameter (pointer to buffer containing data), [esp+c] holds the length of that buffer, etc...

To packet edit you'll have to hook the send api and inspect and manipulate the parameters and buffers sent. In short, code injection at ws2_32!send, get the address of the send buffer, get the length, scan that buffer for the word hello, and if found, replace that with the word idiot

The following code snipet is an example of basic packet editing. (Nothing fancy, but does the job)

 alloc(newmem,2048) //2kb should be enough
 label(returnhere)
 label(originalcode)
 label(exit)
 label(repeat)
 label(repeat2)
 label(nomatch)
 label(nomatch2)
 label(endofroutine)
 alloc(texttoscan,5) //non 5.4.4
 alloc(texttoreplacewith,5)
  
 define(stringlength,5)
 texttoscan:
 db 'hello'
  
 texttoreplacewith:
 db 'idiot'
  
 ws2_32!send:
 jmp newmem
 returnhere:
  
 newmem: //this is allocated memory, you have read,write,execute access
 //place your code here
  
 //start off with a stackframe
 push ebp
 mov ebp,esp
  
 //lets save the used registers
 push eax
 push ecx
 push esi
 push edi
  
  
 mov esi,[ebp+0c] //buffer (I might have said esp+8 in the post, but due to the added stackframe(push ebp), it's all shifted 4 bytes)
 mov edi,texttoscan
 mov ecx,[ebp+10] //length of buffer
 cmp ecx,stringlength
 jl endofroutine
  
 sub ecx,stringlength-1
  
  
 repeat:
 //edit: because 5.4 doesn't support cmp byte [esi],'t' I have to do it different than in 5.4.4
 push ecx
 mov ecx,stringlength-1
 repeat2:
 /*
 sure, it compares from the back to front, but as long as it checks it's a match
 I don't care
 */
 mov al,[esi+ecx]
 cmp al,[edi+ecx]
 jne nomatch2
 loop repeat2
  
  
 //still here, so a match
 push esi
 push edi
 mov edi,esi //I want the found buffer to be the destination, not source
 mov esi,texttoreplacewith
 mov ecx,stringlength
 rep movsb //move the byte stored at [esi] into [edi] ecx times (so move texttoreplacewith to the found string
 pop edi
 pop esi
  
 nomatch2:
 pop ecx
  
 nomatch:
 inc esi
 loop repeat
  
 endofroutine:
  
 //undo any register change
 pop edi
 pop esi
 pop ecx
 pop eax
  
 /*
 undo stackframe. Ok, in this situation the stackframe of the original function
 could have been used, but I try to keep it understandable to readers.
 */
 mov esp,ebp
 pop ebp
  
 originalcode:
 mov edi,edi
 push ebp
 mov ebp,esp
  
 exit:
 jmp returnhere

Note: Instead of editing the actual buffer you might want to create a new buffer and pass that on to the send api. That'll allow for longer texts, and won't mess up if the program actually uses read-only buffers for the send api