format PE GUI 4.0
entry start

include 'win32a.inc'

TH32CS_SNAPPROCESS = 2
PROCESS_QUERY_INFORMATION = 400h

section '.text' code readable executable

  start:

	invoke	GetModuleHandle,0
	mov	[h_process],eax
	call	GetBaseAddress

  exit:
	invoke	ExitProcess,0

proc GetBaseAddress
	push	ebx esi edi
	call	GetGameProcessHandle
	cmp	eax,0
	je	error_GameProcess
	mov	eax,sizeof.MEMORY_BASIC_INFORMATION
	invoke	VirtualQueryEx,[h_game],NULL,procBase,eax
	invoke	wsprintfA,CaptionBaseAddress,fmt,[procBase.BaseAddress]
	invoke	MessageBoxA,HWND_DESKTOP,CaptionBaseAddress,TitleBaseAddress,MB_OK
	invoke	CloseHandle,[h_game]
	jmp	continue
  error_GameProcess:
	invoke	MessageBoxA,HWND_DESKTOP,ErrorGetGameProcessHandle,Title,MB_ICONERROR
  continue:
	pop	edi esi ebx
	ret
endp

proc GetGameProcessHandle
	invoke	CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0
	mov	[h_snapshot],eax
	mov	[procEntry.dwSize],sizeof.PROCESSENTRY32
	invoke	Process32First,[h_snapshot],procEntry
	cmp	eax,0
	je	error_Process32First
  loop_process:
	invoke	lstrcmpi,procEntry.szExeFile,gamename
	cmp	eax,0
	je	process_found
	invoke	Process32Next,[h_snapshot],procEntry
	cmp	eax,0
	je	error_nomorefiles
	jmp	loop_process
  process_found:
	mov	eax,dword[procEntry.th32ProcessID]
	mov	[pid_game],eax
	;invoke  OpenProcess,PROCESS_ALL_ACCESS,FALSE,[pid_game]
	invoke	OpenProcess,PROCESS_QUERY_INFORMATION,FALSE,[pid_game]
	cmp	eax,0
	je	error_OpenProcess
	mov	[h_game],eax
	jmp	goodexit
  error_nomorefiles:
	invoke	MessageBoxA,HWND_DESKTOP,ErrorProcess32Next,Title,MB_ICONERROR
	xor	eax,eax
	jmp	finishproc
  error_Process32First:
	invoke	MessageBoxA,HWND_DESKTOP,ErrorProcess32First,Title,MB_ICONERROR
	xor	eax,eax
	jmp	finishproc
  error_OpenProcess:
	invoke	MessageBoxA,HWND_DESKTOP,ErrorOpenProcess,Title,MB_ICONERROR
	xor	eax,eax
	jmp	finishproc
  goodexit:
	invoke	CloseHandle,[h_snapshot]
	mov	eax,[h_game]
  finishproc:
	ret
endp

section '.data' data readable writable

  struct PROCESSENTRY32
	dwSize			dd ?
	cntUsage		dd ?
	th32ProcessID		dd ?
	th32DefaultHeapID	dd ?
	th32ModuleID		dd ?
	cntThreads		dd ?
	th32ParentProcessID	dd ?
	pcPriClassBase		dd ?
	dwFlags 		dd ?
	szExeFile		dw MAX_PATH dup (?)
  ends

  struct MEMORY_BASIC_INFORMATION
	 BaseAddress		dd ?
	 AllocationBase 	dd ?
	 AllocationProtect	dd ?
	 RegionSize		dd ?
	 State			dd ?
	 Protect		dd ?
	 Type			dd ?
  ends


  procBase   MEMORY_BASIC_INFORMATION
  procEntry  PROCESSENTRY32

  TitleBaseAddress	    db 'Base Address',0
  fmt			    db 'Base Address is: 0x%lX',0
  Title 		    db 'Error',0
  ErrorProcess32First	    db 'Process32First: Process Not Found.',0
  ErrorProcess32Next	    db 'Process32Next: Process Not Found.',0
  ErrorOpenProcess	    db 'OpenProcess: Error opening process.',0
  ErrorGetGameProcessHandle db 'GetGameProcessHandle: Error getting it.',0
  gamename		    db 'FASMW.exe',0

section '.bss' readable writeable

  h_process  dd ? ;handles to the executable process.
  h_thread   dd ? ;handles of the new thread.
  h_snapshot dd ?
  h_game     dd ? ;handles to the game process
  pid_thread dd ? ;PID of the new thread.
  pid_game   dd ? ;PID of the game
  gBase      dd ? ;Game Base Address (most of the times 0x00400000)
  CaptionBaseAddress rb 100h

section '.idata' import data readable writeable

  library kernel,'KERNEL32.DLL',\
	  user,'USER32.DLL'

  import kernel,\
	 GetModuleHandle,'GetModuleHandleA',\
	 CloseHandle,'CloseHandle',\
	 CreateToolhelp32Snapshot,'CreateToolhelp32Snapshot',\
	 Process32First,'Process32First',\
	 Process32Next,'Process32Next',\
	 lstrcmpi,'lstrcmpi',\
	 OpenProcess,'OpenProcess',\
	 CreateThread,'CreateThread',\
	 ExitThread,'ExitThread',\
	 VirtualQueryEx,'VirtualQueryEx',\
	 Sleep,'Sleep',\
	 ExitProcess,'ExitProcess'

  import user,\
	 DialogBoxParam,'DialogBoxParamA',\
	 IsDlgButtonChecked,'IsDlgButtonChecked',\
	 MessageBoxA,'MessageBoxA',\
	 wsprintfA,'wsprintfA',\
	 EndDialog,'EndDialog'