Since there is very little in the way of Unicode/ascii comparison, or Unicode in general Ive found that writing them myself can be very useful. This compares a Unicode string to a ascii string. It could be used the other way around but it will stop when it reaches the null char in the Unicode string so you would have to be carefull when using it to compare ascii strings to Unicode strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; 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 |
You can just set up your strings and then call it, then je or jne to act accordingly. It will stop when the unicode string has a null char (not a space) so i hope your strings are terminated by a null char.
example usage
1 2 3 4 | mov ecx, UniString ; unicode string mov ebx, AsciiString ; Ascii string loccall UniAsciiCmp ; do comparison jne notequal ; jump if they are not equal |
This was the last version of sbtools I made. It was a huge sucess. I went way out of the box and made the entire thing in nasm using nagoa+ and the nagoa ide. Most people use masm, but nasm is closer to masm than att syntax.
Of course, I have not messed with this in a very long time. I think I stopped somewhere in the beggining of ‘08 thanks to a encouraging letter from ubisofts legal department.
Some people have messaged me asking for the “new” version, after some investigating I found out there is a illeged version 4 out there. I have nothing to do with that version, from what I hear its based of my code and made by the asians.
I have stopped making these types of programs in 100% asm, I now use c++ with inline asm, lots of inline asm. I have done some stuff for starcraft while I was bored, that way I stay on top of things.
Here is the entire thing, I added it here so the highlighting would help ppl read it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | %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 |

Categories
Tag Cloud
Blog RSS
Comments RSS

Void « Default
Life
Earth
Wind
Water
Fire
Light 