Серебрянная пуля против Вея Сябао и флудерастов с горнами
Всё началось сдесь с того что один замечательный человек решил избавить нас от засилия красного флуда. Программа работала до Генезиса, была мной обновлена под генезис , но главный трабл в ней всётаки остался. А именно - флуд возвращаетя после релога , или использования внутриигровой панели настроек. Я начал искать лекарство, но оказалось что оно уже есть на ПВИ. По моей просьбе автор программы любезно согласился создать её вариант для руофа. Я занимался тестированием и переводом на русский язык.
Программа на AutoIt, при прикреплении сканирует запущеный в ОЗУ процесс клиента PW. Сама определяет BaseСall, RealBase и некоторые другие необходимые для работы параметры.
Далее требуется установить патч нажатием соответствующей кнопки . Патч устанавливается непосредственно в ОЗУ ,при этом файл elementclient.exe на диске изменениям не подвергается. Патч необходим для устранения фрагментов кода клиента, которые отвечают за автоматическое принудительное включение системного чата (красный) и горн чата во всех каналах чата - групповом , клан , ПМ и других. Так же есть возможность выключения / включения всплывающего окна горнов .
ВНИМАНИЕ !
Как было сказано выше, программа содержит элементы для осуществления доступа и записи ОЗУ ПК( Memory Process Inject ).
Эти элементы могут служить причиной ложного ( False Positive ) распознавания программы как опасной и / или содержащей вирусный код некоторыми антивирусами .
По этой причине я выкладываю все исходные для компилляции файлы - каждый может ознакомиться с содержанием программы лично и убедиться в её безопасности.
ВНИМАНИЕ !
Любые претензии по нахождению в программе опасных элементов / опасности программы будут рассматриваться ИСКЛЮЧИТЕЛЬНО ПРИ ПРИДОСТАВЛЕНИИ ФРАГМЕНТА КОДА ПРОГРАММЫ (DIS-ASSEMBLY) С УКАЗАНИЕМ НА ОПАСНЫЕ ЭЛЕМЕНТЫ !
Иными словами, вопросы типа: пАчИму мой антЕвирус чото видЕт ? - рассматриваются мной исключительно как флуд, и ответ на них в моей подписи .
Выражаю глубокую благодарность автору программы, замечательному парню из старой доброй Англии - Стюарту ака dumbfck за создание руофф версии программы.
Обсуждение оригинальной версии на Английском языке - [Ссылки могут видеть только зарегистрированные пользователи. ]
#include-once
; Sourced from http://www.autoitscript.com/forum/topic/113182-easy-multidimensional-associative-arrays/
; #INDEX# =======================================================================================================================
; Title .........: xHashCollection
; AutoIt Version : 3.3.4.0
; Language ......: English
; Description ...: Create and use Multidimentional Associative Arrays
; Author ........: OHB <me at orangehairedboy dot com>
; ===============================================================================================================================
Global $_xHashCollection = ObjCreate( "Scripting.Dictionary" ), $_xHashCache
; #FUNCTION# ====================================================================================================================
; Name...........: x
; Description ...: Gets or sets a value in an Associative Array
; Syntax.........: SET: x( $sKey , $vValue )
; GET: x( $key )
; Parameters ....: $sKey - the key to set or get. Examples:
; x( 'foo' ) gets value of foo
; x( 'foo.bar' ) gets value of bar which is a key of foo
; $bar = "baz"
; x( 'foo.$bar' ) gets value of baz which is a key of foo (variables are expanded)
; Return values .: Success - When setting, return the value set. When getting, returns the requested value.
; Failure - Returns a 0
; Author ........: OHB <me at orangehairedboy dot com>
; ===============================================================================================================================
Func x( $sKey = '' , $vValue = '' )
$func = "get"
If @NumParams <> 1 Then $func = "set"
If $sKey == '' Then
If $func == "get" Then
Return $_xHashCollection
Else
$_xHashCollection.removeAll
Return ''
EndIf
EndIf
$parts = StringSplit( $sKey , "." )
$last_key = $parts[$parts[0]]
$cur = $_xHashCollection
For $x = 1 To $parts[0] - 1
If Not $cur.exists( $parts[$x] ) Then
If $func == "get" Then Return
$cur.add( $parts[$x] , ObjCreate( "Scripting.Dictionary" ) )
EndIf
$cur = $cur.item( $parts[$x] )
Next
If IsPtr( $vValue ) Then $vValue = String( $vValue )
If $func == "get" Then
If Not $cur.exists( $last_key ) Then Return
$item = $cur.item( $last_key )
Return $item
ElseIf Not $cur.exists( $last_key ) Then
$cur.add( $last_key , $vValue )
Else
$cur.item( $last_key ) = $vValue
EndIf
Return $vValue
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: x_unset
; Description ...: Removes a key from an Associative Array
; Syntax.........: x_unset( $sKey )
; Parameters ....: $sKey - the key to remove.
; Return values .: Success - True
; Failure - False
; Author ........: OHB <me at orangehairedboy dot com>
; ===============================================================================================================================
Func x_unset( $sKey )
If $sKey == '' Then Return x( '' , '' )
$parts = StringSplit( $sKey , "." )
$cur = $_xHashCollection
For $x = 1 To $parts[0] - 1
If Not $cur.exists( $parts[$x] ) Then Return False
$cur = $cur.item( $parts[$x] )
Next
$cur.remove( $parts[$parts[0]] )
Return True
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: x_display
; Description ...: Displays the contents of an Associative Array
; Syntax.........: x_display( $sKey )
; Parameters ....: $sKey - the key to display. Examples:
; x_display() displays everything
; x_display( 'foo' ) displays the contents of foo
; Author ........: OHB <me at orangehairedboy dot com>
; ===============================================================================================================================
Func x_display( $key = '' )
$text = $key
If $key <> '' Then $text &= " "
$text &= StringTrimRight( _x_display( x( $key ) , '' ) , 2 )
$wHnd = GUICreate( "Array " & $key , 700 , 500 )
GUISetState( @SW_SHOW , $wHnd )
$block = GUICtrlCreateEdit( $text , 5 , 5 , 690 , 490 )
GUICtrlSetFont( $block , 10 , 400 , -1 , 'Courier' )
While 1
If GUIGetMsg() == -3 Then ExitLoop
WEnd
GUISetState( @SW_HIDE , $wHnd )
GUIDelete( $wHnd )
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _x_display
; Description ...: Itterates through an array and builds output for x_display
; Author ........: OHB <me at orangehairedboy dot com>
; ===============================================================================================================================
Func _x_display( $item , $tab )
If IsObj( $item ) Then
$text = 'Array (' & @CRLF
$itemAdded = False
For $i In $item
$text &= $tab & " [" & $i & "] => " & _x_display( $item.item($i) , $tab & " " )
$itemAdded = True
Next
If Not $itemAdded Then $text &= @CRLF
$text &= $tab & ')'
ElseIf IsArray( $item ) Then
$text = "Array"
$totalItems = 1
$dimensions = UBound( $item , 0 )
For $dimension = 1 To $dimensions
$size = UBound( $item , $dimension )
$totalItems *= $size
$text &= "[" & $size & "]"
Next
$text &= " (" & @CRLF
For $itemID = 0 To $totalItems - 1
$idName = ''
$idNum = $itemID
For $dimension = 1 To $dimensions - 1
$mul = ( $totalItems / UBound( $item , $dimension ) )
$a = Floor( $idNum / $mul )
$idName &= '[' & $a & ']'
$idNum -= ( $a * $mul )
Next
$idName &= '[' & $idNum & ']'
$text &= $tab & " " & $idName & " => " & _x_display( Execute( "$item" & $idName ) , $tab & " " )
Next
$text &= $tab & ")"
Else
$text = $item
EndIf
$text &= @CRLF
Return $text
EndFunc
файл PW_ChatFilter.au3
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <ComboConstants.au3>
#include <StaticConstants.au3>
#include <GUIComboBox.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <Color.au3>
#include <NomadMemory.au3>
#include <Array.au3>
#include <filterOffsets.au3>
#Include "MultiAssocArray.au3" ; http://www.autoitscript.com/forum/topic/113182-easy-multidimensional-associative-arrays/
Opt("GUIOnEventMode", 1) ;0=disabled, 1=OnEvent mode enabled
Global $ApW = 300, $ApH = 450
Global Const $iPI = 3.1415926535897932384626433832795
$hGui = GUICreate("PW Real Chat Filter by dumbfck", $ApW, $ApH)
GUISetBkColor(0x192127)
GUISetOnEvent(-3, "_Quit")
$Pic = GUICtrlCreatePic("", 0, 75, $ApW, $ApH)
GUICtrlSetState(-1, $GUI_DISABLE)
$cboCharacter = GUICtrlCreateCombo("", 8, 8, 185, 25, BitOR($CBS_DROPDOWN, $CBS_AUTOHSCROLL))
$btnAttach = GUICtrlCreateButton("Прикрепить", 200, 6, 80, 24)
GUICtrlSetOnEvent($btnAttach, "btnAttach_Click")
$btnApply = GUICtrlCreateButton("Применить", 120, 415, 100, 25)
GUICtrlSetOnEvent($btnApply, "btnApply_Click")
$btnPatch = GUICtrlCreateButton("Патч", 200, 36, 80, 25)
GUICtrlSetOnEvent($btnPatch, "btnPatch_Click")
Global $kernel32 = DllOpen('kernel32.dll')
Global $procName = "elementclient.exe"
Global $processes
Global $pid
Global $pHandle
Global $functionAddress
Global $charNames[1]
; Are assigned in constructOffsets()
Global $baseCall
Global $realBase
Global $playerBase
Global $playerNamePtr
Global $guiBase0
Global $guiBase1
Global $tab_gamesetting
Global $tabVisibleOffset
Global $str_Btn_Close
Global $str_gamesetting
Global $str_apply
Global $guiCommandCall
Global $settingsBase
Global $staticChatFilters
Global $patchSearchExpression = _
"885005" & _ ;00569174 MOV BYTE PTR DS:[EAX+5],DL ; force system chat = enabled
"8810" & _ ;00569177 MOV BYTE PTR DS:[EAX],DL ; force whisper enabled
"885008" & _ ;00569179 MOV BYTE PTR DS:[EAX+8],DL ; force horn enabled? (chat type 0xC)
"83C00D" & _ ;0056917C ADD EAX,0D
"49" & _ ;0056917F DEC ECX
"75F2" & _ ;00569180 JNE SHORT 00569174
"33DB" & _ ;00569182 XOR EBX,EBX
"8BCD" & _ ;00569184 MOV ECX,EBP
"889519020000" & _ ;00569186 MOV BYTE PTR SS:[EBP+219],DL
"889D5A020000" & _ ;0056918C MOV BYTE PTR SS:[EBP+25A],BL
"889D62020000" & _ ;00569192 MOV BYTE PTR SS:[EBP+262],BL
"889D5D020000" & _ ;00569198 MOV BYTE PTR SS:[EBP+25D],BL
"889D65020000" ;0056919E MOV BYTE PTR SS:[EBP+265],BL
Global $alreadyPatchedExpression = _
"9090909090909090" & _ ;8 x NOP
"83C00D" & _ ;ADD EAX,0D
"49" & _ ;DEC ECX
"75F2" & _ ;JNE SHORT 00564D54
"33DB" & _ ;XOR EBX,EBX
"8BCD" & _ ;MOV ECX,EBP
"909090909090909090909090909090909090909090909090909090909090" ; 30 x NOP
If Not StringLen($patchSearchExpression) = StringLen($alreadyPatchedExpression) Then
MsgBox(0, "D'oh!", "Patch and unpatch expression lengths do not match!")
Exit
EndIf
$processes = ProcessList($procName)
If UBound($processes) < 2 Then ; first entry is always empty
MsgBox(16, 'Ошибка', 'клиент не найден')
Exit
Else
; Check first found client, get exe path and check the file to see if we can extract offsets
$pid = $processes[1][1] ; [x][1] = PID of process
$pHandle = _MemoryOpen($pid)
If $pHandle <> 0 Then
$client = GetModuleBaseByName($pid, $procName) ; $client[1]= *modBaseAddr, [2]=modbaseSize, [3]=szExePath
getOffsets($client[3], $search) ; $search is defined in filterOffsets.au3
constructOffsets()
Else
MsgBox(0, "Ошибка", "elementsclient.exe не обнаружен. Пожалуйста запустите PW перед пуском программы.")
EndIf
_MemoryClose($pHandle)
For $i = 1 To $processes[0][0]
$pid = $processes[$i][1] ; PID of process
$pHandle = _MemoryOpen($pid)
constructOffsets()
$charName = _MemoryRead($playerNamePtr, $pHandle, 'wchar[30]')
ReDim $charNames[$i]
$charNames[$i - 1] = $charName
_MemoryClose($pHandle)
Next
$charString = _ArrayToString($charNames, "|")
GUICtrlSetData($cboCharacter, $charString, 0)
ControlCommand("", "", $cboCharacter, "SetCurrentSelection", 0)
EndIf
PicSetGraphics($Pic, $ApW, $ApH); <-- Draw GDIPlus graphics on Picture control.
; Draw the checkbox grid
$startLeft = 93
$startTop = 145
$columns = 6
$rows = 13
Global $chkBox[$columns * $rows]
For $x = 0 To $columns - 1
For $y = 0 To $rows - 1
$id = $x * $rows + $y
$chkBox[$id] = GUICtrlCreateCheckbox("chk" & ($id), $startLeft + $x * 28, $startTop + $y * 20, 20, 20)
Next
Next
GUISetState(@SW_SHOW, $hGui)
; Loop forever
While 1
Sleep(10)
WEnd
; This must be updated whenever new offsets are added in filterOffsets.au3
Func constructOffsets()
; These vars are all globals declared at start of program
$baseCall = x('o.baseCall.offset')
ConsoleWrite('baseCall: ' & Hex($baseCall) & @CRLF)
$realBase = _MemoryRead($baseCall, $pHandle) + x('o.realBase.offset')
ConsoleWrite('realBase: ' & Hex($realBase) & @CRLF)
$playerBase = _MemoryRead($realBase, $pHandle) + x('o.playerBase.offset')
ConsoleWrite('playerBase: ' & Hex($playerBase) & @CRLF)
$playerNamePtr = _MemoryRead(_MemoryRead($playerBase, $pHandle) + x('o.playerName.offset'), $pHandle)
ConsoleWrite('playerNameOffset: ' & Hex($playerNamePtr) & @CRLF)
$guiBase0 = _MemoryRead($realBase, $pHandle) + x('o.guiBase0.offset')
ConsoleWrite('guiBase0: ' & Hex($guiBase0) & @CRLF)
$guiBase1 = _MemoryRead($guiBase0, $pHandle) + x('o.guiBase1.offset')
ConsoleWrite('guiBase1: ' & Hex($guiBase1) & @CRLF)
$tab_gamesetting = _MemoryRead($guiBase1, $pHandle) + x('o.tab_gamesetting.offset')
ConsoleWrite('tab_gamesetting: ' & Hex($tab_gamesetting) & @CRLF)
$tabVisibleOffset = x('o.str_gamesetting.offset')
ConsoleWrite('tabVisibleOffset: ' & Hex($tabVisibleOffset) & @CRLF)
$gamesettingTabVisible = _MemoryRead($tab_gamesetting, $pHandle) + x('o.tabVisible.offset')
ConsoleWrite('gamesettingTabVisible: ' & Hex($gamesettingTabVisible) & @CRLF)
$str_Btn_Close = x('o.str_Btn_Close.offset')
ConsoleWrite('str_Btn_Close: ' & Hex($str_Btn_Close) & @CRLF)
$str_gamesetting = x('o.str_gamesetting.offset')
ConsoleWrite('str_gamesetting: ' & Hex($str_gamesetting) & @CRLF)
$settingsBase = _MemoryRead($baseCall, $pHandle) + x('o.settingsBase.offset')
ConsoleWrite('settingsBase: ' & Hex($settingsBase) & @CRLF)
$staticChatFilters = _MemoryRead($settingsBase, $pHandle) + x('o.staticChatFilters.offset') + 4
ConsoleWrite('staticChatFilters: ' & Hex($staticChatFilters) & @CRLF)
#cs
; This bastard is reaaaally hard to find in the code with a regex search...
; So lets cheat and just write the string to memory somewhere (see memWriteString() function, called during attach process)
$str_apply = x('o.str_apply.offset')
ConsoleWrite('str_apply: ' & Hex($str_apply) & @CRLF)
#ce
$guiCommandCall = x('o.guiCommandCall.offset')
ConsoleWrite('guiCommandCall: ' & Hex($guiCommandCall) & @CRLF)
EndFunc
Func btnAttach_Click()
$selectedIndex = _GUICtrlComboBox_GetCurSel($cboCharacter)
$pid = $processes[$selectedIndex + 1][1] ; PID of process
$pHandle = _MemoryOpen($pid)
constructOffsets()
$charName = _MemoryRead($playerNamePtr, $pHandle, 'wchar[30]')
If Not @error Then
MsgBox(0, "Завершено", "Прикреплено к " & $charName & @CRLF & "PID: " & Hex($pid))
getChatFilters()
; Dirty hack because the "apply" string constant offset is such a bitch to find with a regex
; This takes the place of where the string offset ideally should have been fetched in the constructConstants() function
$processHandle = memOpen($pid)
$str_apply = DllCall($kernel32, 'int', 'VirtualAllocEx', 'int', $processHandle, 'ptr', 0, 'int', 0x50, 'int', 0x1000, 'int', 0x40)
$str_apply = $str_apply[0]
memClose($processHandle)
; binary string for "apply" ...
_MemoryWrite($str_apply, $pHandle, "0x6170706C7900", "byte[6]")
EndIf
; leave the handle open for now
EndFunc
Func btnPatch_Click()
If GUICtrlRead($btnPatch) = "Патч" Then
patchClient()
Else
unPatchClient()
EndIf
EndFunc
Func btnApply_Click()
;gamesetting tab needs to be closed to allow proper setting of the filters.
If checkTabVisibility($tab_gamesetting, 0x01) Then
guiCommand($str_Btn_Close, $tab_gamesetting) ; "Btn_Close"
While checkTabVisibility($tab_gamesetting, 0x01)
; just wait until closed
WEnd
EndIf
setChatFilters() ; write the new filter settings to memory
guiCommand($str_gamesetting, $tab_gamesetting) ; Open "gamesetting" tab
While checkTabVisibility($tab_gamesetting, 0x00)
; just wait until visible
WEnd
; Sleep(3000)
guiCommand($str_apply, $tab_gamesetting) ; "apply"
; Sleep(3000)
guiCommand($str_Btn_Close, $tab_gamesetting) ; "Btn_Close"
EndFunc ;==>btnApply_Click
Func checkTabVisibility($tabObj, $value)
$tabVisibility = _MemoryRead(_MemoryRead($tabObj, $pHandle) + x('o.tabVisible.offset') , $pHandle, 'byte[1]')
If $tabVisibility = $value Then
Return True
Else
Return False
EndIf
EndFunc ;==>checkTabVisibility
Func getChatFilters()
$filters = _MemoryRead($staticChatFilters, $pHandle, "byte[78]")
For $x = 0 To $columns - 1
For $y = 0 To $rows - 1
$id = $x * $rows + $y
If StringMid(Hex($filters), $id * 2 + 1, 2) = "01" Then
GUICtrlSetState($chkBox[$id], $GUI_CHECKED)
Else
GUICtrlSetState($chkBox[$id], $GUI_UNCHECKED)
EndIf
Next
Next
EndFunc ;==>getChatFilters
Func setChatFilters()
Local $stateBytes
For $i = 0 To UBound($chkBox) - 1
If GUICtrlRead($chkBox[$i]) = $GUI_CHECKED Then
$stateBytes &= "01"
Else
$stateBytes &= "00"
EndIf
Next
_MemoryWrite($staticChatFilters, $pHandle, "0x" & $stateBytes, "byte[78]")
EndFunc ;==>setChatFilters
Func patchClient()
Local $patchAddress
If $pHandle <> 0 Then
$client = GetModuleBaseByName($pid, $procName)
$data = _MemoryRead("0x" & Hex($client[1]), $pHandle, 'byte[' & $client[2] & ']')
Else
MsgBox(0, "Ошибка", "elementsclient.exe не обнаружен. Пожалуйста запустите PW перед пуском программы.")
EndIf
Local $check = StringInStr($data, $patchSearchExpression)
If $check Then
; Patch the client
$patchAddress = $client[1] + $check / 2 - 1
_MemoryWrite($patchAddress, $pHandle, "0x" & $alreadyPatchedExpression, "byte[" & StringLen($alreadyPatchedExpression) / 2 & "]")
MsgBox(0, "Состояние патча", "Клиент успешно пропатчен по адресу: " & Hex($patchAddress))
Else
$check = StringInStr($data, $alreadyPatchedExpression)
If $check Then
$patchAddress = $client[1] + $check / 2 - 1
MsgBox(0, "Состояние патча", "Клиент уже пропатчен по адресу: " & Hex($patchAddress))
GUICtrlSetData($btnPatch, "Удалить")
Else
MsgBox(0, "Ошибка", "Не найден фрагмент кода для патча" & @CRLF & "...Обновление клиента могло изменить оффсеты")
EndIf
EndIf
EndFunc ;==>patchClient
Func unPatchClient()
MsgBox(0, "", "Удаление патча()")
Local $patchAddress
If $pHandle <> 0 Then
$client = GetModuleBaseByName($pid, $procName)
$data = _MemoryRead("0x" & Hex($client[1]), $pHandle, 'byte[' & $client[2] & ']')
Else
MsgBox(0, "Ошибка", "elementsclient.exe не обнаружен. Пожалуйста запустите PW перед пуском программы")
EndIf
Local $check = StringInStr($data, $alreadyPatchedExpression)
If $check Then
; Unpatch the client
$patchAddress = $client[1] + $check / 2 - 1
_MemoryWrite($patchAddress, $pHandle, "0x" & $patchSearchExpression, "byte[" & StringLen($patchSearchExpression) / 2 & "]")
MsgBox(0, "Состояние патча", "Патч успешно удалён из клиента по адресу: " & Hex($patchAddress))
Else
$check = StringInStr($data, $patchSearchExpression)
If $check Then
$patchAddress = $client[1] + $check / 2 - 1
MsgBox(0, "Состояние патча", "Клиент еще не был пропатчен по адресу: " & Hex($patchAddress))
GUICtrlSetData($btnPatch, "Патч")
Else
MsgBox(0, "Ошибка", "Не найден фрагмент кода для патча" & @CRLF & "...Обновление клиента могло изменить оффсеты")
EndIf
EndIf
EndFunc ;==>unPatchClient
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 &= '8B401C' ; MOV EAX, DWORD PTR DS:[EAX+1C]
;$OPcode &= '8B4018' ; MOV EAX, DWORD PTR DS:[EAX+18]
;$OPcode &= '8B4008' ; MOV EAX, DWORD PTR DS:[EAX+08]
;$OPcode &= '8B80' & _hex($guiObjPtr) ; MOV EAX, DWORD PTR DS:[EAX+XXXXXXXX]
$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
Func _hex($value, $size = 8)
Local $tmp1, $tmp2, $i
$tmp1 = StringRight("000000000" & Hex($value), $size)
For $i = 0 To StringLen($tmp1) / 2 - 1
$tmp2 = $tmp2 & StringMid($tmp1, StringLen($tmp1) - 1 - 2 * $i, 2)
Next
Return $tmp2
EndFunc ;==>_hex
Func memopen($pid)
Local $mid = DllCall($kernel32, 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 1, 'int', $pid)
Return $mid[0]
EndFunc ;==>memopen
Func memclose($mid)
DllCall($kernel32, 'int', 'CloseHandle', 'int', $mid)
EndFunc ;==>memclose
Func GetModuleBaseByName($pid, $module) ; thx to lolkop for this
;Edited by dumbfck to also return process exe path
Local $hSnapshot, $me32, $bFound, $baseAddress[4]
; Create a MODULEENTRY32 structure, $me32
; http://msdn.microsoft.com/en-us/library/ms684225%28v=VS.85%29.aspx
; typedef struct tagMODULEENTRY32 {
; DWORD dwSize;
; DWORD th32ModuleID;
; DWORD th32ProcessID;
; DWORD GlblcntUsage;
; DWORD ProccntUsage;
; BYTE *modBaseAddr;
; DWORD modBaseSize;
; HMODULE hModule;
; TCHAR szModule[MAX_MODULE_NAME32 + 1];
; TCHAR szExePath[MAX_PATH];
; } MODULEENTRY32, *PMODULEENTRY32;
$me32 = DllStructCreate("int;int;int;int;int;int;int;int;char[256];char[260]")
; Set first element (dwSize) of $me32 structure as the allocated size of the structure itself
DllStructSetData($me32, 1, DllStructGetSize($me32))
; Take a snapshot of the modules used by process $PID (flag=8 specifies modules only)
; If the function succeeds, it returns an open handle to the specified snapshot.
; If the function fails, it returns INVALID_HANDLE_VALUE
; Modules are enumerated by Module32First
$hSnapshot = DllCall("kernel32.dll", "hwnd", "CreateToolhelp32Snapshot", "int", 8, "int", $pid)
; Returned INVALID_HANDLE_VALUE ?
If $hSnapshot[0] = -1 Then Return 0
; Retrieve information about the first module associated with process
; Returns TRUE if the first entry of the module list has been copied to the buffer or FALSE otherwise
; The ERROR_NO_MORE_FILES error value is returned by the GetLastError function if no modules exist
; or the snapshot does not contain module information.
; The calling application must set the dwSize member of MODULEENTRY32 to the size, in bytes, of the structure.
; To retrieve information about other modules associated with the specified process, use the Module32Next function.
$bFound = DllCall("kernel32.dll", "int", "Module32First", "ptr", $hSnapshot[0], "long", DllStructGetPtr($me32))
; Traverse module list....
If $bFound[0] Then
Do
; if module name stored in $me32 structure = filename (elementclient.exe)
If StringLower(DllStructGetData($me32, 9)) = StringLower($module) Then
; *modBaseAddr
$baseAddress[1] = DllStructGetData($me32, 6)
; modbaseSize
$baseAddress[2] = DllStructGetData($me32, 7)
; szExePath
$baseAddress[3] = DllStructGetData($me32, 10)
ExitLoop
EndIf
; Set bFound as next module in module list
$bFound = DllCall("kernel32.dll", "int", "Module32Next", "ptr", $hSnapshot[0], "long", DllStructGetPtr($me32))
; Loop until we get ERROR_NO_MORE_FILES
Until Not $bFound[0]
EndIf
; Destroy the snapshot
DllCall("kernel32.dll", "int", "CloseHandle", "int", $hSnapshot[0])
; Hopefully we have a nice base address array
; [0] = ?
; [1] = Module base address pointer
; [2] = Module base size
; [3] = Module exe path
Return $baseAddress
EndFunc ;==>GetModuleBaseByName
Func PicSetGraphics($cID, $iW, $iH)
Local Const $STM_SETIMAGE = 0x0172
Local Const $IMAGE_BITMAP = 0
Local $hWnd, $hBitmap, $hImage, $hGraphic, $hBrush, $hBrush1, $hbmp, $aBmp
$hWnd = GUICtrlGetHandle($cID)
_GDIPlus_Startup()
$hBitmap = _WinAPI_CreateSolidBitmap($hGui, 0x192127, $iW, $iH) ; or use next command
$hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
GDIPlus_SetAngledText($hGraphic, "Общий", 116, 31, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Группа", 139, 39, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Клан", 170, 35, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Шепот", 200, 34, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Торг", 223, 42, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Инфо", 253, 35, -60, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Общий", 54, 80, 0, "", 12, 0xFFCED0D2)
GDIPlus_SetAngledText($hGraphic, "Мир", 59, 100, 0, "", 12, 0xFFCFBB06)
GDIPlus_SetAngledText($hGraphic, "Группа", 55, 120, 0, "", 12, 0xFF03D006)
GDIPlus_SetAngledText($hGraphic, "Клан", 52, 140, 0, "", 12, 0xFF03D0CF)
GDIPlus_SetAngledText($hGraphic, "Шепот", 50, 160, 0, "", 12, 0xFFDF439C)
GDIPlus_SetAngledText($hGraphic, "Урон", 50, 180, 0, "", 12, 0xFFA8A9AA)
GDIPlus_SetAngledText($hGraphic, "Бой", 50, 200, 0, "", 12, 0xFFCFB606)
GDIPlus_SetAngledText($hGraphic, "Торг", 59, 220, 0, "", 12, 0xFFCF6C06)
GDIPlus_SetAngledText($hGraphic, "Система", 52, 240, 0, "", 12, 0xFFB2C58B)
GDIPlus_SetAngledText($hGraphic, "Обьявл.", 52, 260, 0, "", 12, 0xFFEE3402)
GDIPlus_SetAngledText($hGraphic, "Разное", 59, 280, 0, "", 12, 0xFF8793E1)
GDIPlus_SetAngledText($hGraphic, "Other", 59, 300, 0, "", 12, 0xFF8793E1)
GDIPlus_SetAngledText($hGraphic, "Горн", 59, 320, 0, "", 12, 0xFF8793E1)
; Keeps all GDIPlus graphics visible
$hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
$aBmp = DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hbmp)
_WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME))
; Save Graphics on picture control
If $aBmp[0] <> 0 Then _WinAPI_DeleteObject($aBmp[0])
_GDIPlus_ImageDispose($hImage)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphic)
_WinAPI_DeleteObject($hbmp)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_Shutdown()
EndFunc ;==>PicSetGraphics
Func _Quit()
Exit
EndFunc ;==>_Quit
; #FUNCTION# ================================================================
; Name...........: GDIPlus_SetAngledText
; Description ...: Adds text to a graphic object at any angle.
; Syntax.........: GDIPlus_SetAngledText($hGraphic, $nText, [$iCentreX, [$iCentreY, [$iAngle , [$nFontName , _
; [$nFontSize, [$iARGB, [$iAnchor]]]]]]] )
; Parameters ....: $hGraphic - The Graphics object to receive the added text.
; $nText - Text string to be displayed
; $iCentreX - Horizontal coordinate of horixontal centre of the text rectangle (default = 0 )
; $iCentreY - Vertical coordinate of vertical centre of the text rectangle (default = 0 )
; $iAngle - The angle which the text will be place in degrees. (default = "" or blank = 0 )
; $nFontName - The name of the font to be used (default = "" or Blank = "Arial" )
; $nFontSize - The font size to be used (default = "" or Blank = 12 )
; $iARGB - Alpha(Transparency), Red, Green and Blue color (0xAARRGGBB) (Default= "" = random color
; or Default = Blank = 0xFFFF00FF )
; $iAnchor - If zero (default) positioning $iCentreX, $iCentreY values refer to centre of text string.
; If not zero positioning $iCentreX, $iCentreY values refer to top left corner of text string.
; Return values .: 1
; Author ........: Malkey
; Modified.......:
; Remarks .......: Call _GDIPlus_Startup() before starting this function, and call _GDIPlus_Shutdown()after function ends.
; Can enter calculation for Angle Eg. For incline, -ATan($iVDist / $iHDist) * 180 / $iPI , where
; $iVDist is Vertical Distance, $iHDist is Horizontal Distance, and, $iPI is Pi, (an added Global Const).
; When used with other graphics, call this function last. The MatrixRotate() may affect following graphics.
; Related .......: _GDIPlus_Startup(), _GDIPlus_Shutdown(), _GDIPlus_GraphicsDispose($hGraphic)
; Link ..........;
; Example .......; Yes
; ========================================================================================
Func GDIPlus_SetAngledText($hGraphic, $nText, $iCentreX = 0, $iCentreY = 0, $iAngle = 0, $nFontName = "Arial", _
$nFontSize = 12, $iARGB = 0xFFFF00FF, $iAnchor = 0)
Local $x, $y, $iX, $iY, $iWidth, $iHeight
Local $hMatrix, $iXt, $iYt, $hBrush, $hFormat, $hFamily, $hFont, $tLayout
; Default values
If $iAngle = "" Then $iAngle = 0
If $nFontName = "" Or $nFontName = -1 Then $nFontName = "Arial" ; "Microsoft Sans Serif"
If $nFontSize = "" Then $nFontSize = 12
If $iARGB = "" Then ; Randomize ARGB color
$iARGB = "0xFF" & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2) & Hex(Random(0, 255, 1), 2)
EndIf
$hFormat = _GDIPlus_StringFormatCreate(0)
$hFamily = _GDIPlus_FontFamilyCreate($nFontName)
$hFont = _GDIPlus_FontCreate($hFamily, $nFontSize, 1, 3)
$tLayout = _GDIPlus_RectFCreate($iCentreX, $iCentreY, 0, 0)
$aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $nText, $hFont, $tLayout, $hFormat)
$iWidth = Ceiling(DllStructGetData($aInfo[0], "Width"))
$iHeight = Ceiling(DllStructGetData($aInfo[0], "Height"))
;Later calculations based on centre of Text rectangle.
If $iAnchor = 0 Then ; Reference to middle of Text rectangle
$iX = $iCentreX
$iY = $iCentreY
Else ; Referenced centre point moved to top left corner of text string.
$iX = $iCentreX + (($iWidth - Abs($iHeight * Sin($iAngle * $iPI / 180))) / 2)
$iY = $iCentreY + (($iHeight + Abs($iWidth * Sin($iAngle * $iPI / 180))) / 2)
EndIf
;Rotation Matrix
$hMatrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($hMatrix, $iAngle, 1)
_GDIPlus_GraphicsSetTransform($hGraphic, $hMatrix)
;x, y are display coordinates of center of width and height of the rectanglular text box.
;Top left corner coordinates rotate in a circular path with radius = (width of text box)/2.
;Parametric equations for a circle, and adjustments for centre of text box
$x = ($iWidth / 2) * Cos($iAngle * $iPI / 180) - ($iHeight / 2) * Sin($iAngle * $iPI / 180)
$y = ($iWidth / 2) * Sin($iAngle * $iPI / 180) + ($iHeight / 2) * Cos($iAngle * $iPI / 180)
;Rotation of Coordinate Axes formulae - To display at x and y after rotation, we need to enter the
;x an y position values of where they rotated from. This is done by rotating the coordinate axes.
;Use $iXt, $iYt in _GDIPlus_RectFCreate. These x, y values is the position of the rectangular
;text box point before rotation. (before translation of the matrix)
$iXt = ($iX - $x) * Cos($iAngle * $iPI / 180) + ($iY - $y) * Sin($iAngle * $iPI / 180)
$iYt = -($iX - $x) * Sin($iAngle * $iPI / 180) + ($iY - $y) * Cos($iAngle * $iPI / 180)
$hBrush = _GDIPlus_BrushCreateSolid($iARGB)
$tLayout = _GDIPlus_RectFCreate($iXt, $iYt, $iWidth, $iHeight)
_GDIPlus_GraphicsDrawStringEx($hGraphic, $nText, $hFont, $tLayout, $hFormat, $hBrush)
; Clean up resources
_GDIPlus_MatrixDispose($hMatrix)
_GDIPlus_FontDispose($hFont)
_GDIPlus_FontFamilyDispose($hFamily)
_GDIPlus_StringFormatDispose($hFormat)
_GDIPlus_BrushDispose($hBrush)
$tLayout = ""
Return 1
EndFunc ;==>GDIPlus_SetAngledText
Func Color_SetHSL($iHue, $Saturation = 180, $Brightness = 160)
If IsArray($iHue) Then
$aInput = $iHue
Else
Local $aInput[3] = [$iHue, $Saturation, $Brightness]
EndIf
Local $aiRGB = _ColorConvertHSLtoRGB($aInput)
Return "0x" & Hex(Round($aiRGB[0]), 2) & Hex(Round($aiRGB[1]), 2) & Hex(Round($aiRGB[2]), 2)
EndFunc ;==>Color_SetHSL
Для успешной компилляции также необходим файл NomadMemory.au3 - свободно доступный для скачивания в сети.
Для тех же, кто верит в чистоту намерений, и порядочность людей создавших эту программу, и сделавших её доступной для РУ оффа - выкладываю скомпиллированный .ехе
В интерфейсе программы:
3. В программе из разворачивающегося меню выбираем имя персонажа.
4. Нажимаем кнопку Прикрепить, ожидаем подтверждения, нажимаем ОК
5. Нажимаем кнопку Патч, ожидаем подтвеждения. Время зависит от быстродействия ЦПУ и ОЗУ. Если по истечении 15 -30 секунд подтверждения нет, нажимаем еще раз. Важно ! Необходимо получить подтверждение успешности патча.
6.Настраиваем фильтрацию чата. Галочки указывают на разрешение данного канала в соответствующем окне чата.
7. Нажимаем Применить.
7.1 если окон несколько: выбираем имя следующего персонажа, повторяем пункты 4-7.
Настройки сохраняются при релоге , и использовании внутриигровой панели настроек.
8. Если всё работает возвращаемся в эту тему и нажимаем спасибо
Если необходимо переименовать одно из окон - закрываем программу, меняем имя окна. Настройки в окнах при закрытии программы сохраняются. При повторном включении программа полностью синхронизируется с окнами к которым вы её прикрепите. По новой настраивать ничего не придется.
При открытии нового окна/ окон - используем кнопку "Обновить"
Для отключения окна горнов - найдете кнопку
Кроме поддержки нескольких окон, программа приобрела свою иконку -
[Ссылки могут видеть только зарегистрированные пользователи. ]
________________
Не люблю давать глупые ответы ) По этому глупые вопросы - в игноре
Последний раз редактировалось t212; 07.01.2012 в 22:18.
Причина: Обновление
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Это потрясающе ! Наверное самая крутая прога для пв за последнее время
Кроме очевидных достоинств, порадовала возможность отрубить обычные (белые) надписи в общем чате и оставить только мир. Слава автору и ТС!
__
Да, я что-то протупил от радости ) белый чат и так оффнуть можно.
Последний раз редактировалось ktulx; 18.11.2011 в 06:33.
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Неплохо, только вот 90% того что дает прога, делается в самом клиенте игры. В чате ставь или убирай галочки, читать или не читать. Единственное что убирает системный чат и горн. Если бы она еще убивала всплывающее окно горна, тогда да, сенсация. А так ручками пришлось перелопатить кучу файлов))
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Вот вопрос такой имеется, к какому виду чата относится хрень про дуэли? вычистил всё, так теперь окно чата засирается тем, что конь педальный победил педаль конскую в дуэли.
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
нитроген заколебал удалять сообщения! как я тыкну спасибку если ты все мои сообщения тупо удаляешь! и это не флуд а благодарность! только вот почемуто от этой проги чат на аукцион ни как не убераеться! кто подскажет что надо сделать?
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Цитата:
Сообщение от akeks249
нитроген заколебал удалять сообщения! как я тыкну спасибку если ты все мои сообщения тупо удаляешь! и это не флуд а благодарность!
да?
Цитата:
Даже в разделе багов допускается наличие в каждой теме по несколько нормальных/грамотных/адекватных сообщений с благодарностями (например - "Спасибо автору за идею, помогло в том-то и то"). Если сообщений с благодарностями в какой-то конкретной теме становится слишком много - удалять, оставив лишь несколько наиболее вразумительных. Сообщение "спс робит" является нарушением сразу двух пунктов правил (флуд + орфография) и наказывается сразу красной карточкой
рассмотрим твою благодарность
Цитата:
Автору спс и создателю! как 10 сообщений наберу тыкну спасибку!
в данном случае я вижу лишь флуд с целью набить посты, к тому же ты не блещешь орфографией
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Автору большое спасибо за труды, но есть проблема, при запуске 2х и более окон программа корректно работает только с первым запущенным, ники остальных не определяются корректно, патч проходит, при попытке нажать кнопку "Применить" клиент падает. приложение зависает. Тут возникает проблема первыми клиентами обычно весят торговые коты, и в клиенте котором нужно внести изменения(игровой персонаж) невозможно внести изменения. В общем это не есть гуд) надо исправить, в AutoIt я не шарю, в обще не понимаю что там написано, может и подсказал-бы где проблема.
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Цитата:
Сообщение от VitMit
Автору большое спасибо за труды, но есть проблема, при запуске 2х и более окон программа корректно работает только с первым запущенным, ники остальных не определяются корректно, патч проходит, при попытке нажать кнопку "Применить" клиент падает. приложение зависает. Тут возникает проблема первыми клиентами обычно весят торговые коты, и в клиенте котором нужно внести изменения(игровой персонаж) невозможно внести изменения. В общем это не есть гуд) надо исправить, в AutoIt я не шарю, в обще не понимаю что там написано, может и подсказал-бы где проблема.
попробуй ренеймером окошки переименовать во что нибудь, как я понял из сорцов, скрипт ищет окно Perfect World, по идее, проблема должна исчезнуть
Re: Серебрянная пуля против Вея Сябао и флудерастов с горнами
Цитата:
Сообщение от InakI
попробуй ренеймером окошки переименовать во что нибудь, как я понял из сорцов, скрипт ищет окно Perfect World, по идее, проблема должна исчезнуть
Нет так тоже не пашет, но заметил еще 1ну проблему, после запуска этой программы, еще и Window Renamer стал глючить, не видет окон PW, сворачиваеш разворачиваеш по 1 разу каждое окно, начинает видеть. Проблема выше описанная по прежнему не решена.