Mspro_v3.asm.586
.model flat, stdcall
; Common dependencies
include windows.inc
include kernel32.inc
include user32.inc
include shlwapi.inc
include gdi32.inc
includelib kernel32.lib
includelib user32.lib
includelib shlwapi.lib
includelib gdi32.lib
; function prototypes
Hook_CBT proto nCode
WORD, wParam
WORD, lParam
WORD
HideModule proto hModule
WORD
GenerateBeep proto KeyState
WORD
NumLock_Toggle proto State
WORD
HandleKeyPress proto vKey
WORD, KeyState
WORD, EventHandler
WORD
ScaleToClientRect proto X
WORD, Y
WORD
ConvertToGreyscale proto crColor
WORD
GetPixel proto hDC
WORD, x
WORD, y
WORD
SendInput proto cInputs
WORD, pInputs
WORD, cbSize
WORD
keybd_event proto bVk:WORD, bScan:WORD, dwFlags
WORD, dwExtraInfo
WORD
mouse_event proto dwFlags
WORD, x
WORD, y
WORD, cButtons
WORD, dwExtraInfo
WORD
Client_SendCommand proto CommandID
WORD, Argument
WORD
Client_IncomingMessage proto CommandID
WORD, Argument
WORD
Server_SendCommand proto CommandID
WORD
Server_SendCommand2 proto CommandID
WORD, Argument
WORD
Server_SendCommand3 proto CommandID
WORD, Argument
WORD, ArgSize
WORD
Server_IncomingMessage proto CommandID
WORD, Argument
WORD
Thread_GameBot proto lParam
WORD
Thread_GameMoniter proto lParam
WORD
Thread_PipeMoniter proto lParam
WORD
Thread_HideModule proto lParam
WORD
EventHandler_AutoClicker proto
EventHandler_AutoChat proto
EventHandler_AutoLoot proto
EventHandler_AutoPotionHP proto
EventHandler_AutoPotionMP proto
; Helper Macro
MakeString macro Text:VARARG
LOCAL szText
.data
szText db Text, 0
.code
exitm
endm
String macro Text:VARARG
exitm
endm
; SendInput INPUT Structures
KEYBDINPUT struct
wVk WORD ?
wScan WORD ?
dwFlags DWORD ?
time DWORD ?
dwExtraInfo DWORD ?
KEYBDINPUT ends
MOUSEINPUT struct
x LONG ?
y LONG ?
mouseData DWORD ?
dwFlags DWORD ?
time DWORD ?
dwExtraInfo DWORD ?
MOUSEINPUT ends
INPUT struct
dwType DWORD ?
union
keybd KEYBDINPUT {}
mouse MOUSEINPUT {}
ends
INPUT ends
.const
; MSPro state constants
MSPRO_STATE_IDLE equ 0
MSPRO_STATE_HOOK equ 1
MSPRO_STATE_UNHOOK equ 2
MSPRO_STATE_PIPEINIT equ 3
MSPRO_STATE_PIPEOK equ 4
MSPRO_STATE_PIPEERR equ 5
MSPRO_STATE_GETFOCUS equ 6
MSPRO_STATE_LOSTFOCUS equ 7
; MSPro Client-Server communication constants
MSPRO_CLIENT_HANDLE equ 2010h
MSPRO_CLIENT_PID equ 2020h
MSPRO_CLIENT_STATE equ 2030h
MSPRO_SERVER_TESTPIPE equ 3000h
MSPRO_SERVER_SENDKEYS equ 3010h
MSPRO_SERVER_SETCFG1 equ 3020h
MSPRO_SERVER_SETCFG2 equ 3030h
MSPRO_SERVER_SETCFG3 equ 3040h
MSPRO_SERVER_SETCFG4 equ 3050h
MSPRO_SERVER_SETCFG5 equ 3060h
MSPRO_SERVER_SETCFG6 equ 3070h
MSPRO_SERVER_SETCFG7 equ 3080h
MSPRO_SERVER_SETCFG8 equ 3090h
MSPRO_SERVER_SETCFG9 equ 30A0h
MSPRO_SERVER_SETCFG10 equ 30B0h
MSPRO_SERVER_SETCFG11 equ 30C0h
MSPRO_SERVER_SETCFG12 equ 30D0h
; DirectInput scan code constants
DIK_NUMPAD1 equ 79
DIK_NUMPAD2 equ 80
DIK_NUMPAD3 equ 81
DIK_NUMPAD4 equ 75
DIK_NUMPAD5 equ 76
DIK_NUMPAD6 equ 77
DIK_NUMPAD7 equ 71
DIK_NUMPAD8 equ 72
DIK_NUMPAD9 equ 73
DIK_NUMPAD0 equ 82
DIK_HOME equ 199
DIK_END equ 207
DIK_PAGEUP equ 201
DIK_PAGEDOWN equ 209
DIK_INSERT equ 210
DIK_DELETE equ 211
DIK_UP equ 200
DIK_LEFT equ 203
DIK_RIGHT equ 205
DIK_DOWN equ 208
; other constants
DELAY_SINPUT equ 10 ; delay 10 miliseconds between each input
KEYEVENTF_SCANCODE equ 8 ; keybd_event hardware scan code
flag
AUTOPOT_ALARM equ 0F0F0F0h ; full screen
AUTOPOT_ALARM2 equ 0474747h ; windowed mode
.data?
; MSPro common uninitialized data
hHook dd ?
hInstance dd ?
hPipePID dd ? ; Pipe creator process ID
hPipeRead dd ? ; Pipe handles
hPipeWrite dd ?
IsClient dd ?
IsServer dd ?
szBuffer db 255 dup (?)
szClassName db MAX_PATH dup (?)
szModuleName db MAX_PATH dup (?)
FocusOn dd ? ; MapleStory window focus
ConnState dd ? ; MSPro Client-Server connection state
BeepTrigger dd ?
; Window and DC handles
hMapleWnd dd ? ; MapleStory window handle
hDesktopDC dd ?
WndRect RECT {} ; MapleStory window rectangle coordinate
WndWidth dd ?
WndHeight dd ?
; Key States
KeyState_AutoClicker dd ?
KeyState_AutoChat dd ?
KeyState_AutoLoot dd ?
KeyState_AutoPotionHP dd ?
KeyState_AutoPotionMP dd ?
; MSPro configuration variables
Cfg_BeepNotify dd ?
Cfg_FocusCheck dd ?
Hotkey_AutoClicker dd ?
Hotkey_AutoPotionHP dd ?
Hotkey_AutoPotionMP dd ?
Hotkey_AutoChat dd ?
Hotkey_AutoLoot dd ?
Hotkey_HP_Potion WORD ?
Hotkey_MP_Potion WORD ?
Hotkey_AutoLoot_Key WORD ?
AutoPotionHP_Alarm dd ?
AutoPotionMP_Alarm dd ?
.code
; where the code begins
start:
;-----------------
; Dll Entry Point
;-----------------
DllMain proc hInst:HINSTANCE, reason
WORD, reserved1
WORD
push hInst
pop hInstance
.if reason == DLL_PROCESS_ATTACH
; eliminates some overhead
invoke DisableThreadLibraryCalls, hInst
; retrieve the name of current attached module
invoke GetModuleFileName, NULL, addr szModuleName, MAX_PATH
; extract the file name
invoke PathStripPath, addr szModuleName
; check if this module is attached to specified process
invoke lstrcmpi, addr szModuleName, String("MapleStory.exe")
.if eax == 0
; mark as client
mov IsClient, TRUE
; MapleStory hooked
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_HOOK
; create a new thread to moniter the pipe
invoke CreateThread, NULL, NULL, addr Thread_PipeMoniter, NULL,
NULL, NULL
invoke CloseHandle, eax
; create a new thread to moniter the game client
invoke CreateThread, NULL, NULL, addr Thread_GameMoniter, NULL,
NULL, NULL
invoke CloseHandle, eax
; create a new thread to execute the bot command
invoke CreateThread, NULL, NULL, addr Thread_GameBot, NULL, NULL,
NULL
invoke CloseHandle, eax
; create a new thread to hide our module
invoke CreateThread, NULL, NULL, addr Thread_HideModule, NULL,
NULL, NULL
invoke CloseHandle, eax
.else
; check if this module is loaded by our own VGui
invoke lstrcmpi, addr szModuleName, String("MSPro.exe")
.if eax != 0
; nope, we don't waste someone else's memory
xor eax, eax
ret
.endif
.endif
.elseif reason == DLL_PROCESS_DETACH
.if IsClient == TRUE
; MapleStory is unhooked
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_UNHOOK
.endif
.endif
mov eax, TRUE
ret
DllMain endp
;-------------------
; Stealth Functions
;-------------------
Thread_HideModule proc lParam
WORD
; hide our module from being detected
invoke HideModule, hInstance
ret
Thread_HideModule endp
;
; This function hides a specified module from being detected
;
; Credits: PizzaPan @ http://forum.game-deception.net/
;
HideModule proc hModule
WORD
LOCAL PPEB_LDR_DATA
mov eax, hModule
assume fs:nothing ; Assume the Register is 0, MASM by default
assumes its pointing to ERROR FS:[0]
mov eax, fs:[30h] ; PEB
mov eax, [eax+0Ch] ; PEB->ProcessModuleInfo
mov PPEB_LDR_DATA, eax ; Save ProcessModuleInfo
;
http://undocumented.ntinternals.net/UserMode/Structures/PEB_LDR_DATA.html
; typedef struct _PEB_LDR_DATA {
;
; ULONG Length; 00h
; BOOLEAN Initialized; 04h
; PVOID SsHandle; 08h
; LIST_ENTRY InLoadOrderModuleList; 0Ch + 10h
; LIST_ENTRY InMemoryOrderModuleList; 14h + 18h
; LIST_ENTRY InInitializationOrderModuleList; 1Ch + 20h
;
; } PEB_LDR_DATA, *PPEB_LDR_DA
; Lists are Doubly linked, Going Forard and Backwards So Each Entry
is Really 2 DWORDS
; ProcessModuleInfo->InLoadOrderModuleList[FORWARD]
[EAX+0Ch]
; ProcessModuleInfo->InLoadOrderModuleList[BACKWARD]
[EAX+10h]
; ProcessModuleInfo->InMemoryOrderModuleList[FORWARD]
[EAX+14h]
; ProcessModuleInfo->InMemoryOrderModuleList[BACKWARD]
[EAX+18h]
; ProcessModuleInfo->InInitializationOrderModuleList[FORWARD]
[EAX+1Ch]
; ProcessModuleInfo->InInitializationOrderModuleList[BACKWARD]
[EAX+20h]
;@InLoadOrderModuleList
mov esi, [eax+0Ch] ;
ProcessModuleInfo->InLoadOrderModuleList[FORWARD]
mov edx, [eax+10h] ;
ProcessModuleInfo->InLoadOrderModuleList[BACKWARD]
@LoopInLoadOrderModuleList:
lodsd ; Load First Module
mov esi, eax ; ESI points to Next Module
mov ecx, [eax+18h] ; LDR_MODULE->BaseAddress
cmp ecx, hModule ; Is it Our Module ?
jne @f ; If Not, Next Please (@f jumps to nearest Unamed Lable
@@
mov ebx, [eax] ; [FORWARD] Module
mov ecx, [eax+4] ; [BACKWARD] Module
mov [ecx], ebx ; Previous Module's [FORWARD] Notation, Points to
us, Replace it with, Module++
mov [ebx+4], ecx ; Next Modules, [BACKWARD] Notation, Points to us,
Replace it with, Module--
jmp @InMemoryOrderModuleList ; Hidden, so Move onto Next Set
@@:
cmp edx, esi ; Reached End of Modules ?
jne @LoopInLoadOrderModuleList ; If Not, Reloop
@InMemoryOrderModuleList:
mov eax, PPEB_LDR_DATA ; PEB->ProcessModuleInfo
mov esi, [eax+14h] ;
ProcessModuleInfo->InMemoryOrderModuleList[START]
mov edx, [eax+18h] ;
ProcessModuleInfo->InMemoryOrderModuleList[FINISH]
@LoopInMemoryOrderModuleList:
lodsd
mov esi, eax
mov ecx, [eax+10h]
cmp ecx, hModule
jne @f
mov ebx, [eax]
mov ecx, [eax+4]
mov [ecx], ebx
mov [ebx+4], ecx
jmp @InInitializationOrderModuleList
@@:
cmp edx, esi
jne @LoopInMemoryOrderModuleList
@InInitializationOrderModuleList:
mov eax, PPEB_LDR_DATA ; PEB->ProcessModuleInfo
mov esi, [eax+1Ch] ;
ProcessModuleInfo->InInitializationOrderModuleList[START]
mov edx, [eax+20h] ;
ProcessModuleInfo->InInitializationOrderModuleList[FINISH]
@LoopInInitializationOrderModuleList:
lodsd
mov esi, eax
mov ecx, [eax+08h]
cmp ecx, hModule
jne @f
mov ebx, [eax]
mov ecx, [eax+4]
mov [ecx], ebx
mov [ebx+4], ecx
jmp @Finished
@@:
cmp edx, esi
jne @LoopInInitializationOrderModuleList
@Finished:
ret
HideModule endp
;------------------
; Helper Functions
;------------------
HandleKeyPress proc vKey
WORD, KeyState
WORD, EventHandler
WORD
LOCAL State
.if vKey > 0
; read the key state
mov esi, KeyState
mov eax, [esi]
mov State, eax
; check the key state
invoke GetAsyncKeyState, vKey
; handle the key state
.if State > 1
.if eax == FALSE
.if State == 3
; key released, trigger it
mov State, 1
; trigger beep notification
mov BeepTrigger, 1
.else
; key released, release it
mov State, 0
; trigger beep notification
mov BeepTrigger, 2
.endif
.endif
.else
.if eax != FALSE
.if State == 1
; key pressed, release it
mov State, 2
.else
; key pressed, trigger it
mov State, 3
.endif
.endif
.endif
; read the key state
.if State == 1
; invoke key event handler
call [EventHandler]
.endif
; update the key state
mov esi, KeyState
mov eax, State
mov [esi], eax
.endif
; return
ret
HandleKeyPress endp
GenerateBeep proc uses eax KeyState
WORD
.if Cfg_BeepNotify != FALSE
.if KeyState != FALSE
; triggered
invoke Beep, 500, 20
invoke Beep, 550, 20
invoke Beep, 600, 20
invoke Beep, 650, 20
invoke Beep, 700, 20
.else
; untriggered
invoke Beep, 700, 20
invoke Beep, 650, 20
invoke Beep, 600, 20
invoke Beep, 550, 20
invoke Beep, 500, 20
.endif
.endif
ret
GenerateBeep endp
ScaleToClientRect proc uses esi X
WORD, Y
WORD
; get the MapleStory window rectangle coordinate
invoke GetWindowRect, hMapleWnd, addr WndRect
; calculate the MapleStory window width and height
mov eax, WndRect.left
mov ebx, WndRect.right
sub ebx, eax
mov WndWidth, ebx
mov eax, WndRect.top
mov ebx, WndRect.bottom
sub ebx, eax
mov WndHeight, ebx
; calculate x and y coordinate by scaling
; X = Left + (FullScreenX * CurrentWidth) / FullScreenWidth
; Y = Top + (FullScreenY * CurrentHeight) / FullScreenHeight
mov esi, X
mov eax, [esi]
mul WndWidth
mov ebx, 800
xor edx, edx
div ebx
add eax, WndRect.left
mov [esi], eax
mov esi, Y
mov eax, [esi]
mul WndHeight
mov ebx, 600
xor edx, edx
div ebx
add eax, WndRect.top
mov [esi], eax
ret
ScaleToClientRect endp
ConvertToGreyscale proc crColor
WORD
; convert to greyscale [Red + Green + Blue] / 3
lea esi, crColor
xor eax, eax
xor ebx, ebx
mov al, [esi]
add ebx, eax
mov al, [esi + 1]
add ebx, eax
mov eax, [esi + 2]
add ebx, eax
xor edx, edx
mov ecx, 3
div ecx
mov cl, bl
mov ch, bl
shl ecx, 8
mov cl, bl
; return
mov eax, ecx
ret
ConvertToGreyscale endp
NumLock_Toggle proc State
WORD
; check NumLock state
invoke GetKeyState, VK_NUMLOCK
.if eax != 0
.if State == FALSE
; turn off NumLock
invoke keybd_event, VK_NUMLOCK, 45h, KEYEVENTF_EXTENDEDKEY,
NULL
invoke keybd_event, VK_NUMLOCK, 45h, KEYEVENTF_EXTENDEDKEY or
KEYEVENTF_KEYUP, NULL
.endif
.else
.if State == TRUE
; turn on NumLock
invoke keybd_event, VK_NUMLOCK, 45h, KEYEVENTF_EXTENDEDKEY,
NULL
invoke keybd_event, VK_NUMLOCK, 45h, KEYEVENTF_EXTENDEDKEY or
KEYEVENTF_KEYUP, NULL
.endif
.endif
ret
NumLock_Toggle endp
;--------------------
; Exported Functions
;--------------------
MSPro_Initialize proc
; mark as server
mov IsServer, TRUE
; initialize the system-wide hook
invoke SetWindowsHookEx, WH_CBT, addr Hook_CBT, hInstance,
NULL
mov hHook, eax
ret
MSPro_Initialize endp
MSPro_Finalize proc
; release system-wide hook
invoke UnhookWindowsHookEx, hHook
ret
MSPro_Finalize endp
MSPro_GetState proc
; return MSPro connection state
mov eax, ConnState
ret
MSPro_GetState endp
MSPro_SendKeystroke proc bVk
WORD
; send the specified keystroke to client
invoke Server_SendCommand2, MSPRO_SERVER_SENDKEYS, bVk
ret
MSPro_SendKeystroke endp
MSPro_SetConfig1 proc vKey
WORD
; set Auto-Clicker hotkey
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG1, vKey
ret
MSPro_SetConfig1 endp
MSPro_SetConfig2 proc vKey
WORD
; set Auto-Chat hotkey
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG2, vKey
ret
MSPro_SetConfig2 endp
MSPro_SetConfig3 proc vKey
WORD, vKey2
WORD
; set Auto-Loot hotkey and pickup key
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG3, vKey
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG4, vKey2
ret
MSPro_SetConfig3 endp
MSPro_SetConfig4 proc vKey
WORD, vKey2
WORD, Alarm
WORD
; set HP Auto-Potion hotkey, potion key and alarm level
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG5, vKey
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG6, vKey2
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG7, Alarm
ret
MSPro_SetConfig4 endp
MSPro_SetConfig5 proc vKey
WORD, vKey2
WORD, Alarm
WORD
; set MP Auto-Potion hotkey, potion key and alarm level
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG8, vKey
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG9, vKey2
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG10, Alarm
ret
MSPro_SetConfig5 endp
MSPro_SetConfig6 proc Enabled
WORD
; toggle BeepNotify switch
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG11, Enabled
ret
MSPro_SetConfig6 endp
MSPro_SetConfig7 proc Enabled
WORD
; toggle FocusCheck switch
invoke Server_SendCommand2, MSPRO_SERVER_SETCFG12, Enabled
ret
MSPro_SetConfig7 endp
SendInput proc cInputs
WORD, pInputs
WORD, cbSize
WORD
LOCAL lpOSVerInfo:OSVERSIONINFOEX
; check operating system version
mov lpOSVerInfo.dwOSVersionInfoSize, sizeof lpOSVerInfo
invoke GetVersionEx, addr lpOSVerInfo
.if lpOSVerInfo.wServicePackMajor >= 2
; this is Windows XP SP2
push cbSize
push pInputs
push cInputs
call Tunnel_WinXP_SP2
.else
; nope, this isn't
push cbSize
push pInputs
push cInputs
call Tunnel_Non_WinXP_SP2
.endif
ret
Tunnel_Non_WinXP_SP2:
; thanks to TiMBuS for this one
mov eax, 11F6h
mov edx, 7FFE0300h
call edx
ret 0Ch
Tunnel_WinXP_SP2:
; a copy of the actual SendInput api
mov eax, 11F6h
mov edx, 7FFE0300h
call dword ptr [edx]
ret 0Ch
SendInput endp
GetPixel proc hDC
WORD, x
WORD, y
WORD
LOCAL hTempDC
LOCAL hTempBitmap, hTempBitmapOld
LOCAL crColor
LOCAL lpBitmap:BITMAPINFO
; construct a temporary DC and bitmap
invoke CreateCompatibleDC, hDC
mov hTempDC, eax
invoke CreateCompatibleBitmap, hDC, 1, 1
mov hTempBitmap, eax
invoke SelectObject, hTempDC, eax
mov hTempBitmapOld, eax
; copy the pixel from requested DC
invoke BitBlt, hTempDC, 0, 0, 1, 1, hDC, x, y, SRCCOPY
; retrieve the pixel color
mov lpBitmap.bmiHeader.biWidth, 1
mov lpBitmap.bmiHeader.biHeight, 1
mov lpBitmap.bmiHeader.biSize, sizeof lpBitmap
mov lpBitmap.bmiHeader.biPlanes, 1
mov lpBitmap.bmiHeader.biBitCount, 24
mov lpBitmap.bmiHeader.biCompression, BI_RGB
invoke GetDIBits, hTempDC, hTempBitmap, 0, 1, addr crColor, addr
lpBitmap, DIB_RGB_COLORS
; release the temporary DC and bitmap
invoke SelectObject, hTempDC, hTempBitmapOld
invoke DeleteObject, hTempBitmap
invoke DeleteDC, hTempDC
; shuffle big-endian to little-endian
mov eax, crColor
bswap eax
shr eax, 8
; return
ret
GetPixel endp
keybd_event proc bVk:WORD, bScan:WORD, dwFlags
WORD, dwExtraInfo
WORD
LOCAL NumLock
.data
KEYBD INPUT {}
.code
; cache NumLock original state
invoke GetKeyState, VK_NUMLOCK
mov NumLock, eax
; NumLock key state fixes
.if bScan == DIK_HOME
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_END
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_PAGEUP
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_PAGEDOWN
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_INSERT
; turn off NumLock
invoke NumLock_Toggle, FALSE
; use DIK_NUMPAD0 instead
mov bScan, DIK_NUMPAD0
.elseif bScan == DIK_DELETE
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_UP
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_LEFT
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_RIGHT
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_DOWN
; turn off NumLock
invoke NumLock_Toggle, FALSE
.elseif bScan == DIK_NUMPAD1
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD2
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD3
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD4
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD5
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD6
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD7
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD8
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD9
; turn on NumLock
invoke NumLock_Toggle, TRUE
.elseif bScan == DIK_NUMPAD0
; turn on NumLock
invoke NumLock_Toggle, TRUE
.endif
; prepare the pointer
mov eax, offset KEYBD
assume eax:ptr INPUT
; fill in the KEYBDINPUT structure
push INPUT_KEYBOARD
push bVk
push bScan
push dwFlags
push dwExtraInfo
pop [eax].keybd.dwExtraInfo
pop [eax].keybd.dwFlags
pop [eax].keybd.wScan
pop [eax].keybd.wVk
pop [eax].dwType
; invoke SendInput function
invoke SendInput, 1, eax, 1Ch
; restore NumLock state
invoke NumLock_Toggle, NumLock
; return
ret 10h
keybd_event endp
mouse_event proc dwFlags
WORD, x
WORD, y
WORD, cButtons
WORD, dwExtraInfo
WORD
.data
MOUSE INPUT {}
.code
; prepare the pointer
mov eax, offset MOUSE
assume eax:ptr INPUT
; fill in the MOUSEINPUT structure
push INPUT_MOUSE
push dwFlags
push x
push y
push cButtons
push dwExtraInfo
pop [eax].mouse.dwExtraInfo
pop [eax].mouse.mouseData
pop [eax].mouse.y
pop [eax].mouse.x
pop [eax].mouse.dwFlags
pop [eax].dwType
; invoke SendInput
invoke SendInput, 1, eax, 1Ch
; return
ret 14h
mouse_event endp
;---------------
; Hook Function
;---------------
Hook_CBT proc nCode
WORD, wParam
WORD, lParam
WORD
.if IsServer == TRUE
.if nCode >= 0
; handle incoming client command
invoke Server_IncomingMessage, wParam, lParam
.endif
.endif
; pass this message to the next hook in chain
invoke CallNextHookEx, hHook, nCode, wParam, lParam
ret
Hook_CBT endp
;-------------------
; Client-Side Codes
;-------------------
Thread_PipeMoniter proc lParam
WORD
LOCAL lBytesRead
; Create a pipe for interprocess communication
invoke CreatePipe, addr hPipeRead, addr hPipeWrite, NULL, sizeof
szBuffer
.if eax != 0
; pass the pipe write handle to server
invoke GetCurrentProcessId
invoke Client_SendCommand, MSPRO_CLIENT_PID, eax
invoke Client_SendCommand, MSPRO_CLIENT_HANDLE, hPipeWrite
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_PIPEINIT
; lower the priority of this thread
invoke GetCurrentThread
invoke SetThreadPriority, eax, THREAD_PRIORITY_BELOW_NORMAL
.while TRUE
; read and wait for server
invoke RtlZeroMemory, addr szBuffer, sizeof szBuffer
invoke ReadFile, hPipeRead, addr szBuffer, sizeof szBuffer - 1,
addr lBytesRead, FALSE
; parse the command
mov esi, offset szBuffer
mov eax, [esi]
add esi, 4
; handle the incoming server command
invoke Client_IncomingMessage, eax, esi
.endw
.else
; pipe creation error
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_PIPEERR
.endif
ret
Thread_PipeMoniter endp
Thread_GameBot proc lParam
WORD
; raise the priority of this thread to get a better
performance
invoke GetCurrentThread
invoke SetThreadPriority, eax, THREAD_PRIORITY_HIGHEST
.while TRUE
; check if MapleStory is in focus
.if FocusOn != FALSE
; reset beep notification trigger
mov BeepTrigger, 0
; handle the key events
invoke HandleKeyPress, Hotkey_AutoClicker, addr
KeyState_AutoClicker, addr EventHandler_AutoClicker
invoke HandleKeyPress, Hotkey_AutoChat, addr KeyState_AutoChat,
addr EventHandler_AutoChat
invoke HandleKeyPress, Hotkey_AutoLoot, addr KeyState_AutoLoot,
addr EventHandler_AutoLoot
invoke HandleKeyPress, Hotkey_AutoPotionHP, addr
KeyState_AutoPotionHP, addr EventHandler_AutoPotionHP
invoke HandleKeyPress, Hotkey_AutoPotionMP, addr
KeyState_AutoPotionMP, addr EventHandler_AutoPotionMP
.if BeepTrigger == 1
; generate beep notification
invoke GenerateBeep, TRUE
.elseif BeepTrigger == 2
; generate beep notification
invoke GenerateBeep, FALSE
.endif
.endif
; yeild to the other threads
invoke SleepEx, 1, TRUE
.endw
ret
Thread_GameBot endp
Thread_GameMoniter proc lParam
WORD
LOCAL LastWnd
LOCAL LastDesktop
.while TRUE
; locate the foreground window
invoke GetForegroundWindow
.if eax != LastWnd
; cache the window handle
mov LastWnd, eax
; save the MapleStory window handle
push LastWnd
pop hMapleWnd
; check for MapleStory window focus
.if Cfg_FocusCheck != FALSE
; get the windows class name
invoke GetClassName, hMapleWnd, addr szClassName, MAX_PATH
; check if MapleStory is in focus
invoke lstrcmpi, addr szClassName, String("MapleStoryClass")
.if eax == 0
; MapleStory is on focus
mov FocusOn, TRUE
; notify the server
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_GETFOCUS
.else
; MapleStory is lost focus
mov FocusOn, FALSE
; notify the server
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_LOSTFOCUS
.endif
.else
; assume window is in focus
mov FocusOn, TRUE
.endif
.endif
; get the desktop window handle
invoke GetDesktopWindow
.if eax != LastDesktop
; cache the desktop window handle
mov LastDesktop, eax
; release the device context
invoke ReleaseDC, NULL, hDesktopDC
; get a handle to screen device context
invoke GetDC, NULL
mov hDesktopDC, eax
.endif
; yeild to the other threads
invoke SleepEx, 50, TRUE
.endw
ret
Thread_GameMoniter endp
EventHandler_AutoClicker proc
; auto-clicker
invoke mouse_event, MOUSEEVENTF_LEFTDOWN, NULL, NULL, NULL,
NULL
invoke mouse_event, MOUSEEVENTF_LEFTUP, NULL, NULL, NULL,
NULL
ret
EventHandler_AutoClicker endp
EventHandler_AutoChat proc
.data
Timer_AutoChat dd ?
.code
; auto-chat
invoke GetTickCount
.if eax >= Timer_AutoChat
invoke keybd_event, VK_DOWN, NULL, NULL, NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, VK_DOWN, NULL, KEYEVENTF_KEYUP, NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, VK_RETURN, NULL, NULL, NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, VK_RETURN, NULL, KEYEVENTF_KEYUP, NULL
; calculate the next tick
invoke GetTickCount
add eax, 1000
mov Timer_AutoChat, eax
.endif
ret
EventHandler_AutoChat endp
EventHandler_AutoLoot proc
; auto-loot
invoke keybd_event, NULL, Hotkey_AutoLoot_Key, KEYEVENTF_SCANCODE,
NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, NULL, Hotkey_AutoLoot_Key, KEYEVENTF_KEYUP or
KEYEVENTF_SCANCODE, NULL
ret
EventHandler_AutoLoot endp
EventHandler_AutoPotionHP proc
LOCAL ScaleX
LOCAL ScaleY
.data
szMsg db 1024 dup (?)
.code
; convert the coordinate from fullscreen to client rectangle
mov eax, AutoPotionHP_Alarm
add eax, 220
mov ScaleX, eax
mov ScaleY, 590
invoke ScaleToClientRect, addr ScaleX, addr ScaleY
; check the pixel color
invoke GetPixel, hDesktopDC, ScaleX, ScaleY
invoke ConvertToGreyscale, eax
xor ebx, ebx
.if eax == AUTOPOT_ALARM
mov ebx, TRUE
.elseif eax == AUTOPOT_ALARM2
mov ebx, TRUE
.endif
.if ebx != 0
; alarm is triggered
invoke keybd_event, NULL, Hotkey_HP_Potion, KEYEVENTF_SCANCODE,
NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, NULL, Hotkey_HP_Potion, KEYEVENTF_KEYUP or
KEYEVENTF_SCANCODE, NULL
invoke Beep, 500, 10
.endif
ret
EventHandler_AutoPotionHP endp
EventHandler_AutoPotionMP proc
LOCAL ScaleX
LOCAL ScaleY
; convert the coordinate from fullscreen to client rectangle
mov eax, AutoPotionMP_Alarm
add eax, 328
mov ScaleX, eax
mov ScaleY, 590
invoke ScaleToClientRect, addr ScaleX, addr ScaleY
; check the pixel color
invoke GetPixel, hDesktopDC, ScaleX, ScaleY
invoke ConvertToGreyscale, eax
xor ebx, ebx
.if eax == AUTOPOT_ALARM
mov ebx, TRUE
.elseif eax == AUTOPOT_ALARM2
mov ebx, TRUE
.endif
.if ebx != 0
; alarm is triggered
invoke keybd_event, NULL, Hotkey_MP_Potion, KEYEVENTF_SCANCODE,
NULL
invoke SleepEx, DELAY_SINPUT, TRUE
invoke keybd_event, NULL, Hotkey_MP_Potion, KEYEVENTF_KEYUP or
KEYEVENTF_SCANCODE, NULL
invoke Beep, 500, 10
.endif
ret
EventHandler_AutoPotionMP endp
Client_SendCommand proc CommandID
WORD, Argument
WORD
; send the specified command to the server
invoke SendMessageTimeout, HWND_BROADCAST, WM_SYSCOMMAND,
CommandID, Argument, SMTO_BLOCK or SMTO_ABORTIFHUNG, 2000,
NULL
ret
Client_SendCommand endp
Client_IncomingMessage proc CommandID
WORD, Argument
WORD
LOCAL VKey:WORD
.if CommandID == MSPRO_SERVER_TESTPIPE
; respond with pipe OK message
invoke Client_SendCommand, MSPRO_CLIENT_STATE,
MSPRO_STATE_PIPEOK
.endif
ret
Client_IncomingMessage endp
;-------------------
; Server-Side Codes
;-------------------
Server_SendCommand proc uses esi edi CommandID
WORD
LOCAL lBytesWritten
; copy the command to buffer
mov esi, CommandID
mov edi, offset szBuffer
mov [edi], esi
; send the specified command to the client
invoke WriteFile, hPipeWrite, addr szBuffer, 4, addr lBytesWritten,
FALSE
invoke SleepEx, 100, TRUE
ret
Server_SendCommand endp
Server_SendCommand2 proc uses esi edi CommandID
WORD, Argument
WORD
LOCAL lBytesWritten
; copy the command to buffer
mov esi, CommandID
mov edi, offset szBuffer
mov [edi], esi
; copy the DWORD argument to buffer
mov esi, Argument
mov [edi + 4], esi
; send the specified command to the client
invoke WriteFile, hPipeWrite, addr szBuffer, 8, addr lBytesWritten,
FALSE
invoke SleepEx, 100, TRUE
ret
Server_SendCommand2 endp
Server_SendCommand3 proc uses esi edi ebx CommandID
WORD, Argument
WORD, ArgSize
WORD
LOCAL lBytesWritten
; copy the command to buffer
mov esi, CommandID
mov edi, offset szBuffer
mov [edi], esi
.if ArgSize <= sizeof szBuffer - 4
; copy the string argument to buffer
invoke RtlMoveMemory, addr szBuffer + 4, Argument, ArgSize
; calculate the argument size
mov ebx, ArgSize
add ebx, 4
; send the specified command to the client
invoke WriteFile, hPipeWrite, addr szBuffer, ebx, addr
lBytesWritten, FALSE
invoke SleepEx, 100, TRUE
.endif
ret
Server_SendCommand3 endp
Server_IncomingMessage proc CommandID
WORD, Argument
WORD
LOCAL hProcess
.if CommandID == MSPRO_CLIENT_HANDLE
; open a handle to pipe creator process
invoke OpenProcess, PROCESS_DUP_HANDLE, FALSE, hPipePID
mov hProcess, eax
; duplicate the pipe write handle
invoke GetCurrentProcess
invoke DuplicateHandle, hProcess, Argument, eax, addr hPipeWrite,
NULL, FALSE, DUPLICATE_SAME_ACCESS
; test the pipe
invoke Server_SendCommand, MSPRO_SERVER_TESTPIPE
.elseif CommandID == MSPRO_CLIENT_PID
; save the pipe creator process ID
push Argument
pop hPipePID
.elseif CommandID == MSPRO_CLIENT_STATE
; save the client state
push Argument
pop ConnState
.endif
ret
Server_IncomingMessage endp
end start
mspro_v3.def
LIBRARY MSPro
EXPORTS MSPro_Initialize
EXPORTS MSPro_Finalize
EXPORTS MSPro_GetState
EXPORTS MSPro_SendKeystroke
EXPORTS MSPro_SetConfig1
EXPORTS MSPro_SetConfig2
EXPORTS MSPro_SetConfig3
EXPORTS MSPro_SetConfig4
EXPORTS MSPro_SetConfig5
EXPORTS MSPro_SetConfig6
EXPORTS MSPro_SetConfig7
; Tunnel functions
EXPORTS SendInput
EXPORTS GetPixel
EXPORTS keybd_event
EXPORTS mouse_event
MSpro_v3.rap
[Project]
Assembler=masm
Type=Dll Project
Description=MSPro v3
Backup=$P\Bak\
Group=1
GroupExpand=1
Debug=0
[Files]
1=MSPro_v3.Asm
2=
3=MSPro_v3.Def
4=
[MakeFiles]
0=MSPro_v3.rap
1=MSPro_v3.rc
2=MSPro_v3.asm
3=MSPro_v3.obj
4=MSPro_v3.res
5=MSPro_v3.exe
6=MSPro_v3.def
7=MSPro_v3.dll
8=MSPro_v3.txt
9=MSPro_v3.lib
10=MSPro_v3.mak
11=MSPro_v3.hla
12=MSPro_v3.com
13=MSPro_v3.ocx
14=MSPro_v3.idl
15=MSPro_v3.tlb
[MakeDef]
Menu=0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0
1=4,O,$B\RC.EXE /v,1
2=3,O,$B\ML.EXE /c /coff /Cp /nologo /I"$I",2
3=7,O,$B\LINK.EXE /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:$6
/LIBPATH:"$L" /OUT:"$7",3
4=0,0,,5
5=rsrc.obj,O,$B\CVTRES.EXE,rsrc.res
6=*.obj,O,$B\ML.EXE /c /coff /Cp /nologo /I"$I",*.asm
7=0,0,"$E\OllyDbg",5
11=4,O,$B\RC.EXE /v,1
12=3,O,$B\ML.EXE /c /coff /Cp /Zi /nologo /I"$I",2
13=7,O,$B\LINK.EXE /SUBSYSTEM:WINDOWS /DEBUG /DLL /DEF:$6
/LIBPATH:"$L" /OUT:"$7",3
14=0,0,,5
15=rsrc.obj,O,$B\CVTRES.EXE,rsrc.res
16=*.obj,O,$B\ML.EXE /c /coff /Cp /nologo /I"$I",*.asm
17=0,0,"$E\OllyDbg",5
[Group]
Group=Added files,Assembly,Resources,Misc,Modules
1=2
2=
3=4
4=
[Collapse]
4=
1=,,,
2=
3=
[Size]
4=0,0,0,0,224
1=0,0,0,0,16086
2=
3=0,0,0,0,403
[Find]
1="ConnState"
2="Redirect_Direct3DCreate8"
3="Hook_Direct3DCreate8"
4="ScreenToGameSpace"
5="KEYPRESS_DELAY"
6="BeepNotify"
7="Thread_GameMoniter"
8="Server_SendCommand"
9="MSPRO_STATE_CLOSED"
10="MSPRO_STATE_IDLE"
[VersionControl]
Settings=1246
Milestones=129
MilestoneEvery=10
MilestoneEveryCurrent=0
MilestoneOnBuild=0.0.0.0
MilestoneOnTime=2
MilestoneOnDate=0
MilestoneOnDateWhen=1
MilestoneOnDateStatus=0
MilestoneOnDateDate=7
MilestoneOnDateTimeYear=2006
MilestoneOnDateTimeMonth=4
MilestoneOnDateTimeDate=27
MilestoneOnDateTimeHour=21
MilestoneOnDateTimeMin=31
MilestoneOnDateTimeSec=49
MilestoneOnDateTimeStatus=0
BackupLocation=C:\RadASM\Masm\Projects\VCBackups\
CompressionLevel=0
DefaultComment=Project $N, $Z, Backup Created On $D At $T.
ExcludeExt1=\
ExcludeExt2=\
ExcludeExt3=\
ExcludeExt4=\
FileVerLength=4
FileVer2Range=0
FileVer3Range=0
FileVer4Range=0
ProductVerLength=4
ProductVer2Range=0
ProductVer3Range=0
ProductVer4Range=0
[Colref]
0=00FFFFFF
1=00FFFFFF
2=00FFFFFF
3=00FFFFFF
4=00FFFFFF
5=00FFFFFF
6=00FFFFFF
7=00FFFFFF
[BookMark]
0=
1=
2=
3=
4=
5=
6=
7=
8=
9=
[BreakPoint]
0=