All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.darkatra.injector.ProcessUtils.kt Maven / Gradle / Ivy

The newest version!
package de.darkatra.injector

import com.sun.jna.Memory
import com.sun.jna.Pointer
import com.sun.jna.platform.win32.Kernel32
import com.sun.jna.platform.win32.WinDef
import com.sun.jna.platform.win32.WinNT
import com.sun.jna.ptr.IntByReference
import de.darkatra.injector.jna.Psapi
import java.util.logging.Logger

internal object ProcessUtils {

    private val LOGGER = Logger.getLogger(ProcessUtils::class.qualifiedName)

    // x86
    private val IMAGE_FILE_MACHINE_I386: Short = 0x014cu.toShort()

    // x64
    private val IMAGE_FILE_MACHINE_AMD64: Short = 0x8664u.toShort()

    fun getProcessArchitecture(processHandle: WinNT.HANDLE, moduleBaseAddress: Long): ProcessArchitecture {

        val offsetToPESignature = readInt(
            processHandle,
            Pointer.createConstant(moduleBaseAddress + OFFSET_TO_PE_SIGNATURE_POINTER)
        )

        val imageFileMachine = readShort(
            processHandle,
            Pointer.createConstant(moduleBaseAddress + offsetToPESignature + 4)
        )

        return when (imageFileMachine) {
            IMAGE_FILE_MACHINE_I386 -> ProcessArchitecture.X_86
            IMAGE_FILE_MACHINE_AMD64 -> ProcessArchitecture.X_64
            else -> throw InjectionException("Unsupported image file machine: $imageFileMachine")
        }
    }

    fun getRemoteModuleHandle(processHandle: WinNT.HANDLE, name: String): WinDef.HMODULE? {

        val modules = arrayOfNulls(1024)
        val modulesSizeNeeded = IntByReference()

        val successful = Psapi.INSTANCE.EnumProcessModulesEx(
            processHandle,
            modules,
            modules.size,
            modulesSizeNeeded,
            Psapi.LIST_MODULES_ALL
        )
        if (!successful) {
            throw InjectionException("Failed to enumerate process modules, error code: ${Kernel32.INSTANCE.GetLastError()}")
        }

        if (modulesSizeNeeded.value > modules.size) {
            LOGGER.warning("Only iterating the first ${modules.size} modules but this process has ${modulesSizeNeeded.value} modules.")
        }

        return modules.filterNotNull().firstOrNull { module ->

            val moduleName = try {
                ModuleUtils.getModuleName(processHandle, module)
            } catch (e: InjectionException) {
                LOGGER.warning(e.message)
                return@firstOrNull false
            }

            moduleName.equals(name, true)
        }
    }

    /**
     * Reads a 32-bit integer from the given address.
     */
    fun readInt(processHandle: WinNT.HANDLE, address: Pointer): Int {

        return readProcessMemory(
            processHandle,
            address,
            4
        ) { it: Memory ->
            it.getInt(0)
        }
    }

    /**
     * Reads a 16-bit integer from the given address.
     */
    fun readShort(processHandle: WinNT.HANDLE, address: Pointer): Short {

        return readProcessMemory(
            processHandle,
            address,
            2
        ) { it: Memory ->
            it.getShort(0)
        }
    }

    fun  readProcessMemory(processHandle: WinNT.HANDLE, address: Pointer, bytesToRead: Int, mappingFunction: (Memory) -> T): T {

        return Memory(bytesToRead.toLong()).use { memory ->

            val success = Kernel32.INSTANCE.ReadProcessMemory(
                processHandle,
                address,
                memory,
                bytesToRead,
                null
            )
            if (!success) {
                throw RuntimeException("Failed to read process memory, error code: ${Kernel32.INSTANCE.GetLastError()}")
            }

            mappingFunction(memory)
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy