Skip to content

Instantly share code, notes, and snippets.

@robertabcd
Created December 5, 2010 07:32
Show Gist options
  • Save robertabcd/728918 to your computer and use it in GitHub Desktop.
Save robertabcd/728918 to your computer and use it in GitHub Desktop.
; (x) Z0MBiE 2010
; 3.3.2 Run lua Protected shit
; Same Use as luafoo
; create a macro using:
; ex: /run Do("MoveForwardStart(0)")
; ex: /run Do( "CastSpellByName(\"Flash Heal\");" )
;
#include <Asm.au3>
#include <Misc.au3>
#include <Array.au3>
#include <Memory.au3>
#include <_Distorm.au3>
#include <NomadMemory.au3>
; dont remove that or we cant write to wow process memory
#requireadmin
;
; WOW 3.3.5a MEMORY OFFSET CONSTANTS
;
Global Const $DX_DEVICE = 0x00C5DF88 ; 3.3.3a 0x00BB672C ; 3.3.2 0x00C776B8 ; 3.3.0 0x00C76668 ; 3.1.3 0x0113C290
Global Const $DX_DEVICE_IDX = 0x397C
Global Const $ENDSCENE_IDX = 0xA8
;
Global Const $OBJECTMGR_BASE = 0x00C79CE0 ; 3.3.3a 0x00BB43F0 ; 3.3.2 0x00C93410 ; 3.3.0 0x00C923C0 ; 3.1.3 0x01139F80
Global Const $OBJECTMGR_IDX = 0x2ED0 ; 3.3.3a 0x2EB0 ; 3.3.2 0x2E04 ; 3.3.0 0x2E04 ; 3.1.3 0x2C34
;
Global Const $PLAYER_BASE = 0x00CD87A8 ; 3.3.3a 0x00B366D0 ; 3.3.2 0x00CF8C50
Global Const $PLAYER_IDX1 = 0x34
Global Const $PLAYER_IDX2 = 0x24
; functions
Global Const $lua_dostring = 0x00819210 ; 3.3.3a 0x004B32B0 3.3.2 0x007F25C0 ; 3.3.0 0x007F1F40 ; 3.1.3 0x0049AAB0
Global Const $lua_register = 0x00817F90 ; 3.3.3a 0x004B2030 3.3.2 0x007F1340 ; 3.3.0 0x007F0CC0 ; 3.1.3 0x004998E0
Global Const $lua_gettop = 0x0084DBD0 ; 3.3.3a 0x00488A80 3.3.2 0x00826D80 ; 3.3.0 0x00826680 ; 3.1.3 0x0091A8B0
Global Const $lua_tostring = 0x0084E0E0 ; 3.3.3a 0x00488F90 3.3.2 0x00827290 ; 3.3.0 0x00826B90 ; 3.1.3 0x0091ADC0
; constant stub data area size
Global Const $STUB_DATA_SIZE = 4096
; Setting privilege
SetPrivilege( "SeDebugPrivilege", 1 )
; Open wow process to hook endscene
$wow = _MemoryOpen(WinGetProcess("World of Warcraft"))
; Makes sure WoW is open
If @error == 1 then
MsgBox( 0x1010, "Error", "World of Warcraft Process not found!")
Exit
EndIf
; check if user is logged In
if GetPlayerBaseAddress( $wow ) = 0 Then
_MemoryClose( $wow )
MsgBox( 0x1010, "Error", "Login to your World of Warcraft account first!")
Exit
endif
; check if LuaRegister callback was injected
$pCodeCave = Function_Find( $wow, $lua_register, "IsHookJump" )
; did we find code cave?
if $pCodeCave == 0 then
; inject the lua register callback
$pLuaRegisterCb = Function_Inject( $wow, STUB_LuaRegisterCallback() )
; create invalid ptr jump patch
$jmpcb = HookJump_Create( $pLuaRegisterCb )
$jmpcb_size = HookJump_GetSize( $jmpcb )
; search for unused bytes
$pCodeCave = Function_Find( $wow, $lua_register, "IsEmptyCC" )
; deprotect CodeCave
DllCall("Kernel32.dll", "int", "VirtualProtect", "ptr", $pCodeCave, "long", $jmpcb_size, "dword", 0x40, "dword*", 0 )
; write redirect
HookJump_Write( $wow, $pCodeCave, $jmpcb )
endif
; register lua do function
LuaRegister( $wow, "Do", $pCodeCave )
; show some shit
DoString( $wow, "DEFAULT_CHAT_FRAME:AddMessage(""Do() injected !!!"", 1, 0, 0);" );
; close wow memory
_MemoryClose( $wow )
Exit
;
; MISC
;
Func GetPlayerBaseAddress( $wow )
$base = _MemoryRead("0x" & hex($PLAYER_BASE), $wow, "dword")
$base_2 = _MemoryRead("0x" & hex($base + $PLAYER_IDX1), $wow, "dword")
$base_3 = _MemoryRead("0x" & hex($base_2 + $PLAYER_IDX2), $wow, "dword")
return $base_3
EndFunc
;//////////////////
; clazz comparator
; //////////////////
;
; Comparator to find 0xCC alignment areas
;
Func IsEmptyCC( $sig ) ;extends comparator
$size = HookJump_GetSize( 0 )
; return comparator size
if IsNumber( $sig ) and $sig == 0 then
return $size
endif
; check for 0xCC repeated $size times
$cc_arr = StringSplit( hex( $sig ), "CC", 1 )
if $cc_arr[0] == $size + 1 Then
return true;
else
return false
endif
EndFunc
;
; comparator checks if $sig is a hook jump
;
Func IsHookJump( $sig ) ;extends comparator
; comparator chunk size
if IsNumber( $sig ) and $sig == 0 Then
return HookJump_GetSize( $sig )
endif
; 0x68, 0xC3, 0x90
return ( hex( BinaryMid( $sig, 1, 1 ) ) == "68" and _
hex( BinaryMid( $sig, 6, 1 ) ) == "C3" and hex( BinaryMid( $sig, 7, 1 ) ) == "90" )
EndFunc
;
; write according to endscene hook stub layout
;
Func LuaRegister( $wow, $cb_name, $cb_func )
; struct layout
$t_data = "dword dwAddress;" & _ ; $lua_register
"char szAddressType[12];" & _ ; cdecl
"dword dwParamCount;" & _ ; 2
"dword dwParam1;" & _ ; offset $cb_name
"dword dwParam2;" & _ ; $cb_func
"char szParam1[64];" ; $cb_name
; create struct
$data = DllStructCreate( $t_data )
; set parameters
DllStructSetData( $data, "dwFlag", 1 )
DllStructSetData( $data, "dwParamCount", 2 )
DllStructSetData( $data, "dwAddress", $lua_register )
DllStructSetData( $data, "szAddressType", "cdecl" )
DllStructSetData( $data, "dwParam1", DllStructGetPtr( $data, "szParam1" ) )
DllStructSetData( $data, "dwParam2", $cb_func )
DllStructSetData( $data, "szParam1", $cb_name )
return EndScene_CallFunction( $wow, $data )
EndFunc
;
; Injected callback to run protected lua
;
Func STUB_LuaRegisterCallback()
$Asm = AsmInit()
AsmReset($Asm)
; offsets used in stub
Local Const $dwLuaState = "ebp + 20h + 8"
; enter
AsmAdd($Asm, "pushad")
AsmAdd($Asm, "push ebp")
AsmAdd($Asm, "mov ebp, esp")
; get count arguments
AsmAdd($Asm, "push dword ["& $dwLuaState &"]") ; luastate*
AsmAdd($Asm, "mov eax, " & hex( $lua_gettop ) & "h")
AsmAdd($Asm, "call eax")
AsmAdd($Asm, "add esp, 4")
; check if any argument was given
AsmAdd($Asm, "or eax, eax")
AsmAdd($Asm, "jz $+35") ; exit
; get command to be run
AsmAdd($Asm, "push 0")
AsmAdd($Asm, "push eax")
AsmAdd($Asm, "push dword ["& $dwLuaState &"]") ; luastate*
AsmAdd($Asm, "mov eax, " & hex( $lua_tostring ) & "h")
AsmAdd($Asm, "call eax")
AsmAdd($Asm, "add esp, 0Ch")
; check if valid
AsmAdd($Asm, "or eax, eax")
AsmAdd($Asm, "jz $+17") ; exit
; execute command
AsmAdd($Asm, "push 0" )
AsmAdd($Asm, "push eax" )
AsmAdd($Asm, "push eax" )
AsmAdd($Asm, "mov eax, " & hex( $lua_dostring ) & "h" )
AsmAdd($Asm, "call eax" )
AsmAdd($Asm, "add esp, 0Ch" )
; leave
AsmAdd($Asm, "exit:")
AsmAdd($Asm, "mov esp, ebp")
AsmAdd($Asm, "pop ebp")
AsmAdd($Asm, "popad")
AsmAdd($Asm, "xor eax, eax")
AsmAdd($Asm, "ret")
return $Asm
EndFunc
;
; write according to endscene hook stub layout
;
Func DoString( $wow, $cmd, $file = $cmd, $unk = 0 )
; struct layout
$t_data = "dword dwAddress;" & _ ; $lua_dostring
"char szAddressType[12];" & _ ; cdecl
"dword dwParamCount;" & _ ; 3
"dword dwParam1;" & _ ; offset $cmd
"dword dwParam2;" & _ ; offset $file
"dword dwParam3;" & _ ; $unk
"char szParam1[512];" & _ ; $cmd
"char szParam2[512];" ; $file
; create struct
$data = DllStructCreate( $t_data )
; set parameters
DllStructSetData( $data, "dwAddress", $lua_dostring )
DllStructSetData( $data, "szAddressType", "cdecl" )
DllStructSetData( $data, "dwParamCount", 3 )
DllStructSetData( $data, "dwParam1", DllStructGetPtr( $data, "szParam1" ) )
DllStructSetData( $data, "dwParam2", DllStructGetPtr( $data, "szParam2" ) )
DllStructSetData( $data, "dwParam3", $unk )
DllStructSetData( $data, "szParam1", $cmd )
DllStructSetData( $data, "szParam2", $file )
return EndScene_CallFunction( $wow, $data )
EndFunc
;
; Asm++
;
Func AsmSize( $asm )
return $asm[2]
EndFunc
;
; clazz EndScene
;
;
; tells the endscene hook to run something
;
Func EndScene_CallFunction( $wow, $data )
; get endscene function address
$pEndScene = EndScene_GetAddress( $wow )
; get address of end scene function hook
$pEndSceneHook = HookJump_GetAddress( $wow, $pEndScene )
; not hooked?
if $pEndSceneHook == 0 Then
$stubEndSceneHook = STUB_EndSceneHook()
$pEndSceneHook = Function_Inject( $wow, $stubEndSceneHook )
Function_Hook( $wow, $pEndScene, $pEndSceneHook, AsmSize( $stubEndSceneHook ) )
endif
; data_area is right beyond function
$data_area = $pEndSceneHook + EndScene_GetHookSize( $wow, $pEndSceneHook )
; build command struct
$t_cmd = "dword dwRetVal;" & _ ; function return value
"dword dwFlag;" ; 1=call function 0=ready to call
$cmd = DllStructCreate( $t_cmd )
$cmd_size = DllStructGetSize( $cmd )
; get pointer to it
$p_data = DllStructGetPtr( $data )
; fix dwParamX offsets
$param_count = DllStructGetData( $data, "dwParamCount" )
for $i = 1 to $param_count
$dwParamX = DllStructGetData( $data, "dwParam" & $i )
$j = 4 + $param_count
do
$pParamX = DllStructGetPtr( $data, $j )
if @error == 0 and hex( $dwParamX ) == hex( $pParamX ) Then
DllStructSetData( $data, "dwParam" & $i, $pParamX - $p_data + $data_area + $cmd_size )
endif
$j = $j + 1;
until $pParamX == 0
next
; set run flag
DllStructSetData( $cmd, "dwFlag", 1 )
; write execution parameters
DllCall( $wow[0], 'int', 'WriteProcessMemory', 'int', $wow[1], 'int', $data_area + $cmd_size, 'ptr', $p_data, 'int', DllStructGetSize( $data ), 'int', '')
; write command data
DllCall( $wow[0], 'int', 'WriteProcessMemory', 'int', $wow[1], 'int', $data_area, 'ptr', DllStructGetPtr( $cmd ), 'int', $cmd_size, 'int', '')
; wait execution
do
$sig = _MemoryRead( $data_area, $wow, "byte[8]" )
$dwRetVal = DllStructSetData( $cmd, "dwRetVal", "0x" & hex( BinaryMid( $sig, 1, 4 ) ) )
$dwFlag = DllStructSetData( $cmd, "dwFlag" , "0x" & hex( BinaryMid( $sig, 5, 4 ) ) )
until $dwFlag == 0
; return value
return $dwRetVal
EndFunc
;
; Returns the size of the EndSceneHook + Original Bytes + Back Jump
;
Func EndScene_GetHookSize( $wow, $pEndSceneHook )
; return jump marks the end
$pAddress = Function_Find( $wow, $pEndSceneHook, "IsHookJump" )
if $pAddress <> 0 Then
return ($pAddress - $pEndSceneHook) + HookJump_GetSize( $pAddress )
else
return 0
endif
EndFunc
;
; returns endscene function address
;
Func EndScene_GetAddress( $wow )
$pDevice = _MemoryRead( "0x" & hex( $DX_DEVICE ) , $wow, "dword")
$p1 = _MemoryRead( $pDevice + $DX_DEVICE_IDX, $wow, "dword")
$p2 = _MemoryRead( $p1 , $wow, "dword")
$pEndScene = _MemoryRead( $p2 + $ENDSCENE_IDX , $wow, "dword")
return $pEndScene
EndFunc
;
; This is the endscene injected hook code
; It can just call any function in wow process
; data area starts in GetEndSceneHookAddress() + GetEndSceneHookSize()
;
; layout: (ebp register)
;
; 0 dword dwRetVal ---- function return value
; 4 dword dwFlag ---- 1=call function 0=ready to call
; 8 dword dwAddress ---- function address to call
; 12 char szAddressType[12] ---- cdecl, stdcall, thiscall
; 24 dword dwParamCount ---- number of function parameters
; ...... (according to dwParamCount)
; 28 dword dwParam1 ---- dword parameter 1
; 32 dword dwParam2 ---- dword parameter 2
; 36 dword dwParamN ---- dword parameter N
;
Func STUB_EndSceneHook()
$Asm = AsmInit()
AsmReset($Asm)
; offsets used in stub
Local Const $dwRetVal = "ebp"
Local Const $dwFlag = "ebp + 04h"
Local Const $dwAddress = "ebp + 08h"
Local Const $szAddressType = "ebp + 0Ch"
Local Const $dwParamCount = "ebp + 18h"
; function type constants
Local Const $dwAddrTypeCdecl = 0x63656463 ; 'cdec'
Local Const $dwAddrTypeStdcall = 0x63647473 ; 'stdc'
Local Const $dwAddrTypeThiscall = 0x73696874 ; 'this'
; save 'n start
AsmAdd($Asm, "pushad")
AsmAdd($Asm, "pushfd")
; delta
AsmAdd($Asm, "call $+5")
AsmAdd($Asm, "pop ebp")
AsmAdd($Asm, "add ebp, 0ACh") ; data area
; check activity flag
AsmAdd($Asm, "cmp dword ["& $dwFlag &"], 1")
AsmAdd($Asm, "jnz $+8B") ;exit
; clean flag to avoid re-entering
AsmAdd($Asm, "xor eax, eax")
AsmAdd($Asm, "mov dword ["& $dwFlag &"], eax")
; UpdateCurMgr
AsmAdd($Asm, "mov eax, fs:[2Ch]")
AsmAdd($Asm, "mov eax, [eax]")
AsmAdd($Asm, "add eax, 0x10")
AsmAdd($Asm, "mov edx, [" & hex($OBJECTMGR_BASE) & "h]")
AsmAdd($Asm, "mov edx, [edx + " & hex( $OBJECTMGR_IDX ) & "h]")
AsmAdd($Asm, "mov [eax], edx")
; check if parameter count = 0
AsmAdd($Asm, "mov edx, ["& $dwParamCount &"]") ; parameter count
AsmAdd($Asm, "or edx, edx")
AsmAdd($Asm, "jz $+22") ; callf [ __stdcall/__cdecl type func( void ) ]
; load data area parameters address
AsmAdd($Asm, "std")
AsmAdd($Asm, "lea esi, [edx * 4 +"& $dwParamCount &"]")
; check if __thiscall
AsmAdd($Asm, "mov eax, ["& $szAddressType &"]")
AsmAdd($Asm, "cmp eax, "& hex( $dwAddrTypeThiscall ) &"h")
AsmAdd($Asm, "jnz $+7") ; cycle
; *this
AsmAdd($Asm, "lodsd")
AsmAdd($Asm, "xchg eax, ecx") ; __thiscall
AsmAdd($Asm, "dec edx")
AsmAdd($Asm, "jz $+8") ; callf [ __thiscall type func( void ) ]
; push cycle
AsmAdd($Asm, "cycle:")
AsmAdd($Asm, "lodsd")
AsmAdd($Asm, "push eax") ; push cycle
AsmAdd($Asm, "dec edx")
AsmAdd($Asm, "jnz @cycle")
; call function
AsmAdd($Asm, "callf:")
AsmAdd($Asm, "cld") ; very important
AsmAdd($Asm, "call dword ["& $dwAddress &"]") ; call function
; fix stack
AsmAdd($Asm, "mov ebx, ["& $szAddressType &"]")
AsmAdd($Asm, "cmp ebx, "& hex( $dwAddrTypeCdecl ) &"h")
AsmAdd($Asm, "jnz $+13") ; save_ret
; fix stack cdecl
AsmAdd($Asm, "mov ebx, ["& $dwParamCount &"]")
AsmAdd($Asm, "shl ebx, 2")
AsmAdd($Asm, "add esp, ebx")
; save ret val
AsmAdd($Asm, "save_ret:")
AsmAdd($Asm, "mov ["& $dwRetVal &"], eax")
; clear data area
AsmAdd($Asm, "xor eax, eax")
AsmAdd($Asm, "mov ecx, "& hex( $STUB_DATA_SIZE ) &"h")
AsmAdd($Asm, "lea edi, ["& $dwFlag &"]")
AsmAdd($Asm, "rep stosb")
; restore 'n finish
AsmAdd($Asm, "exit:")
AsmAdd($Asm, "popfd")
AsmAdd($Asm, "popad")
return $Asm
EndFunc
; ////////////////
; clazz HookJump
;/////////////////
Func HookJump_Create( $pAddress )
$jmp = AsmInit()
AsmAdd( $jmp, "push " & hex( $pAddress ) & "h" )
AsmAdd( $jmp, "ret")
AsmAdd( $jmp, "nop")
return $jmp
EndFunc
;
; returns hook address or 0 to indicate not hooked yet
;
Func HookJump_GetAddress( $wow, $pAddress )
$sig = _MemoryRead( $pAddress, $wow, "byte[8]" )
if IsHookJump( $sig ) then
; omfg, 500k - bswap
$pHook = BitShift("0x"& hex(BinaryMid( $sig, 2, 1 )), -00 ) + _
BitShift("0x"& hex(BinaryMid( $sig, 3, 1 )), -08 ) + _
BitShift("0x"& hex(BinaryMid( $sig, 4, 1 )), -16 ) + _
BitShift("0x"& hex(BinaryMid( $sig, 5, 1 )), -24 )
return $pHook
endif
return 0
EndFunc
;
; returns size of a hook jump
;
Func HookJump_GetSize( $jmp )
if IsArray( $jmp ) then
return AsmSize( $jmp )
else
return AsmSize( HookJump_Create( $jmp ) )
endif
EndFunc
;
; Write HookJump to some address
;
Func HookJump_Write( $wow, $pAdress, $jmp )
_MemoryWrite( $pAdress, $wow, AsmGetBinary( $jmp ), "byte["& AsmSize( $jmp ) &"]" )
EndFunc
; ///////////////////////////
; clazz Function
; ///////////////////////////
;
; Search for pattern starting at $f_start and calls $f_comparator function
; to compare.
;
Func Function_Find( $wow, $f_start, $f_comp )
Local Const $MAX_FIND_RANGE = 4096
; request size of chunk from comparator
$comp_buf_size = Call( $f_comp, 0 )
; if no valid function name was given
if @error = 0xDEAD and @extended = 0xBEEF then
return 0
endif
; read bytes
$mem = _MemoryRead( $f_start, $wow, "byte[" & $MAX_FIND_RANGE & "]" )
; search starts at $f_start
For $i = 1 to $MAX_FIND_RANGE - $comp_buf_size
$sig = BinaryMid( $mem, $i, $comp_buf_size )
; call comparator
if Call( $f_comp, $sig ) == true then
return $f_start + ($i - 1)
endif
Next
return 0
EndFunc
;
; inject some asm shit inside another process
;
Func Function_Inject( $wow, $stub )
; get stub size
$stub_size = AsmSize( $stub )
; allocate memory to store injected code
$stub_mem = _MemVirtualAllocEx( $wow[1], 0, $stub_size + $STUB_DATA_SIZE, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE )
; write stub
_MemoryWrite( $stub_mem, $wow, AsmGetBinary( $stub ), "byte["& $stub_size &"]" )
; return address
return $stub_mem
EndFunc
;
; hook $pFunc redirecting to $pHook
;
Func Function_Hook( $wow, $pFunc, $pHook, $dwHookSize )
; max instruction count read from function to be hooked
Local Const $ORIG_ISTR_SIZE = 64
; read original hook bytes
$orig = _MemoryRead( $pFunc, $wow, "byte["& $ORIG_ISTR_SIZE &"]" )
; avoid rehook
If IsHookJump( $orig ) Then
return -1
EndIf
; save original instructions beyond hook code
_MemoryWrite( $pHook + $dwHookSize, $wow, $orig, "byte["& $ORIG_ISTR_SIZE &"]" )
; prepare pointer for api call
$orig_ptr = DllStructCreate("byte["& $ORIG_ISTR_SIZE &"]")
DllStructSetData( $orig_ptr, 1, $orig )
; create hook jump
$jmpto = HookJump_Create( $pHook )
; create bufffer to store instruction disasm info
$DecodeArray = DllStructCreate("byte[" & $sizeofDecodedInst * $ORIG_ISTR_SIZE & "]")
; disasm original bytes
$ret = distorm_decode( 0, DllStructGetPtr( $orig_ptr ), $ORIG_ISTR_SIZE, $Decode32Bits, DllStructGetPtr( $DecodeArray ), $ORIG_ISTR_SIZE )
; parse until we can jump back
$sumsize = 0
if $ret[0] == $DECRES_SUCCESS Then
for $i = 0 To $ret[1] ; number of decoded instructions
; get size of 1 instruction
$instr = DllStructCreate($tagDecodedInst, DllStructGetPtr($DecodeArray) + ($i * $sizeofDecodedInst))
$sumsize += DllStructGetData($instr, "size")
; check if we copied enough instructions
if $sumsize >= HookJump_GetSize( $jmpto ) Then
$jmpback = HookJump_Create( $pFunc + $sumsize )
; write jump back
HookJump_Write( $wow, $pHook + $dwHookSize + $sumsize, $jmpback )
ExitLoop
Endif
Next
Endif
; write jump hook
HookJump_Write( $wow, $pFunc, $jmpto )
; ok
return 0
EndFunc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment