Created
January 22, 2022 00:40
-
-
Save Auax/d6556564b6ace69b1924730c07ce2fa6 to your computer and use it in GitHub Desktop.
Change Assault Cube's rifle ammo using this simple external script. Although this is a simple demonstration, it can be freely used.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ASSAULT CUBE Go external cheat. | |
// The objective of this script is to show how to perform operations such as writing / reading the memory of a process. | |
// With this script, you can change the rifle ammo inside the game. | |
// You can set the ammo's value, ammo's address offset, and more inside the main() function. | |
// Note: The window must be windowed for this to work. | |
// BY AUAX 2006 | |
package main | |
import ( | |
"fmt" | |
"log" | |
"os" | |
"syscall" | |
"unsafe" | |
) | |
var ( | |
user32 = syscall.MustLoadDLL("user32.dll") | |
kernel32 = syscall.MustLoadDLL("kernel32.dll") | |
procEnumWindows = user32.MustFindProc("EnumWindows") | |
procGetWindowTextW = user32.MustFindProc("GetWindowTextW") | |
) | |
//goland:noinspection GoSnakeCaseUsage | |
const ( | |
PROCESS_ALL_ACCESS = 0x1F0FFF | |
) | |
func EnumWindows(enumFunc uintptr, lparam uintptr) (err error) { | |
r1, _, e1 := syscall.SyscallN(procEnumWindows.Addr(), enumFunc, lparam, 0) | |
if r1 == 0 { | |
if e1 != 0 { | |
err = error(e1) | |
} else { | |
err = syscall.EINVAL | |
} | |
} | |
return | |
} | |
func GetWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) { | |
r0, _, e1 := syscall.SyscallN(procGetWindowTextW.Addr(), uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount)) | |
len = int32(r0) | |
if len == 0 { | |
if e1 != 0 { | |
err = error(e1) | |
} else { | |
err = syscall.EINVAL | |
} | |
} | |
return | |
} | |
func FindWindow(title string) (syscall.Handle, error) { | |
var hwnd syscall.Handle | |
cb := syscall.NewCallback(func(h syscall.Handle, p uintptr) uintptr { | |
b := make([]uint16, 200) | |
_, err := GetWindowText(h, &b[0], int32(len(b))) | |
if err != nil { | |
// Ignore the error | |
return 1 // Continue enumeration | |
} | |
if syscall.UTF16ToString(b) == title { | |
// Note the window | |
hwnd = h | |
return 0 // Stop enumeration | |
} | |
return 1 // Continue enumeration | |
}) | |
EnumWindows(cb, 0) | |
if hwnd == 0 { | |
return 0, fmt.Errorf("no window with title '%s' found", title) | |
} | |
return hwnd, nil | |
} | |
func GetWindowThreadProcessId(hwnd uintptr) uintptr { | |
var processId uintptr = 0 | |
prc := user32.MustFindProc("GetWindowThreadProcessId") | |
ret, _, err := prc.Call(hwnd, uintptr(unsafe.Pointer(&processId))) | |
fmt.Println("ProcessID:", processId, "ret:", ret, "Message:", err) | |
return processId | |
} | |
func OpenProcessHandle(pid int) uintptr { | |
proc := kernel32.MustFindProc("OpenProcess") | |
handle, _, _ := proc.Call(PROCESS_ALL_ACCESS, ptr(true), ptr(pid)) | |
return handle | |
} | |
func ProcessMemory(name string, handle uintptr, lpBaseAddress uintptr, lpBuffer *uintptr, nSize uintptr) (uintptr, error) { | |
readProcMem := kernel32.MustFindProc(name) | |
//var length uint64 // length of bytes written / read | |
res, _, err := readProcMem.Call( | |
handle, // HANDLE hProcess | |
lpBaseAddress, // LPCVOID lpBaseAddress (memory address to read) | |
uintptr(unsafe.Pointer(&(*lpBuffer))), // LPCVOID lpBuffer (&buff) | |
nSize, // DWORD nSize [sizeof(int*)] | |
uintptr(0)) // LPDWORD lpNumberOfBytesRead/Written (length, optional) | |
return res, err | |
} | |
func ReadProcessMemory(handle uintptr, lpBaseAddress uintptr, lpBuffer *uintptr, nSize uintptr) (uintptr, error) { | |
return ProcessMemory("ReadProcessMemory", handle, lpBaseAddress, &(*lpBuffer), nSize) | |
} | |
func WriteProcessMemory(handle uintptr, lpBaseAddress uintptr, lpBuffer *uintptr, nSize uintptr) (uintptr, error) { | |
return ProcessMemory("WriteProcessMemory", handle, lpBaseAddress, &(*lpBuffer), nSize) | |
} | |
func ptr(val interface{}) uintptr { | |
switch val.(type) { | |
case string: | |
utf16ptr, _ := syscall.UTF16PtrFromString(val.(string)) | |
return uintptr(unsafe.Pointer(utf16ptr)) | |
case int: | |
return uintptr(val.(int)) | |
default: | |
return uintptr(0) | |
} | |
} | |
func main() { | |
var ammoValue uintptr = 100 | |
var ammoBaseAddr uintptr = 0x57B0B8 | |
var ammoOffset uintptr = 0x140 | |
const title = "AssaultCube" | |
// Find window's handle address | |
hwnd, err := FindWindow(title) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Get PID from the handle address | |
pid := GetWindowThreadProcessId(uintptr(hwnd)) | |
fmt.Printf("Found '%s' window: HWND=0x%x -> PID=%d\n", title, hwnd, pid) | |
// Attach process | |
handle := OpenProcessHandle(int(pid)) | |
// Check if the handle is defined | |
if handle == 0 { | |
log.Fatal("Handle error!") | |
os.Exit(-1) // Abort execution | |
} | |
fmt.Printf("PID: %d\n", int(pid)) | |
fmt.Printf("handle: %d\n", handle) | |
var ammoPtr uintptr | |
i := 1 | |
ReadProcessMemory(handle, ammoBaseAddr, &ammoPtr, unsafe.Sizeof(i)) | |
fmt.Printf("0x%d ptr -> 0x%d ] + %d", ammoBaseAddr, ammoPtr, ammoOffset) | |
ammoAddr := ammoPtr + ammoOffset | |
WriteProcessMemory(handle, ammoAddr, &ammoValue, unsafe.Sizeof(i)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment