Unfortunately you can't send your button / key mappings using packets. The cleanest way to do this is probably to inject into the guiCommand() function in the client. You can use something like this:
Code:
Func guiCommand($command, $guiObjPtr)
;//Declare local variables
Local $pRemoteThread, $vBuffer, $loop, $result, $OPcode, $processHandle, $stringAddress, $stringSize
$processHandle = memOpen($pid)
;//Allocate memory for the OpCode and retrieve address for this
$functionAddress = DllCall($kernel32, 'int', 'VirtualAllocEx', 'int', $processHandle, 'ptr', 0, 'int', 0x46, 'int', 0x1000, 'int', 0x40)
;//Construct the OpCode for calling the 'guiCommand' function
$OPcode &= '60' ; PUSHAD
$OPcode &= 'A1' & _hex($guiObjPtr) ; MOV EAX, guiObjPtr
$OPcode &= '50' ; PUSH EAX
$OPcode &= '68' & _hex($command) ; PUSH commandString
$OPcode &= 'B8' & _hex($guiCommandCall) ; MOV EAX, guiCommandCall
$OPcode &= 'FFD0' ; CALL EAX
$OPcode &= '61' ; POPAD
$OPcode &= 'C3' ; RETN
;//Put the OpCode into a struct for later memory writing
$vBuffer = DllStructCreate('byte[' & StringLen($OPcode) / 2 & ']')
For $loop = 1 To DllStructGetSize($vBuffer)
DllStructSetData($vBuffer, 1, Dec(StringMid($OPcode, ($loop - 1) * 2 + 1, 2)), $loop)
Next
;//Write the OpCode to previously allocated memory
DllCall($kernel32, 'int', 'WriteProcessMemory', 'int', $processHandle, 'int', $functionAddress[0], 'int', DllStructGetPtr($vBuffer), 'int', DllStructGetSize($vBuffer), 'int', 0)
;//Create a remote thread in order to run the OpCode
$hRemoteThread = DllCall($kernel32, 'int', 'CreateRemoteThread', 'int', $processHandle, 'int', 0, 'int', 0, 'int', $functionAddress[0], 'ptr', 0, 'int', 0, 'int', 0)
;//Wait for the remote thread to finish
Do
$result = DllCall('kernel32.dll', 'int', 'WaitForSingleObject', 'int', $hRemoteThread[0], 'int', 50)
Until $result[0] <> 258
;//Close the handle to the previously created remote thread
DllCall($kernel32, 'int', 'CloseHandle', 'int', $hRemoteThread[0])
;//Free the previously allocated memory
DllCall($kernel32, 'ptr', 'VirtualFreeEx', 'hwnd', $processHandle, 'int', $functionAddress[0], 'int', 0, 'int', 0x8000)
memClose($processHandle)
Return True
EndFunc ;==>guiCommand
where $guiCommandCall is the function call address in the client.
And you would call it like this:
Code:
guiCommand($command, $control)
Where $command and $control are both strings... unfortunately, I can't remember what those string are for the skillbar keys. I'll have to take a look when I get home this evening, unless someone else would be kind enough to take a look :P (if you breakpoint at the function call in OllyDbg and take a few steps in, I think you can find the strings fairly easily).
Oh... and to find the function call, assuming it hasn't changed in the PWI update (has that happened yet?) you can use this utility - just stick it in your element folder and run it in AutoIt. It will spit the function call address out in the console. For the PWI client as of yesterday, the address was at 0x616CB0
Code:
getGuiCommandOffset()
Func getGuiCommandOffset()
$path = "elementclient.exe"
$file = FileOpen($path, 16)
$data = FileRead($file, FileGetSize($path))
FileClose($file)
$search = StringRegExp($data, '53' & _ ; PUSH EBX ; guiCommand()
'8B5C24.{2}' & _ ; MOV EBX,DWORD PTR SS:[ARG.1]
'56' & _ ; PUSH ESI
'8B7424.{2}' & _ ; MOV ESI,DWORD PTR SS:[ARG.2]
'57' & _ ; PUSH EDI
'56' & _ ; PUSH ESI ; /Arg2 => [ARG.2]
'53' & _ ; PUSH EBX ; |Arg1 => [ARG.1]
'E8.{8}' & _ ; CALL 007E6E30 ; \ElementClient.007E6E30
'84C0' & _ ; TEST AL,AL
'74.{2}' & _ ; JE SHORT 00604B6A
'85F6' & _ ; TEST ESI,ESI
'74.{2}' & _ ; JE SHORT 00604B62
'8BCE' & _ ; MOV ECX,ESI
'E8.{8}' & _ ; CALL 007F4940 ; [ElementClient.007F4940
'84C0' & _ ; TEST AL,AL
'74.{2}' & _ ; JE SHORT 00604B62
'8B06' & _ ; MOV EAX,DWORD PTR DS:[ESI]
'6A.{2}' & _ ; PUSH 1
'6A.{2}' & _ ; PUSH 0
'6A.{2}' & _ ; PUSH 0
'8BCE' & _ ; MOV ECX,ESI
'FF50.{2}' & _ ; CALL DWORD PTR DS:[EAX+1C]
'5F' & _ ; POP EDI
'5E' & _ ; POP ESI
'B0.{2}' & _ ; MOV AL,1
'5B' & _ ; POP EBX
'C2.{4}' & _ ; RETN 8
'68.{8}', 2) ; PUSH OFFSET 00AB4C8C
$call_pos = StringInStr($data, $search[0])/2 + 0x3FFFFF
ConsoleWrite('guiCommand() call address: 0x' & Hex($call_pos) & @CRLF)
EndFunc
Func rev($string)
Local $all
For $i = StringLen($string) + 1 To 1 Step -2
$all = $all & StringMid($string, $i, 2)
Next
While StringLeft($all, 1) = '0'
$all = StringTrimLeft($all, 1)
WEnd
Return $all
EndFunc