Code Injection

04/30/2011 18:42 Shortpants#1
Hey epvp,

I have been messing around for quite a while now, and I came to the point where I have no idea what i'm doing wrong the OPCODE looks fine (imho). Yet it still crashes the client.

Any help would be very appreciated, code is posted below. I hope you're not just going to give a working code but also information on why the current OPCODE is wrong.

Thanks in advance.

Code:
#RequireAdmin
#include 'NomadMemory.au3'

HotKeySet('{ESC}', '__Terminate')

; Main Variables
Dim $APP_TITLE = 'Perfect World International'

Dim $PID = WinGetProcess($APP_TITLE)
Dim $MEM_HANDLE = _MemoryOpen($PID)

; Required for Code injection
Dim $OPCODE



; Main Loop 0 to 769
For $iIndex = 0 To 769
	If GetNPCID($iIndex) <> 0 Then TargetNPC(GetNPCID($iIndex))
	Sleep(1000)
Next

__Terminate()
Exit



; Functions
Func TargetNPC($NPC_ID)
	#cs
		Original Code
		
		00464EAD - A1 C444AE00                - mov eax,[00AE44C4] : [00AE4B68]
		00464EB2 - 57                         - push edi
		00464EB3 - 8B 48 20                   - mov ecx,[eax+20]
		00464EB6 - 81 C1 EC000000             - add ecx,000000EC
		00464EBC - E8 2F121E00                - call 006460F0
	#ce
	$OPCODE &= '60' ; pushad
	$OPCODE &= 'A1' & 'C444AE00' ; mov eax,[00AE44C4]
	$OPCODE &= '68' & _ReverseBytes($NPC_ID) ; push mob ID
	$OPCODE &= '8B4820' ; mov ecx,[eax+0x20]
	$OPCODE &= '81C1EC000000' ; add ecx,000000EC
	$OPCODE &= 'E8' & '2F121E00' ; call 006460F0
	$OPCODE &= '61' ; popad
	$OPCODE &= 'C3' ; ret

	InjectCode($PID, $OPCODE)
EndFunc   ;==>TargetNPC

Func GetNPCID($i)
	Local $NPCID_OFFSET[7], $RBASE_ADDRESS = 0x00AE44C4
	$NPCID_OFFSET[1] = 0x0000001C
	$NPCID_OFFSET[2] = 0x0000001C
	$NPCID_OFFSET[3] = 0x00000024
	$NPCID_OFFSET[4] = 0x00000050
	$NPCID_OFFSET[5] = ($i * 0x00000004)
	$NPCID_OFFSET[6] = 0x0000011C

	$NPC_ID = _MemoryPointerRead($RBASE_ADDRESS, $MEM_HANDLE, $NPCID_OFFSET)
	Return Hex($NPC_ID[1])
EndFunc   ;==>GetNPCID

Func _ReverseBytes($dBytes)
	Local $dOut, $i

	For $i = (StringLen($dBytes) + 1) To 0 Step -2
		$dOut &= StringMid($dBytes, $i, 2)
	Next

	Return $dOut
EndFunc   ;==>_ReverseBytes

Func InjectCode($PID, $OPCODE)
	; __Terminate()

	If $PID <> 0 And $OPCODE <> "" Then
		Local $DATA = DllStructCreate("byte[" & StringLen($OPCODE) / 2 & "]")
		For $i = 1 To DllStructGetSize($DATA)
			DllStructSetData($DATA, 1, Dec(StringMid($OPCODE, ($i - 1) * 2 + 1, 2)), $i)
		Next
		Local $RESULT, $PROCESS, $ADD, $THREAD
		$RESULT = DllCall("Kernel32.Dll", "int", "OpenProcess", "int", 2035711, "int", 0, "int", $PID)
		$PROCESS = $RESULT[0]
		$RESULT = DllCall("Kernel32.dll", "ptr", "VirtualAllocEx", "int", $PROCESS, "ptr", 0, "int", DllStructGetSize($DATA), "int", 4096, "int", 64)
		$ADD = $RESULT[0]
		$RESULT = DllCall("kernel32.dll", "int", "WriteProcessMemory", "int", $PROCESS, "ptr", $ADD, "ptr", DllStructGetPtr($DATA), "int", DllStructGetSize($DATA), "int", 0)
		$RESULT = DllCall("kernel32.dll", "int", "CreateRemoteThread", "int", $PROCESS, "ptr", 0, "int", 0, "int", $ADD, "ptr", 0, "int", 0, "int", 0)
		$THREAD = $RESULT[0]
		Do
			$RESULT = DllCall("kernel32.dll", "int", "WaitForSingleObject", "int", $THREAD, "int", 50)
		Until $RESULT[0] <> 258
		DllCall("Kernel32.dll", "int", "CloseHandle", "int", $THREAD)
		$RESULT = DllCall("Kernel32.dll", "ptr", "VirtualFreeEx", "hwnd", $PROCESS, "ptr", DllStructGetPtr($DATA), "int", DllStructGetSize($DATA), "int", 32768)
		DllCall("Kernel32.dll", "int", "CloseHandle", "int", $PROCESS)
		$OPCODE = ""
		$DATA = 0
	EndIf
EndFunc   ;==>InjectCode

Func __Terminate()
	; MsgBox(0, '', $OPCODE)
	_MemoryClose($PID)
	Exit
EndFunc   ;==>__Terminate
04/30/2011 19:24 Sᴡoosh#2
Quote:
00464EAD - A1 C444AE00 - mov eax,[00AE44C4] : [00AE4B68]
00464EB2 - 57 - push edi
00464EB3 - 8B 48 20 - mov ecx,[eax+20] //unsure
00464EB6 - 81 C1 EC000000 - add ecx,000000EC
00464EBC - E8 2F121E00 - call 006460F0
I havent checked this function for ages. But I do know that when you inject mining action, you need to write +34h as character struct, not +20h like you are dooing.
I dont remember if thats the cause for targeting to. Did you check in debugger?
04/30/2011 20:03 Shortpants#3
Quote:
Originally Posted by 2981611 View Post
I havent checked this function for ages. But I do know that when you inject mining action, you need to write +34h as character struct, not +20h like you are dooing.
I dont remember if thats the cause for targeting to. Did you check in debugger?
Well, I checked PWI yesterday and it's still this function (in memory view), but let me try with 34.

Edit: Doesn't seem to work either. Must be something really small, like always.... :/
04/30/2011 22:51 Interest07#4
Perhaps the call function part is wrong?

Try storing the function address in a register and call that. I've had issues before trying to call a function as an offset before.


I mean this part:
$OPCODE &= 'E8' & '2F121E00' ; call 006460F0
instead do for example:
mov eax, 0x006460F0
call eax
04/30/2011 23:00 Sᴡoosh#5
Ive had a simular problem with inline asm in delphi to. Good point there, interest :)
05/01/2011 01:23 Shortpants#6
Tried both commented lines, still doesn't work. Is my Mob ID right? Since the return is an integer I assume, which then gets returned as hex and reversed, but even that I tried with different types. Honestly have no idea what's wrong. Can't think of anything else to try either, I would love to see a working sample of this. Either here or through PM, in any language really since this was pure conceptional.

Code:
  	$OPCODE &= '60' ; pushad
	$OPCODE &= 'A1' & 'C444AE00' ; mov eax,[00AE44C4]
	$OPCODE &= '68' & _ReverseBytes($NPC_ID) ; push ID
	$OPCODE &= '8B4820' ; mov ecx,[eax+0x20]
	$OPCODE &= '81C1EC000000' ; add ecx,000000EC

	; $OPCODE &= 'B82F121E00' ; mov eax dword ptr 006460F0
	; $OPCODE &= 'A12F121E00' ; mov eax,006460F0
	$OPCODE &= 'FFD0' ; call eax

	$OPCODE &= '61' ; popad
	$OPCODE &= 'C3' ; ret

	InjectCode($PID, $OPCODE)
05/01/2011 01:29 Sᴡoosh#7
Check out Prophet bot source; I belive they target through Packets, but I think you will have a reference there.
05/01/2011 01:37 Shortpants#8
But did they ever got the targetting system to work through code injection? Packets is not what i'm looking for, since I want to inject more codes then just this one.

Maybe inline assembly on other languages will make more sense then manually searched OPcodes, might give that a try if I can't find a working answer here :)
05/01/2011 02:27 Sᴡoosh#9
Uhhh... using packets you can do everything you want, as long as its serversided, logically. Gathering, Rolling, Talking,Attacking,Calling shit, using items... And yes, even targeting :)
05/01/2011 03:52 Shortpants#10
Quote:
Originally Posted by 2981611 View Post
Uhhh... using packets you can do everything you want, as long as its serversided, logically. Gathering, Rolling, Talking,Attacking,Calling shit, using items... And yes, even targeting :)
I'm aware of that, but packets might change too. And sending wrong packets (eg if it changed due to a patch) is so easily detectable. If you take a game such as Diablo II for example, if you send a packet that was used for dupes or bots or any other sort of third party application you'll be instant banned.
05/01/2011 06:32 Interest07#11
; $OPCODE &= 'B82F121E00' ; mov eax dword ptr 006460F0
; $OPCODE &= 'A12F121E00' ; mov eax,006460F0

these are not moving the correct address to eax, literally move 006460F0 to eax . Presuming that's the correct address for the function of course :p Else i'm not sure why its in the comments

like if the function address is 00499140, then you'd call it as follows:


Code:
            byte[] opcode = new byte[]
            { 
                0x60,                           //pushad
                0xB9, 0x00, 0x00, 0x00, 0x00,   //mov ECX, itemBaseAddress
                0xB8, 0x40, 0x91, 0x49, 0x00,   //mov EAX, functionAddress
                0xFF, 0xD0,                     //call EAX
                0x61,                           //popad
                0xC3                            //retn
            };

even if your mobId wasn't correct, your client should not crash I think, it would probably give an error message (in blue chat)
05/01/2011 19:45 Shortpants#12
Quote:
Originally Posted by Interest07 View Post
; $OPCODE &= 'B82F121E00' ; mov eax dword ptr 006460F0
; $OPCODE &= 'A12F121E00' ; mov eax,006460F0

these are not moving the correct address to eax, literally move 006460F0 to eax . Presuming that's the correct address for the function of course :p Else i'm not sure why its in the comments

like if the function address is 00499140, then you'd call it as follows:


Code:
            byte[] opcode = new byte[]
            { 
                0x60,                           //pushad
                0xB9, 0x00, 0x00, 0x00, 0x00,   //mov ECX, itemBaseAddress
                0xB8, 0x40, 0x91, 0x49, 0x00,   //mov EAX, functionAddress
                0xFF, 0xD0,                     //call EAX
                0x61,                           //popad
                0xC3                            //retn
            };

even if your mobId wasn't correct, your client should not crash I think, it would probably give an error message (in blue chat)
So the base address and function address should be called in normal hex? Not a modified version, just exactly how it is in the opcode?
05/02/2011 08:21 Interest07#13
Well, I'm not sure where you got "2F121E00" from, but it's not a function address as far as I can tell. You have to put the actual function address in there.

just do "B8F0606400"
05/02/2011 08:55 Shortpants#14
Well, I must say I have rewritten all of it in C++ and even this fails to work... I'm pretty sure this should always work no matter what................ I am honestly out of ideas.

Code:
static DWORD WINAPI Target(DWORD dwParam)
{
	/*
		00464EAD - A1 C444AE00                - mov eax,[00AE44C4] : [00AE4B68]
		00464EB2 - 57                         - push edi
		00464EB3 - 8B 48 20                   - mov ecx,[eax+20]
		00464EB6 - 81 C1 EC000000             - add ecx,000000EC
		00464EBC - E8 2F121E00                - call 006460F0
	*/

	DWORD dwBaseAddr = 0x00AE44C4;
	DWORD dwCallAddr = 0x006460F0;
	DWORD dwTargetID = 0x80107AF5;

	_asm
	{
		mov eax, dwBaseAddr;
		mov eax, [eax];
		mov edi, dwTargetID;
		push edi;
		mov ecx, DWORD PTR [eax+0x20];
		add ecx, 0xEC;
		mov edx, dwCallAddr;
		mov edx, [edx];
		call edx;
	}

	return dwTargetID;
}
05/02/2011 09:45 Interest07#15
try removing mov edx, [edx];?