1. Skin36
  2. DwarfTherapistPY

Source

DwarfTherapistPY / dfinstancewinddows.py

"""
Dwarf Therapist
Copyright (c) 2009 Trey Stout (chmod)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""

from ctypes import *
from ctypes.wintypes import *
from win_structs import *
# from PyQt4 import QtGui, QtCore
from truncatingfilelogger import logger
from utils import *

PROCESS_QUERY_INFORMATION=0x0400
PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
PROCESS_VM_OPERATION = 0x0008

OpenProcess = ctypes.windll.kernel32.OpenProcess
FindWindow = ctypes.windll.user32.FindWindowA
GetWindowThreadProcessId=ctypes.windll.user32.GetWindowThreadProcessId
#удалить
CloseHandle = windll.kernel32.CloseHandle

ReadProcessMemory = windll.kernel32.ReadProcessMemory
ReadProcessMemory.argtypes = [HANDLE, LPCVOID, LPVOID, SIZE_T, SIZE_T_p]
ReadProcessMemory.restype = BOOL

def DFInstanceWindows():
    if m_proc:
        CloseHandle(m_proc)
    return

def calculate_checksum():
    # logger.debug('Target EXE was compiled at %s',compile_timestamp.toString(Qt.ISODate))
    pass 

def enumerate_vector(addr):
    logger.trace ("beginning vector enumeration at %s" ,hex(addr))
#   QVector<VIRTADDR> addresses;
#   VIRTADDR start = read_addr(addr + 4);
    logger.trace ("start of vector %s" ,hex(start))
#   VIRTADDR end = read_addr(addr + 8);
    logger.trace ("end of vector %s" ,hex(end))

#   int entries = (end - start) / sizeof(VIRTADDR);
    logger.trace ("there appears to be %s entries in this vector", entries)

    logger.warning("vector at %s has over 5000 entries! (%s)", hex(addr),entries)

    logger.trace ("FOUND %s addresses in vector at %s", addresses.size(),hex(addr))
    pass 

def read_string(addr):
    logger.warning("Tried to read a string at %s but it was totally not a string...", hex(addr))
    pass 
   
def write_string(addr,str):
    pass

def write_int(addr,val):
    pass
   
def read_raw(addr,bytes, buffer):
    pass
  
def write_raw(addr,bytes, buffer):
    pass


def find_running_copy():
    m_is_ok = False
    logger.debug('attempting to find running copy of DF by window handle')
    #получаем дискриптор окна    
    hwnd = FindWindow(None, b"Dwarf Fortress")
    if hwnd==0:
        hwnd = FindWindow(b"SDL_app", b"Dwarf Fortress")
    if hwnd==0:
        hwnd = FindWindow(None, b"Dwarf Fortress")
    if hwnd==0:
#        QMessageBox.warning(self, self.tr("Warning"), self.tr("Unable to locate a running copy of Dwarf "
#        "Fortress, are you sure it's running?"))
        logger.warning("can't find running copy")
        return m_is_ok
    
    logger.debug("found copy with HWND: %s", hex(hwnd))
    
    pid = 0
    pid = c_int()
    windll.user32.GetWindowThreadProcessId(hwnd,byref(pid))
    pid=pid.value
    if pid==0:
        return m_is_ok
    logger.debug("PID of process is: %s", pid)
    m_pid = pid
#    m_hwnd = hwnd

    m_proc = OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ| PROCESS_VM_OPERATION| PROCESS_VM_WRITE, False, m_pid)   
    logger.debug("PROC HANDLE: %s", hex(m_proc)) 
    if m_proc==0:
       logger.error("Error opening process! %s", GetLastError())
    
    peb_addr = GetPebAddress(m_proc)
    logger.debug("PEB is at: %s", hex(peb_addr))
       
#    connection_error = QtCore.QString (tr("I'm sorry. I'm having trouble connecting to "
#        "DF. I can't seem to locate the PEB address "
#        "of the process. \n\nPlease re-launch DF and "
#        "try again."))

    if peb_addr == 0:
        QtGui.QMessageBox(QtGui.QMessageBox.Critical,
        connection_error, "PEB address came back as 0",
        buttons = QtGui.QMessageBox.Ok)

    else:
        peb=PEB()
        bytes=c_ulong(0)
        if ReadProcessMemory(m_proc, peb_addr,byref(peb), sizeof(peb), byref(bytes)):
            logger.debug("read %s bytes BASE ADDR is at: %s",bytes.value,hex(peb.ImageBaseAddress))
            m_base_addr = peb.ImageBaseAddress
            m_is_ok = True
            CloseHandle(m_proc)
        else:
#            QtGui.QMessageBox(QtGui.QMessageBox.Critical,
#            connection_error, "unable to read remote PEB!", GetLastError(),
#            buttons = QtGui.QMessageBox.Ok)
#            logger.critical("unable to read remote PEB!",GetLastError())
            m_is_ok = False

    logger.debug("base address: %s", hex(m_base_addr))
#    logger.debug("memory correction: %s", hex(m_memory_correction))

#    logger.debug("GetModuleFileNameEx returned: %s", exe_path)
#    logger.info("Dwarf fortress path: %s", m_df_dir.absolutePath())

    m_is_ok = True
    return m_is_ok







find_running_copy()


def map_virtual_memory():
# start by figuring out what kernel we're talking to
    logger.trace("Mapping out virtual memory")
    # SYSTEM_INFO info;
    # GetSystemInfo(&info);
    logger.trace( "PROCESSORS: %s", info.dwNumberOfProcessors)
    logger.trace("PROC TYPE: %s %s %s", info.wProcessorArchitecture,
                 info.wProcessorLevel,
                 info.wProcessorRevision)
    loger.trace("PAGE SIZE %s", info.dwPageSize)
    loger.trace("MIN ADDRESS: %s", hex(info.lpMinimumApplicationAddress))
    loger.trace("MAX ADDRESS: %s", hex(info.lpMaximumApplicationAddress))

    loger.trace("FOUND READABLE COMMITED MEMORY SEGMENT FROM %s - %s SIZE: %sKB FLAGS: %s",
                hex(segment_start),
                hex(segment_start + segment_size),
                (segment_size / 1024.0),
                mbi.Protect)
    loger.trace("REJECTING MEMORY SEGMENT AT %sKB, FLAGS: %s, SIZE: %s" ,hex(segment_start),
    (segment_size / 1024.0),mbi.Protect)

    logger.debug("MEMORY SEGMENT SUMMARY: accepted %s, rejected %s, total %s", accepted, rejected, accepted + rejected)
    pass

def authorize():
    return true


#hwnd = FindWindow("SDL_app", "Dwarf Fortress")
#    if not hwnd:
#        hwnd = FindWindow(NULL, "Dwarf Fortress")
#    if not hwnd:
#        QMessageBox::warning(0, tr("Warning"),
#            tr("Unable to locate a running copy of Dwarf "
#            "Fortress, are you sure it's running?"))
#        print("can't find running copy")
#    return threadID

#print (ReadProcessMemory(h, peb_addr, buf, size, ctypes.byref(gotBytes)))