


; warcraft 3 cd key grabber by asmhack
; asmhack@live.com
; win32 x86, flat assembler syntax



  format pe console on 'nul'
  entry @@entry
  include 'win32a.inc'



; warcraft 3 uses dma (dynamic memory allocation)
; after some memory analyzing, we can see that RoC key
; is stored everytime at $XXXXXA0 address and the FT key
; is stored 6 bytes after the end of the RoC key
; (the keys are stored encrypted inside an .mpq file after the installation
; and are loaded everytime into the memory when we enter local area network or battle.net)
  WC3_KEY_ADDRESS_PATTERN equ $00000A0
;                                   |
; dma scan addresses jump           |
  WC3_KEY_ADDRESS_JUMP	  equ $0010000
;                                |  |
; maximum address                |  |
  WC3_KEY_ADDRESS_MAX	  equ $FFF0000+WC3_KEY_ADDRESS_PATTERN
;                             $FFF00A0
; key length
  WC3_KEY_LENGTH	  equ $6+$4+$6+$4+$6
;
; key distance |RoC-FT|
  WC3_KEY_DISTANCE	  equ WC3_KEY_LENGTH+$6



  section '' import data code writable readable executable



  library kernel32,'kernel32',user32,'user32',advapi32,'advapi32',crtdll,'crtdll'

  import  kernel32,ExitProcess,'ExitProcess',\
		   GetCurrentProcess,'GetCurrentProcess',\
		   Sleep,'Sleep',\
		   OpenProcess,'OpenProcess',\
		   ReadProcessMemory,'ReadProcessMemory'

  import    user32,FindWindowA,'FindWindowA',\
		   GetWindowThreadProcessId,'GetWindowThreadProcessId',\
		   GetAsyncKeyState,'GetAsyncKeyState'

  import  advapi32,OpenProcessToken,'OpenProcessToken',\
		   LookupPrivilegeValueA,'LookupPrivilegeValueA',\
		   AdjustTokenPrivileges,'AdjustTokenPrivileges'

  import    crtdll,printf,'printf'



  struc TOKEN_PRIVILEGES
{ .privilegecount  dd $0
  .low		   dd $0
  .high 	   dd $0
  .attributes	   dd $0 } tkp TOKEN_PRIVILEGES



  roc		   db 'RoC: ',$0
  ft		   db $D,$A,'FT:  ',$0



  SE_DEBUG_NAME    db 'SeDebugPrivilege',$0
  WC3_WND_NAME	   db 'Warcraft III',$0



  pro		   dd $0
  tmp		   dd $0
  chr		   db $0
  buffer	   rb WC3_KEY_LENGTH+$1    ; buffer to store key
					   ; (size = key length + 1 (null-terminated string))
  message	   rb WC3_KEY_LENGTH+$4+$1 ; buffer to store final formated key
					   ; (size = key length + 4 seperators (-) + 1 (null-terminated string))



  @@entry:
  xor	   ebx,ebx

  call	   [GetCurrentProcess]				     ; get debug privileges
  stdcall  [OpenProcessToken],eax,$28,tmp		     ; so we can access/read process memory
  stdcall  [LookupPrivilegeValueA],ebx,SE_DEBUG_NAME,tkp.low
  mov	   dword[tkp.privilegecount],$1
  mov	   dword[tkp.attributes],$2
  stdcall  [AdjustTokenPrivileges],[tmp],ebx,tkp,ebx,ebx,ebx

  @@switch:
  stdcall  [Sleep],$FF					     ; wait for [Insert] key press
  stdcall  [GetAsyncKeyState],VK_INSERT 		     ; the key should be pressed after
  test	   eax,eax					     ; we enter [Local Area Network] in the game
  jz	   @@switch

  stdcall  [FindWindowA],ebx,WC3_WND_NAME		     ; is the game opened ?
  test	   eax,eax
  jz	   @@switch

  stdcall  [GetWindowThreadProcessId],eax,tmp		     ; get process handle
  stdcall  [OpenProcess],PROCESS_ALL_ACCESS,ebx,[tmp]
  mov	   [pro],eax

  mov	   ebp,WC3_KEY_ADDRESS_PATTERN

  @@scan:						     ; scan the memory for the key
  cmp	   ebp,WC3_KEY_ADDRESS_MAX
  jz	   @@switch
  lea	   ebp,[ebp+WC3_KEY_ADDRESS_JUMP]
  stdcall  [ReadProcessMemory],[pro],ebp,chr,$1,ebx
  test	   eax,eax
  jz	   @@scan
  mov	   [tmp],ebp
  jmp	   @f
  @@check:
  stdcall  [ReadProcessMemory],[pro],[tmp],chr,$1,ebx
  test	   eax,eax
  jz	   @@scan
  @@:
  cmp	   byte[chr],$30				     ; A <= byte <= Z or 0 <= byte <= 9
  jb	   @@scan
  cmp	   byte[chr],$5A
  ja	   @@scan
  cmp	   byte[chr],$3A
  jb	   @f
  cmp	   byte[chr],$40
  jbe	   @@scan
  @@:
  inc	   [tmp]
  mov	   eax,[tmp]
  sub	   eax,ebp
  cmp	   eax,WC3_KEY_LENGTH				     ; check until we have whole the key
  jb	   @@check

  sub	   [tmp],WC3_KEY_LENGTH
  stdcall  [ReadProcessMemory],[pro],[tmp],buffer,WC3_KEY_LENGTH,ebx ; read RoC key
  call	   @@format						     ; format
  cinvoke  printf,roc						     ; display
  cinvoke  printf,message
  add	   [tmp],WC3_KEY_DISTANCE
  stdcall  [ReadProcessMemory],[pro],[tmp],buffer,WC3_KEY_LENGTH,ebx ; read FT key
  call	   @@format						     ; format
  cinvoke  printf,ft						     ; display
  cinvoke  printf,message
  stdcall  [Sleep],-$1

  @@format:							     ; insert 4 seperators (-)
  mov	   ecx,buffer
  mov	   edx,message
  mov	   eax,dword[ecx]
  mov	   dword[edx],eax
  mov	   ax,word[ecx+$4]
  mov	   word[edx+$4],ax
  mov	   byte[edx+$6],'-'
  mov	   eax,dword[ecx+$6]
  mov	   dword[edx+$7],eax
  mov	   byte[edx+$B],'-'
  mov	   eax,dword[ecx+$A]
  mov	   dword[edx+$C],eax
  mov	   ax,word[ecx+$E]
  mov	   word[edx+$10],ax
  mov	   byte[edx+$12],'-'
  mov	   eax,dword[ecx+$10]
  mov	   dword[edx+$13],eax
  mov	   byte[edx+$17],'-'
  mov	   eax,dword[ecx+$14]
  mov	   dword[edx+$18],eax
  mov	   ax,word[ecx+$18]
  mov	   word[edx+$1C],ax
  ret