diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/build.gradle b/Ghidra/Debug/Debugger-agent-dbgeng/build.gradle index 4f218b4165..8ea79a8ce0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/build.gradle +++ b/Ghidra/Debug/Debugger-agent-dbgeng/build.gradle @@ -21,7 +21,6 @@ apply from: "$rootProject.projectDir/gradle/distributableGhidraModule.gradle" apply from: "$rootProject.projectDir/gradle/debugger/hasNodepJar.gradle" apply from: "$rootProject.projectDir/gradle/debugger/hasPythonPackage.gradle" -apply from: "buildNatives.gradle" apply plugin: 'eclipse' eclipse.project.name = 'Debug Debugger-agent-dbgeng' @@ -37,12 +36,45 @@ dependencies { testImplementation project(path: ":Debugger-gadp", configuration: 'testArtifacts') } -// Include buildable native source in distribution -rootProject.assembleDistribution { - from (this.project.projectDir.toString()) { - include "src/**" - into { getZipPath(this.project) } - } +if ("win_x86_64".equals(getCurrentPlatformName())) { + + String makeName = "win_x86_64DbgmodelTlbMake" + task(type: Exec, makeName) { + ext.tmpBatch = file("build/buildTlb.bat") + ext.idl = file("src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl") + ext.tlb = file("build/os/win_x86_64/dbgmodel.tlb") + inputs.file(idl) + outputs.file(tlb) + + doFirst { + file(tlb).parentFile.mkdirs() + def midlCmd = "midl /tlb ${tlb} ${idl}" + println "Executing: " + midlCmd + + tmpBatch.withWriter { out -> + out.println "call " + VISUAL_STUDIO_VCVARS_CMD + out.println midlCmd + } + } + doLast { + assert file(tlb).exists() : "Failed to build dbgmodel.tlb" + } + + commandLine "cmd", "/c", tmpBatch + } + + tasks.assemblePyPackage { + from(tasks."$makeName") { + into("src/ghidradbg/dbgmodel/tlb") + } + } +} +else { + tasks.assemblePyPackage { + from(rootProject.BIN_REPO + '/' + getGhidraRelativePath(project) + "/os/win_x86_64/dbgmodel.tlb") { + into("src/ghidradbg/dbgmodel/tlb") + } + } } tasks.nodepJar { diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/buildNatives.gradle b/Ghidra/Debug/Debugger-agent-dbgeng/buildNatives.gradle deleted file mode 100644 index 38a8306d5d..0000000000 --- a/Ghidra/Debug/Debugger-agent-dbgeng/buildNatives.gradle +++ /dev/null @@ -1,49 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -if ("win_x86_64".equals(getCurrentPlatformName())) { - - String makeName = "win_x86_64TlbMake" - task(type: Exec, makeName) { - - def projectPath = projectDir.toString() - def solutionBatchFilePath = projectPath + "/build/buildSolution.bat" - def projectPathWindows = projectPath.replace("/", File.separator) - - doFirst { - file("build/os/win_x86_64").mkdirs() - - def srcdir = "src/main/py/src/dbgmodel" - def msbuildCmd = "midl /tlb build/os/win_x86_64/dbgmodel.tlb ${srcdir}/DbgModel.idl" - - println "Executing: " + msbuildCmd - - new File(solutionBatchFilePath).withWriter { out -> - out.println "call " + VISUAL_STUDIO_VCVARS_CMD - out.println msbuildCmd - } - } - - doLast { - assert file("build/os/win_x86_64/dbgmodel.tlb").exists() : "Failed to build dbgmodel.tlb" - } - - executable "cmd" - - args "/c" - args solutionBatchFilePath.replace("/", File.separator) - } -} diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/certification.manifest b/Ghidra/Debug/Debugger-agent-dbgeng/certification.manifest index caa6d946db..1ff44acca4 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/certification.manifest +++ b/Ghidra/Debug/Debugger-agent-dbgeng/certification.manifest @@ -5,5 +5,5 @@ data/debugger-launchers/local-dbgeng.bat||GHIDRA||||END| src/main/py/LICENSE||GHIDRA||||END| src/main/py/README.md||GHIDRA||||END| src/main/py/pyproject.toml||GHIDRA||||END| -src/main/py/src/dbgmodel/DbgModel.idl||GHIDRA||||END| +src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl||GHIDRA||||END| src/main/py/src/ghidradbg/schema.xml||GHIDRA||||END| diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/pyproject.toml b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/pyproject.toml index 9972ad4aec..9aea393d5e 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/pyproject.toml +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/pyproject.toml @@ -18,7 +18,7 @@ classifiers = [ ] dependencies = [ "ghidratrace==10.4", - "pybag>=2.2.8" + "pybag>=2.2.9" ] [project.urls] diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py index 536e1b3473..6c5fc1de71 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/__init__.py @@ -13,45 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from . import util, commands, methods, hooks -from dbgmodel.ihostdatamodelaccess import HostDataModelAccess -import ctypes -import platform -import os +# NOTE: libraries must precede EVERYTHING, esp pybag and DbgMod -ctypes.windll.kernel32.SetErrorMode(0x0001 | 0x0002 | 0x8000) - -if platform.architecture()[0] == '64bit': - dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'), - r'C:\Program Files\Windows Kits\10\Debuggers\x64', - r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64'] -else: - dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'), - r'C:\Program Files\Windows Kits\10\Debuggers\x86', - r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x86'] -dbgdir = None -for _dir in dbgdirs: - if os.path.exists(_dir): - dbgdir = _dir - break - -if not dbgdir: - raise RuntimeError("Windbg install directory not found!") - -# preload these to get correct DLLs loaded -try: - ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbghelp.dll')) -except Exception as exc: - print(f"LoadLibrary failed: {dbgdir}\dbghelp.dll {exc}") - pass -try: - ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbgeng.dll')) -except Exception as exc: - print(f"LoadLibrary failed: {dbgdir}\dbgeng.dll {exc}") - pass -try: - ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'DbgModel.dll')) -except Exception as exc: - print(f"LoadLibrary failed: {dbgdir}\dbgmodel.dll {exc}") - pass +from . import libraries, util, commands, methods, hooks diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py index 6a393eb55c..652c5f5c5f 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/arch.py @@ -14,11 +14,11 @@ # limitations under the License. ## from ghidratrace.client import Address, RegVal - from pybag import pydbg from . import util + language_map = { 'ARM': ['AARCH64:BE:64:v8A', 'AARCH64:LE:64:AppleSilicon', 'AARCH64:LE:64:v8A', 'ARM:BE:64:v8', 'ARM:LE:64:v8'], 'Itanium': [], diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py index e693937a4d..adcd78d6c0 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/commands.py @@ -22,15 +22,14 @@ import socket import sys import time +from ghidratrace import sch +from ghidratrace.client import Client, Address, AddressRange, TraceObject from pybag import pydbg, userdbg, kerneldbg from pybag.dbgeng import core as DbgEng from pybag.dbgeng import exception -from dbgmodel.imodelobject import ModelObjectKind - -from ghidratrace import sch -from ghidratrace.client import Client, Address, AddressRange, TraceObject from . import util, arch, methods, hooks +from .dbgmodel.imodelobject import ModelObjectKind PAGE_SIZE = 4096 diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/DbgModel.idl b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl similarity index 100% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/DbgModel.idl rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/DbgModel.idl diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/__init__.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/__init__.py new file mode 100644 index 0000000000..79e3c794a2 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/__init__.py @@ -0,0 +1,20 @@ +## ### +# IP: GHIDRA +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## +import os + + +def module_locator(): + return os.path.dirname(os.path.realpath(__file__)) diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idatamodelmanager.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idatamodelmanager.py similarity index 92% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idatamodelmanager.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idatamodelmanager.py index d0734a66d2..55a0d41a43 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idatamodelmanager.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idatamodelmanager.py @@ -13,12 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception -import dbgmodel.imodelobject as mo + +from . import imodelobject as mo + class DataModelManager(object): def __init__(self, mgr): @@ -41,43 +43,43 @@ class DataModelManager(object): def AcquireNamedModel(self, modelName, modelObject): raise exception.E_NOTIMPL_Error - + def Close(self): raise exception.E_NOTIMPL_Error - + def CreateNoValue(self, object): raise exception.E_NOTIMPL_Error - + def CreateErrorObject(self, error, message, object): raise exception.E_NOTIMPL_Error - + def CreateTypedObject(self, context, objectLocation, objectType, object): raise exception.E_NOTIMPL_Error - + def CreateTypedObjectByReference(self, context, objectLocation, objectType, object): raise exception.E_NOTIMPL_Error - + def CreateSyntheticObject(self, context, object): raise exception.E_NOTIMPL_Error - + def CreateDataModelObject(self, dataModel, object): raise exception.E_NOTIMPL_Error - + def CreateTypedIntrinsicObject(self, intrinsicData, type, object): raise exception.E_NOTIMPL_Error - + def CreateIntrinsicObject(self, objectKind, intrinsicData, object): raise exception.E_NOTIMPL_Error - + def GetModelForTypeSignature(self, typeSignature, dataModel): raise exception.E_NOTIMPL_Error - + def GetModelForType(self, type, dataModel, typeSignature, wildcardMatches): raise exception.E_NOTIMPL_Error - + def RegisterExtensionForTypeSignature(self, typeSignature, dataModel): raise exception.E_NOTIMPL_Error - + def RegisterModelForTypeSignature(self, typeSignature, dataModel): raise exception.E_NOTIMPL_Error @@ -92,5 +94,3 @@ class DataModelManager(object): def UnregisterNamedModel(self, modelName): raise exception.E_NOTIMPL_Error - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idebughost.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idebughost.py similarity index 93% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idebughost.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idebughost.py index 65eac4ec2f..f5539e24db 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/idebughost.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/idebughost.py @@ -13,13 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception from pybag.dbgeng import win32 + class DebugHost(object): def __init__(self, host): self._host = host @@ -38,11 +39,6 @@ class DebugHost(object): def GetDefaultMetadata(self, metadata): raise exception.E_NOTIMPL_Error - + def GetHostDefinedInterface(self, hostUnk): raise exception.E_NOTIMPL_Error - - - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ihostdatamodelaccess.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ihostdatamodelaccess.py similarity index 91% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ihostdatamodelaccess.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ihostdatamodelaccess.py index fde3dc5529..7aa5aadf21 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ihostdatamodelaccess.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ihostdatamodelaccess.py @@ -13,14 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception from .idatamodelmanager import DataModelManager -from .idebughost import DebugHost +from .idebughost import DebugHost + class HostDataModelAccess(object): def __init__(self, hdma): @@ -41,6 +42,3 @@ class HostDataModelAccess(object): hr = self._hdma.GetDataModel(byref(manager), byref(host)) exception.check_err(hr) return (DataModelManager(manager), DebugHost(host)) - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/iiterableconcept.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/iiterableconcept.py similarity index 90% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/iiterableconcept.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/iiterableconcept.py index 9a077a8908..43ce722fd9 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/iiterableconcept.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/iiterableconcept.py @@ -13,20 +13,21 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes import COMError -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * +from comtypes import COMError from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception + from .imodeliterator import ModelIterator + class IterableConcept(object): def __init__(self, concept): self._concept = concept concept.AddRef() - # IterableConcept def GetDefaultIndexDimensionality(self, context, dimensionality): @@ -39,6 +40,3 @@ class IterableConcept(object): except COMError as ce: return None return ModelIterator(iterator) - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ikeyenumerator.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ikeyenumerator.py similarity index 89% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ikeyenumerator.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ikeyenumerator.py index 3f5407abb5..b98d5ca0d6 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/ikeyenumerator.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/ikeyenumerator.py @@ -13,13 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes import BSTR -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * +from comtypes import BSTR from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception -import dbgmodel.imodelobject as mo + +from . import imodelobject as mo + class KeyEnumerator(object): def __init__(self, keys): @@ -46,6 +48,3 @@ class KeyEnumerator(object): def Reset(self): hr = self._keys.Reset() exception.check_err(hr) - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodeliterator.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodeliterator.py similarity index 83% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodeliterator.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodeliterator.py index 2e23db69a1..4d2c8376b5 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodeliterator.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodeliterator.py @@ -13,13 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes import COMError -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * +from comtypes import COMError from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception -import dbgmodel.imodelobject as mo + +from . import imodelobject as mo + class ModelIterator(object): def __init__(self, iter): @@ -33,7 +35,8 @@ class ModelIterator(object): indexer = POINTER(DbgMod.IModelObject)() metadata = POINTER(DbgMod.IKeyStore)() try: - self._iter.GetNext(byref(object), dimensions, byref(indexer), byref(metadata)) + self._iter.GetNext(byref(object), dimensions, + byref(indexer), byref(metadata)) except COMError as ce: return None index = mo.ModelObject(indexer) @@ -43,6 +46,3 @@ class ModelIterator(object): def Reset(self): hr = self._keys.Reset() exception.check_err(hr) - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodelobject.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodelobject.py similarity index 89% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodelobject.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodelobject.py index f7fbb3be6f..f0abda7ca1 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/imodelobject.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/imodelobject.py @@ -13,18 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes import IUnknown, COMError -from comtypes.automation import IID, VARIANT -from comtypes.hresult import S_OK, S_FALSE -from comtypes.gen.DbgMod import * -from enum import Enum +from ctypes import * +from enum import Enum +from comtypes import IUnknown, COMError +from comtypes.automation import IID, VARIANT from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception -from .ikeyenumerator import KeyEnumerator +from comtypes.gen.DbgMod import * + from .iiterableconcept import IterableConcept +from .ikeyenumerator import KeyEnumerator + class ModelObjectKind(Enum): PROPERTY_ACCESSOR = 0 @@ -38,6 +40,7 @@ class ModelObjectKind(Enum): METHOD = 8 KEY_REFERENCE = 9 + class ModelObject(object): def __init__(self, obj): self._obj = obj @@ -56,42 +59,42 @@ class ModelObject(object): def AddParentModel(self, model, contextObject, override): raise exception.E_NOTIMPL_Error - + def ClearConcepts(self): raise exception.E_NOTIMPL_Error - + def ClearKeys(self): raise exception.E_NOTIMPL_Error - + def Compare(self, other, equal): raise exception.E_NOTIMPL_Error - + def Dereference(self, object): raise exception.E_NOTIMPL_Error - + def EnumerateKeyReferences(self): raise exception.E_NOTIMPL_Error - + def EnumerateKeys(self): keys = POINTER(DbgMod.IKeyEnumerator)() hr = self._obj.EnumerateKeys(byref(keys)) if hr != S_OK: return None return KeyEnumerator(keys) - + def EnumerateKeyValues(self): raise exception.E_NOTIMPL_Error - + def EnumerateRawReferences(self, kind, searchFlags): raise exception.E_NOTIMPL_Error - + def EnumerateRawValues(self, kind, searchFlag): keys = POINTER(DbgMod.IRawEnumerator)() hr = self._obj.EnumerateRawValues(kind, searchFlag, byref(keys)) if hr != S_OK: return None return RawEnumerator(keys, kind) - + def GetConcept(self, ref): ifc = POINTER(IUnknown)() metadata = POINTER(DbgMod.IKeyStore)() @@ -102,10 +105,10 @@ class ModelObject(object): def GetContext(self, context): raise exception.E_NOTIMPL_Error - + def GetContextForDataModel(self, dataModelObject, context): raise exception.E_NOTIMPL_Error - + def GetIntrinsicValue(self): var = VARIANT() hr = self._obj.GetIntrinsicValue(var) @@ -123,7 +126,7 @@ class ModelObject(object): raise exception.E_NOTIMPL_Error def GetKeyValue(self, key): - kbuf = cast(c_wchar_p(key),POINTER(c_ushort)) + kbuf = cast(c_wchar_p(key), POINTER(c_ushort)) value = POINTER(DbgMod.IModelObject)() store = POINTER(DbgMod.IKeyStore)() hr = self._obj.GetKeyValue(kbuf, byref(value), byref(store)) @@ -142,16 +145,16 @@ class ModelObject(object): def GetNumberOfParentModels(self, numModels): raise exception.E_NOTIMPL_Error - + def GetParentModel(self, i, model, context): raise exception.E_NOTIMPL_Error - + def GetRawReference(self, kind, name, searchFlags, object): raise exception.E_NOTIMPL_Error - + def GetRawValue(self, kind, name, searchFlags, object): raise exception.E_NOTIMPL_Error - + def GetTargetInfo(self): location = POINTER(DbgMod._Location)() type = POINTER(DbgMod.IDebugHostType)() @@ -161,47 +164,47 @@ class ModelObject(object): def GetTypeInfo(self, type): raise exception.E_NOTIMPL_Error - + def IsEqualTo(self, other, equal): raise exception.E_NOTIMPL_Error - + def RemoveParentModel(self, model): raise exception.E_NOTIMPL_Error - + def SetConcept(self, ref, interface, metadata): raise exception.E_NOTIMPL_Error - + def SetContextForDataModel(self, modelObject, context): raise exception.E_NOTIMPL_Error - + def SetKey(self, key, object, metadata): raise exception.E_NOTIMPL_Error - + def SetKeyValue(self, key, object): raise exception.E_NOTIMPL_Error - + def TryCastToRuntimeType(self, runtimeTypedObject): raise exception.E_NOTIMPL_Error - + # Auxiliary def GetKeyValueMap(self): map = {} keys = self.EnumerateKeys() - (k,v) = keys.GetNext() + (k, v) = keys.GetNext() while k is not None: map[k.value] = self.GetKeyValue(k.value) - (k,v) = keys.GetNext() + (k, v) = keys.GetNext() return map def GetRawValueMap(self): map = {} kind = self.GetKind() keys = self.EnumerateRawValues(kind, c_long(0)) - (k,v) = keys.GetNext() + (k, v) = keys.GetNext() while k is not None: map[k.value] = v - (k,v) = keys.GetNext() + (k, v) = keys.GetNext() return map def GetAttributes(self): @@ -210,12 +213,11 @@ class ModelObject(object): if kind == ModelObjectKind.ERROR: return map if kind == ModelObjectKind.INTRINSIC or \ - kind == ModelObjectKind.TARGET_OBJECT or \ - kind == ModelObjectKind.TARGET_OBJECT_REFERENCE: + kind == ModelObjectKind.TARGET_OBJECT or \ + kind == ModelObjectKind.TARGET_OBJECT_REFERENCE: return self.GetRawValueMap() return self.GetKeyValueMap() - def GetElements(self): list = [] if self.concept is None: @@ -248,7 +250,7 @@ class ModelObject(object): if "x" not in idx: idx = int(idx) else: - idx = int(idx,16) + idx = int(idx, 16) next = next.GetElement(idx) else: next = next.GetKeyValue(element) @@ -268,6 +270,5 @@ class ModelObject(object): kind = self.GetKind() if kind == ModelObjectKind.TARGET_OBJECT or \ kind == ModelObjectKind.INTRINSIC: - return self.GetTargetInfo() + return self.GetTargetInfo() return None - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/irawenumerator.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/irawenumerator.py similarity index 89% rename from Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/irawenumerator.py rename to Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/irawenumerator.py index 273bb096b3..3e284aec03 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/dbgmodel/irawenumerator.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/dbgmodel/irawenumerator.py @@ -13,13 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. ## -from ctypes import * -from comtypes import BSTR -from comtypes.hresult import S_OK, S_FALSE +from ctypes import * +from comtypes import BSTR from comtypes.gen import DbgMod +from comtypes.hresult import S_OK, S_FALSE from pybag.dbgeng import exception -import dbgmodel.imodelobject as mo + +from . import imodelobject as mo + class RawEnumerator(object): def __init__(self, keys, kind): @@ -46,6 +48,3 @@ class RawEnumerator(object): def Reset(self): hr = self._keys.Reset() exception.check_err(hr) - - - diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/libraries.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/libraries.py new file mode 100644 index 0000000000..7aebf5c846 --- /dev/null +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/libraries.py @@ -0,0 +1,69 @@ +## ### +# IP: GHIDRA +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +## +import ctypes +import os +import platform + +import comtypes +import comtypes.client +from ghidradbg import dbgmodel + + +ctypes.windll.kernel32.SetErrorMode(0x0001 | 0x0002 | 0x8000) + +if platform.architecture()[0] == '64bit': + dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'), + r'C:\Program Files\Windows Kits\10\Debuggers\x64', + r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x64'] +else: + dbgdirs = [os.getenv('OPT_DBGMODEL_PATH'), + r'C:\Program Files\Windows Kits\10\Debuggers\x86', + r'C:\Program Files (x86)\Windows Kits\10\Debuggers\x86'] +dbgdir = None +for _dir in dbgdirs: + if _dir is not None and os.path.exists(_dir): + dbgdir = _dir + break + +if not dbgdir: + raise RuntimeError("Windbg install directory not found!") + +print(f"Loading dbgeng and friends from {dbgdir}") + +# preload these to get correct DLLs loaded +try: + ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbghelp.dll')) +except Exception as exc: + print(f"LoadLibrary failed: {dbgdir}\dbghelp.dll {exc}") + pass +try: + ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'dbgeng.dll')) +except Exception as exc: + print(f"LoadLibrary failed: {dbgdir}\dbgeng.dll {exc}") + pass +try: + ctypes.windll.LoadLibrary(os.path.join(dbgdir, 'DbgModel.dll')) +except Exception as exc: + print(f"LoadLibrary failed: {dbgdir}\dbgmodel.dll {exc}") + pass + +try: + from comtypes.gen import DbgMod +except: + tlb = os.path.join(dbgmodel.module_locator(), 'tlb', 'dbgmodel.tlb') + print(f"Loading TLB: {tlb}") + comtypes.client.GetModule(tlb) + from comtypes.gen import DbgMod diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py index 5765e2b931..af20e44811 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/methods.py @@ -19,11 +19,10 @@ from io import StringIO import re import sys -from pybag import pydbg -from pybag.dbgeng import core as DbgEng, exception - from ghidratrace import sch from ghidratrace.client import MethodRegistry, ParamDesc, Address, AddressRange +from pybag import pydbg +from pybag.dbgeng import core as DbgEng, exception from . import util, commands diff --git a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py index 599a68163e..7459ae7896 100644 --- a/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py +++ b/Ghidra/Debug/Debugger-agent-dbgeng/src/main/py/src/ghidradbg/util.py @@ -28,22 +28,16 @@ import traceback from comtypes import CoClass, GUID import comtypes +from comtypes.gen import DbgMod from comtypes.hresult import S_OK - from pybag import pydbg, userdbg, kerneldbg, crashdbg from pybag.dbgeng import core as DbgEng from pybag.dbgeng import exception from pybag.dbgeng import util as DbgUtil from pybag.dbgeng.callbacks import DbgEngCallbacks -from dbgmodel.ihostdatamodelaccess import HostDataModelAccess -import comtypes.client -try: - from comtypes.gen import DbgMod -except: - tlb = "..\..\..\..\build\os\win_x86_64\dbgmodel.tlb" - comtypes.client.GetModule(tlb) - from comtypes.gen import DbgMod +from ghidradbg.dbgmodel.ihostdatamodelaccess import HostDataModelAccess + DbgVersion = namedtuple('DbgVersion', ['full', 'name', 'dotted', 'arch']) diff --git a/gradle/debugger/hasPythonPackage.gradle b/gradle/debugger/hasPythonPackage.gradle index 39940a6aa1..14a0affa49 100644 --- a/gradle/debugger/hasPythonPackage.gradle +++ b/gradle/debugger/hasPythonPackage.gradle @@ -14,6 +14,39 @@ * limitations under the License. */ +def checkPythonVersion(String pyCmd) { + try { + def stdout = new ByteArrayOutputStream() + exec { + commandLine pyCmd, "-c", "import sys; print('{0}.{1}'.format(*sys.version_info))" + standardOutput = stdout + } + def version = "$stdout".strip() + println "$pyCmd is version $version" + return version + } + catch (Exception e) { + println "Could not run $pyCmd: $e" + return "ABSENT" + } +} + +ext.SUPPORTED_PY_VERSIONS = ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12'] + +def findPython3() { + for (pyCmd in ['python3', 'python']) { + if (checkPythonVersion(pyCmd) in SUPPORTED_PY_VERSIONS) { + println "Using $pyCmd" + return pyCmd + } + } + println "Could not find compatible Python 3" + // Don't fail until task execution. Just let "python3" fail. + return 'python3' +} + +ext.PYTHON3 = findPython3() + task assemblePyPackage(type: Copy) { from "src/main/py" into "build/pypkg/" @@ -27,7 +60,7 @@ task buildPyPackage(type: Exec) { outputs.dir(dist) workingDir { "build/pypkg" } - commandLine "python3", "-m", "build" + commandLine PYTHON3, "-m", "build" } // At the moment, any module with a python package also distributes it.