%include "h:\ASM\lab\vasm\inc\nagoa.inc" ; above you need to put the right path to nagoa.inc ; nagoa.inc is free but it does need to be included global DllMain global MsgBox export MsgBox data32 ;data here (vars) szTitle db "SBT3.com",0 ;msgbox titles szIntro db "SBT 3 B.b",0 ;intro iJMP db 0xEB ;a JMP instruction iUJMP db 0xE9 ;long jump iNOP db 0x90 ;nop instruction iPUSHEBP db 0x55 ;push epb instruction iA8 db 0xA8 ;a8 for admin command thing i00 db 0x00 ;00 for admin command thing sTar db "/tar ",0 ;for comparison sAtk db "/atk ",0 ;for comparison sGrp db "Group",0 ;for comparison sGrpKey db "/groupkey ",0 ;for comparison sAttack db "/attack",0 ;for just attacking sMob db "/mob",0 ;for targeting mob sSCH db "/sch",0 ;spell cooldown hack lgJmp resb 5 ;for jmppatch rotin UserInput resb 50 ;50 chars for user commands GroupInput resb 50 ; 50 chars for group commands GroupKey db "z" ; key for group, default 'z' ToonsChecked dw 0x00 TargetNext dd 0x00B9DEF0 ;target next player function FirstTarget dd 0x00000000 ;first target so we dont check twice AttackTarget dd 0x00BD4330 ;attack target function AttackVar1 dd 0x0012FB40 ; arg1 for attack function AttackVar2 dd 0x01AA8EBC ; arg2 for attack function TargetMobFxn dd 0x00B9DF40 ; targeting next mob function code32 ;begin code section rotin DllMain,hInstDLL,fdwReason,lpvReserved ;dllmain proc, like main() START: ;start label cmp DWORD [fdwReason], DLL_PROCESS_ATTACH ;is our dll attaching ? jne DETACH ;if not jump to detach label loccall SetupStuff ;sets up code mods call MessageBoxA,0,szIntro,szTitle,MB_OK ;put a started messagbox DETACH: ;detach label cmp DWORD [fdwReason], DLL_PROCESS_DETACH ;is our dll detaching jne THREADSTART ;if not jump threadstart call MessageBoxA,0,"GoodBye",szTitle,MB_OK ;our dll is detached ;code here for exit, remove patches and mods etc mov eax,TRUE ;this says our dll did ok THREADSTART: cmp DWORD [fdwReason], DLL_THREAD_ATTACH ;is our thread attaching? jne THREADSTOP ;if not jump to threadstop ;code here for when your thread detaches, normally nothing THREADSTOP: cmp DWORD [fdwReason], DLL_THREAD_DETACH ;is our thread detaching? ;code here for when the thread detaches, normally nothing endrotin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is where we patch a jump to our functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; rotin SetupStuff ;sets up jumppatches and nops loccall JmpPatch,0x009FEE41,addr Intercept,0 loccall WriteMem,0x009FEE46,iNOP,1 ;nop out garbage loccall WriteMem,0x009FEE47,iNOP,1 ;nop out garbage loccall WriteMem,0x009FEE48,iNOP,1 ;nop out garbage loccall WriteMem,0x009FEE49,iNOP,1 ;nop out garbage loccall WriteMem,0x009FEE4A,iNOP,1 ;nop out garbage ; this is for patch for chat input, first nop then patch !! better loccall WriteMem,0x00820945,iNOP,1 ;nop old lea command loccall WriteMem,0x00820946,iNOP,1 ;nop loccall WriteMem,0x00820947,iNOP,1 ;nop loccall WriteMem,0x00820948,iNOP,1 ;nop loccall WriteMem,0x00820949,iNOP,1 ;nop loccall WriteMem,0x0082094A,iNOP,1 ;nop loccall JmpPatch,0x00820945,addr InterceptChat,0 ; for group msg ; nop out the function that was causeing group atk to crash loccall WriteMem,0x00BD44B5,iNOP,1 ;nop loccall WriteMem,0x00BD44B6,iNOP,1 ;nop loccall WriteMem,0x00BD44B7,iNOP,1 ;nop loccall WriteMem,0x00BD44B8,iNOP,1 ;nop loccall WriteMem,0x00BD44B9,iNOP,1 ;nop ; set up admin commands loccall WriteMem,0x00886B60,iUJMP,1 loccall WriteMem,0x00886B61,iA8,1 loccall WriteMem,0x00886B62,i00,1 loccall WriteMem,0x00886B63,i00,1 loccall WriteMem,0x00886B65,iNOP,1 ; set up spell cooldown this is not on by default ! ; loccall WriteMem,0x0049D182,iJMP,1 ; remove los checking loccall WriteMem,0x0049CFA8,iJMP,1 endrotin ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Compare a unicode string to a ascii string ;;; unicode in ecx, ascii in ebx, result in zf, for je or jne ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UniAsciiCmp: push eax ; uses ecx push esi ; uses esi xor esi, esi compare: mov ah, [ecx+esi*2] ; char in unicode mov al, [ebx+esi] ; char in ascii cmp ah, 0x00 ; is unicode finished ? je isEQ ; reached the end is eq cmp ah, al ; compare both the bits jne notEQ ; if not equal return ne cmp esi, 0x32 ; if we have tested 50 chars jge isEQ ; equal to 48 chars at least inc esi jmp compare ; compare next char notEQ: or al, 1 ; zf = 0 so str-str !=0 pop esi pop eax ret isEQ: test al, 0 ; zf = 1 so str-str = 0 pop esi pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Get Unicode string and put it in ascii local variable str ;;; unicode in ecx, ascii in ebx, (uses eax, esi) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetUnicodeString: push eax ;save eax push esi ;save esi xor esi, esi ;clear esi StoreUnicode: ;ECX is a pointer to our string at this point its in unicode so ;we just get every other char to make a ascii string mov AH, [ECX+ESI] ;move char temp AH mov [EBX], AH ;move char into our array inc EBX ;point to next char add ESI, 0x02 ;move index skipping null cmp AH, 0x00 ;Have we reached the end of str? je StoreUnicodeFin ;if so go to got command (fin) cmp ESI, 0x62 ;have we tested 49 chars? jne StoreUnicode ;if not carry on StoreUnicodeFin pop esi pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is where we intercept anything in chat window ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; InterceptChat: push eax push ebx push ecx mov ecx, [ebp-0x9C] ; point to category eg. grp, tell, etc mov ebx, sGrp ; point to "Group" string for compare loccall UniAsciiCmp ; do comparision jne endInterceptChat ; it is not a group message ;call MessageBoxA,0,"Group Msg",szTitle,MB_OK mov ecx, [ebp-0xBC] ; point to the message mov ah, [ecx] ; get the first char of message cmp ah, [GroupKey] ; is it for our group ? jne endInterceptChat ; if not skip action, if so its our group add ecx, 0x04 ; point to start of command reciving mov ebx, UserInput ; point to our local string for userinput add ebx, 0x01 ; move one to make space for '/' loccall GetUnicodeString ; put the string in our local var mov ebx, UserInput ; point to the first char again mov BYTE[ebx], '/' ; add the / so the user dont have to type it loccall processcmd ; process the command as if it was sent ; from our current user ;;;; this is if we did not recive a command to do a action endInterceptChat ; restore registers and code we overwrote pop ecx pop ebx pop eax lea edx, [EBP-0xC0] ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is where we intercept users input from game ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;this function gets whatever the user types in the chat console Intercept: push ESI ;save old esi push EBX ;save old ebx push EAX ;save old EAX push ECX ;duh xor ESI, ESI ;clear it mov EBX, UserInput ;point to our array sub ECX, 0x018 ;points to stack where pointer is mov ECX, [ECX] GetCommand: ;ECX is a pointer to our string at this point its in unicode so ;we just get every other char to make a ascii string mov AH, [ECX+ESI] ;move char temp AH mov [EBX], AH ;move char into our array inc EBX ;point to next char add ESI, 0x02 ;move index skipping null cmp AH, 0x00 ;Have we reached the end of str? je GotCommand ;if so go to got command (fin) cmp ESI, 0x62 ;have we tested 49 chars? jne GetCommand ;if not carry on GotCommand: ;add null char, this is a null terminated string, for msgbox and everything inc EBX mov BYTE[EBX], 0 loccall processcmd jnc cleanup ;if they gave us a valid command we replace it with "/g ok" mov BYTE[ECX+2], "g" mov BYTE[ECX+4], 0x20 ;mov BYTE[ECX + 6], "o" ;mov BYTE[ECX + 8], "k" mov BYTE[ECX + 10], 0 cleanup: ;this was only for debugging users input stored locally ;call MessageBoxA,0,UserInput,szTitle,MB_OK pop ECX pop EAX pop EBX pop ESI ;do what the orinal code did, the stuff we NOPed so it wont crash lea ECX, [EBP-0x40] mov DWORD[EBP-0x4], 2 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is were we process the users input ;;; cf=1 means we got valid command cf=0 means nothing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; processcmd: push ECX ;save ecx push eax ;save eax push edi push esi clc ;clear carry flag mov ECX, 5 mov ESI, UserInput mov EDI, sTar ;is it tar command ? cld ;forward search repe cmpsb clc ;clear carry flag jne .atk mov EBX, UserInput loccall tarplayer stc ;set carry flag jmp .theEnd ;skip everything else ;;;;;; start of attack .atk: mov ECX, 5 ;check 5 chars "/atk " mov ESI, UserInput mov EDI, sAtk ;is it tar command ? cld ;forward search repe cmpsb clc ;clear carry flag jne .grpkey loccall tarplayer ; target player for attack jnc .gotoend ; target not found (cf=0) loccall AtkTarget ; .gotoend stc ;set carry flag jmp .theEnd ;skip everything else ;;;;; end of attack ;;;;; start group keysetting .grpkey mov ECX, 0x0A ; 10 chars mov ESI, UserInput mov EDI, sGrpKey ;is it grpkey command ? cld ;forward search repe cmpsb clc ;clear carry flag jne .attack ; if its not skip action mov ESI, UserInput ; point to users input add ESI, 0x0A ; point to argument mov CH, [esi] ; get byte char mov [GroupKey], CH stc ;set carry flag jmp .theEnd ;skip everything else ;;;;; stop group keysetting ;;;;;; start of attack whatever .attack: mov ECX, 7 ;check 5 chars "/attack" mov ESI, UserInput mov EDI, sAttack ;is it tar command ? cld ;forward search repe cmpsb clc ;clear carry flag jne .spellhack loccall AtkTarget stc ;set carry flag jmp .theEnd ;skip everything else ;;;;; end of attack whatever ;;;;;; start of spell cooldown toggle .spellhack: mov ECX, 4 ;check 5 chars "/sch" mov ESI, UserInput mov EDI, sSCH ;is it spell cooldown ? cld ;forward search repe cmpsb clc ;clear carry flag jne .theEnd ;call MessageBoxA,0,"SCH has been taken out",szTitle,MB_OK loccall WriteMem,0x0049D182,iJMP,1 stc ;set carry flag jmp .theEnd ;skip everything else ;;;;; end of spell cooldown toggle ;;;;;; start of select mob THIS IS OFF ! jmp .theEnd .mob: mov ECX, 4 ;check 5 chars "/mob" mov ESI, UserInput mov EDI, sMob ;is it tar command ? cld ;forward search repe cmpsb clc ;clear carry flag jne .theEnd loccall TargetNextMob stc ;set carry flag jmp .theEnd ;skip everything else ;;;;; end of target mob .theEnd: pop esi pop edi pop eax pop ECX ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is the Attack command, it should attack whatever ;;; is selected. Uses eax and who knows what else ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; AtkTarget: push eax mov EAX, [0x01AA8EBC] ;the call needs this push EAX push 0x0012FB40 push EAX push 0x0012FB40 CALL [AttackTarget] ;call in game function to attack pop eax ;these clean up stuff we dont use pop eax ; but this function does put stuff on stack pop eax pop eax pop eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is the target next mob command, just targets next mob ;;; EAX may be destroyed ?) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; TargetNextMob: ;push eax mov EAX, [0x01AA8EBC] ;the call needs this push 0x00000000 push 0x00000000 push eax push 0x0012FB40 ;the call needs these pushes CALL [TargetMobFxn] pop eax ; get rid of garbage pop eax ; get rid of garbage pop eax ; get rid of garbage pop eax ; restore eax ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; this is the target command ;;; EBX = UserInput(the name) cf=1 if found cf=0 if not found ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; tarplayer: xor ESI,ESI mov ECX, [0x01AA8EBC] ;the call needs this CALL [TargetNext] ;call function to target next mov ECX, [0x01AA4064] ;ecx=pointer to toon cmp ECX, 0 ;is nothing selected? je theEnd cmp WORD[ToonsChecked], 0x00 ;have we checked 0 (first) je first inc WORD[ToonsChecked] ;people checked = edx cmp WORD[ToonsChecked], 0x32 ;have we checked 50? je notFound ;if yes give up first: jne notfirst ; its not the first time mov [FirstTarget], ECX ; get first target inc WORD[ToonsChecked] ;people checked = edx jmp firsttime notfirst: cmp ECX, [FirstTarget] ;is this our first target ? je notFound ;we have gone back to begginig firsttime: add ECX, 0xC4C ;holds pointer to name mov ECX, [ECX] ;ECX=toon name mov EBX, UserInput ;point to userinput add EBX, 0x05 ;+6 chars in array for param mov AH, [EBX] ;move user input to ah mov AL, [ECX] ;move target name to al cmp ESI, 0 ;for the first time je testLetter ;dont inc letters nextLetter: ;point to next letter inc ESI ;index ++ mov AH, [EBX+ESI] ;move user input to ah mov AL, [ECX+ESI*2] ;move target name to al cmp AH, 0x00 ;null char = end of str je theEnd ;if so we have a winner testLetter: cmp AH, AL ;cmp the two letters je nextLetter ;if same test next letter sub AH, 0x20 ;make uppercase cmp AH, AL ;cmp again je nextLetter ;if it was then check next letter jmp tarplayer ;letters dont match next toon cmp AH, 0x00 ;have we reached null ? jne nextLetter ;we found a match theEnd: mov DWORD[FirstTarget], 0x00000000 mov WORD[ToonsChecked], 0x0000 stc ret notFound: ;mov ECX, [0x01AA4064] ;ecx=pointer to toon ;mov DWORD[ECX], 0x00 ;target no one mov DWORD[FirstTarget], 0x00000000 mov WORD[ToonsChecked], 0x0000 clc ret rotin WriteMem,MemOffset,DataPtr,dataLen ;Originally by Drakken ;Converted to Nasm syntax by Jakor ;This version for nagoa.inc NOT nagoa+ (by mikel) sectiondata OldProt dd 0 sectioncode call VirtualProtect,[MemOffset],[dataLen],PAGE_EXECUTE_READWRITE,OldProt call RtlMoveMemory,[MemOffset],[DataPtr],[dataLen] call VirtualProtect,[MemOffset],[dataLen],[OldProt],OldProt endrotin rotin JmpPatch,from,to,bMakeCall ;Originally by Drakken ;Converted to Nasm syntax by Jakor ;added bMakeCall to determine Jmp or Call address ;uses ecx,ebx mov ebx, [to] mov ecx, [from] add ecx, 0x05 sub ebx, ecx lea ecx, [lgJmp] cmp dword [bMakeCall],0 je .MakeCall mov byte [ecx], 0xEB jmp .WriteIt .MakeCall: mov byte [ecx], 0xE8 .WriteIt: mov dword [ecx+1], ebx loccall WriteMem, [from],addr lgJmp, 5 endrotin rotin MsgBox,title,info call MessageBoxA,0,[title],[info],MB_OK call ExitProcess,0 endrotin