├── README.md ├── xdynstructsengine.pri ├── LICENSE ├── xdynstructsengine.h └── xdynstructsengine.cpp /README.md: -------------------------------------------------------------------------------- 1 | # XDynStructsEngine 2 | 3 | Engine for structs 4 | -------------------------------------------------------------------------------- /xdynstructsengine.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | 4 | HEADERS += \ 5 | $$PWD/xdynstructsengine.h 6 | 7 | SOURCES += \ 8 | $$PWD/xdynstructsengine.cpp 9 | 10 | contains(XCONFIG, use_xwiniodriver) { 11 | DEFINES += USE_XWINIODRIVER 12 | } 13 | 14 | !contains(XCONFIG, xformats) { 15 | XCONFIG += xformats 16 | include($$PWD/../Formats/xformats.pri) 17 | } 18 | 19 | !contains(XCONFIG, xprocess) { 20 | XCONFIG += xprocess 21 | include($$PWD/../XProcess/xprocess.pri) 22 | } 23 | 24 | !contains(XCONFIG, dialogtextinfo) { 25 | XCONFIG += dialogtextinfo 26 | include($$PWD/../FormatDialogs/dialogtextinfo.pri) 27 | } 28 | 29 | win32 { 30 | contains(XCONFIG, use_xwiniodriver) { 31 | DEFINES += USE_XWINIODRIVER 32 | !contains(XCONFIG, xwiniodriver) { 33 | XCONFIG += xwiniodriver 34 | include($$PWD/../XWinIODriver/xwiniodriver.pri) 35 | } 36 | } 37 | } 38 | 39 | # TODO cmake 40 | DISTFILES += \ 41 | $$PWD/LICENSE \ 42 | $$PWD/README.md 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2025 hors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /xdynstructsengine.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2021-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #ifndef XDYNSTRUCTSENGINE_H 22 | #define XDYNSTRUCTSENGINE_H 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "xbinary.h" 29 | #include "xhtml.h" 30 | #include "xoptions.h" 31 | #include "xprocess.h" 32 | #ifdef USE_XWINIODRIVER 33 | #include "xwiniodriver.h" 34 | #endif 35 | 36 | class XDynStructsEngine : public QObject { 37 | Q_OBJECT 38 | 39 | // TODO user/Kernel 40 | // TODO def XPROCESS !!! 41 | // TODO create for HEX 42 | public: 43 | enum IOMODE { 44 | IOMODE_UNKNOWN = 0, 45 | IOMODE_DEVICE, 46 | IOMODE_PROCESS_USER, 47 | #ifdef USE_XWINIODRIVER 48 | IOMODE_PROCESS_KERNEL 49 | #endif 50 | }; 51 | 52 | enum RECORDTYPE { 53 | RECORDTYPE_AUTO = 0, 54 | RECORDTYPE_NONE, 55 | RECORDTYPE_VARIABLE, 56 | RECORDTYPE_POINTER, 57 | RECORDTYPE_ARRAY 58 | }; 59 | 60 | struct DSPOSITION { 61 | qint64 nOffset; 62 | qint64 nSize; 63 | qint32 nBitOffset; 64 | qint32 nBitSize; 65 | QString sName; 66 | QString sType; 67 | RECORDTYPE recordType; 68 | qint32 nArrayCount; 69 | }; 70 | 71 | struct DYNSTRUCT { 72 | QString sIUID; 73 | QString sName; 74 | QString sInfoFilePrefix; 75 | QString sInfoFile; 76 | qint64 nSize; 77 | RECORDTYPE recordType; 78 | QList listPositions; 79 | }; 80 | 81 | struct INFORECORD { 82 | quint64 nAddress; // Do not show if -1 83 | quint64 nOffset; // Do not show if -1; Offset from begin 84 | QString sType; 85 | QString sName; 86 | QString sValue; 87 | QString sValueData; // If not empty -> active link 88 | QString sComment; 89 | }; 90 | 91 | struct INFO { 92 | bool bIsValid; 93 | QList listRecords; 94 | }; 95 | 96 | enum STRUCTTYPE { 97 | STRUCTTYPE_VARIABLE = 0, 98 | STRUCTTYPE_POINTER 99 | }; 100 | 101 | explicit XDynStructsEngine(QObject *pParent = nullptr); 102 | virtual ~XDynStructsEngine(); 103 | 104 | void adjust(); 105 | void setProcessId(qint64 nProcessId, IOMODE ioMode); 106 | void setDevice(QIODevice *pDevice); 107 | void setOptions(XOptions *pXOptions); 108 | IOMODE getIOMode(); 109 | qint64 getProcessId(); 110 | QIODevice *getDevice(); 111 | INFO getInfo(quint64 nAddress, QString sStructName, STRUCTTYPE structType, qint32 nCount); 112 | QList loadFile(QString sFileName); 113 | QList *getStructs(); 114 | QString getValue(quint64 nAddress, quint64 nSize, RECORDTYPE recordType, qint32 nBitOffset, qint32 nBitSize); 115 | QString getValueData(quint64 nAddress, RECORDTYPE recordType, QString sType, QString sValue, qint32 nArrayCount); 116 | QString getComment(quint64 nAddress, QString sStructName, QString sType, QString sName); 117 | DYNSTRUCT getDynStructByName(QString sName); 118 | static RECORDTYPE getRecordType(QString sType); 119 | QString createListEntryLinks(quint64 nAddress, QString sStructName, qint64 nDeltaOffset); 120 | XIODevice *createIODevice(quint64 nAddress, quint64 nSize); 121 | 122 | private: 123 | #ifdef Q_OS_WIN 124 | INFORECORD getPEB(qint64 nProcessId); 125 | QList getTEBs(qint64 nProcessId); 126 | INFORECORD getEPROCESS(qint64 nProcessId); 127 | QList getKPCRs(qint64 nProcessId); 128 | #endif 129 | 130 | signals: 131 | void errorMessage(QString sErrorMessage); 132 | 133 | private: 134 | QList m_listDynStructs; 135 | // OPTIONS m_options; 136 | XOptions *m_pXOptions; 137 | QIODevice *m_pDevice; 138 | X_ID m_nProcessId; 139 | X_HANDLE m_hProcess; 140 | void *m_hDriver; 141 | QString m_sStructsPath; 142 | XBinary *m_pBinary; 143 | IOMODE m_ioMode; 144 | }; 145 | 146 | #endif // XDYNSTRUCTSENGINE_H 147 | -------------------------------------------------------------------------------- /xdynstructsengine.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2021-2025 hors 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | * SOFTWARE. 20 | */ 21 | #include "xdynstructsengine.h" 22 | 23 | XDynStructsEngine::XDynStructsEngine(QObject *pParent) : QObject(pParent) 24 | { 25 | m_nProcessId = 0; 26 | m_hProcess = 0; 27 | m_hDriver = 0; 28 | m_pDevice = nullptr; 29 | m_pXOptions = nullptr; 30 | m_pBinary = nullptr; 31 | m_ioMode = IOMODE_UNKNOWN; 32 | } 33 | 34 | XDynStructsEngine::~XDynStructsEngine() 35 | { 36 | if (m_nProcessId && m_hProcess) { 37 | if (m_ioMode == IOMODE_PROCESS_USER) { 38 | XProcess::closeProcess(m_hProcess); 39 | } 40 | #ifdef Q_OS_WIN 41 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 42 | if (m_hProcess) { 43 | XWinIODriver::closeProcess(m_hDriver, m_hProcess); 44 | } 45 | 46 | if (m_hDriver) { 47 | XWinIODriver::closeDriverDevice(m_hDriver); 48 | } 49 | } 50 | #endif 51 | } 52 | 53 | if (m_pDevice && m_pBinary) { 54 | if (m_ioMode == IOMODE_DEVICE) { 55 | delete m_pBinary; 56 | } 57 | } 58 | } 59 | 60 | void XDynStructsEngine::adjust() 61 | { 62 | // QString sStructsPath = XBinary::convertPathName(m_pXOptions->getStructsPath()); 63 | 64 | // if (sStructsPath != m_sStructsPath) { 65 | // XBinary::OSINFO osInfo = XProcess::getOsInfo(); 66 | 67 | // #ifdef QT_DEBUG 68 | // qDebug("OS Build: %s", osInfo.sBuild.toLatin1().data()); 69 | // #endif 70 | 71 | // // Load structs 72 | // m_listDynStructs.clear(); 73 | 74 | // // if(options.bSystem) 75 | // { 76 | // QString sFileName = sStructsPath + QDir::separator() + osInfo.sArch + QDir::separator() + QString("%1.json").arg(osInfo.sBuild); 77 | 78 | // if (!XBinary::isFileExists(sFileName)) { 79 | // if (osInfo.sBuild.contains("10.0.")) { 80 | // // TODO 10.0.19041 81 | // sFileName = sStructsPath + QDir::separator() + osInfo.sArch + QDir::separator() + QString("%1.json").arg("10.0.17134"); 82 | // } 83 | // } 84 | 85 | // m_listDynStructs.append(loadFile(sFileName)); 86 | // } 87 | 88 | // // if(options.bGeneral) 89 | // { 90 | // m_listDynStructs.append(loadFile(sStructsPath + QDir::separator() + osInfo.sArch + QDir::separator() + QString("general.json"))); 91 | // } 92 | 93 | // // if(options.bCustom) 94 | // { 95 | // m_listDynStructs.append(loadFile(sStructsPath + QDir::separator() + osInfo.sArch + QDir::separator() + QString("custom.json"))); 96 | // } 97 | // } 98 | 99 | // m_sStructsPath = sStructsPath; 100 | } 101 | 102 | void XDynStructsEngine::setProcessId(qint64 nProcessId, IOMODE ioMode) 103 | { 104 | m_nProcessId = nProcessId; 105 | 106 | if (m_nProcessId) { 107 | if (ioMode == IOMODE_PROCESS_USER) { 108 | m_hProcess = XProcess::openProcess(nProcessId); 109 | m_ioMode = IOMODE_PROCESS_USER; 110 | } 111 | #ifdef Q_OS_WIN 112 | else if (ioMode == IOMODE_PROCESS_KERNEL) { 113 | QString sServiceName; 114 | 115 | if (m_pXOptions) { 116 | sServiceName = m_pXOptions->getValue(XOptions::ID_IODRIVER_SERVICENAME).toString(); 117 | } 118 | 119 | if (sServiceName != "") { 120 | m_hDriver = XWinIODriver::openDriverDevice(sServiceName); 121 | m_hProcess = XWinIODriver::openProcess(m_hDriver, nProcessId); 122 | m_ioMode = IOMODE_PROCESS_KERNEL; 123 | } 124 | } 125 | #endif 126 | } 127 | 128 | adjust(); 129 | } 130 | 131 | void XDynStructsEngine::setDevice(QIODevice *pDevice) 132 | { 133 | m_pDevice = pDevice; 134 | 135 | if (m_pDevice) { 136 | m_pBinary = new XBinary(pDevice); 137 | m_ioMode = IOMODE_DEVICE; 138 | } 139 | 140 | adjust(); 141 | } 142 | 143 | void XDynStructsEngine::setOptions(XOptions *pXOptions) 144 | { 145 | m_pXOptions = pXOptions; 146 | } 147 | 148 | XDynStructsEngine::IOMODE XDynStructsEngine::getIOMode() 149 | { 150 | return m_ioMode; 151 | } 152 | 153 | qint64 XDynStructsEngine::getProcessId() 154 | { 155 | return m_nProcessId; 156 | } 157 | 158 | QIODevice *XDynStructsEngine::getDevice() 159 | { 160 | return m_pDevice; 161 | } 162 | 163 | XDynStructsEngine::INFO XDynStructsEngine::getInfo(quint64 nAddress, QString sStructName, STRUCTTYPE structType, qint32 nCount) 164 | { 165 | INFO result = {}; 166 | 167 | if (sStructName != "") { 168 | if (structType == STRUCTTYPE_VARIABLE) { 169 | DYNSTRUCT dynStruct = getDynStructByName(sStructName); 170 | 171 | if (dynStruct.sIUID != "") { 172 | result.bIsValid = true; 173 | 174 | if (nCount <= 1) { 175 | qint32 nNumberOfPositions = dynStruct.listPositions.count(); 176 | 177 | for (qint32 i = 0; i < nNumberOfPositions; i++) { 178 | DSPOSITION position = dynStruct.listPositions.at(i); 179 | 180 | INFORECORD infoRecord = {}; 181 | 182 | infoRecord.nOffset = position.nOffset; 183 | infoRecord.nAddress = nAddress + infoRecord.nOffset; 184 | infoRecord.sType = position.sType; 185 | infoRecord.sName = position.sName; 186 | 187 | infoRecord.sValue = getValue(infoRecord.nAddress, position.nSize, position.recordType, position.nBitOffset, position.nBitSize); 188 | infoRecord.sValueData = getValueData(infoRecord.nAddress, position.recordType, position.sType, infoRecord.sValue, position.nArrayCount); 189 | infoRecord.sComment = getComment(infoRecord.nAddress, sStructName, infoRecord.sType, infoRecord.sName); 190 | 191 | result.listRecords.append(infoRecord); 192 | } 193 | } else { 194 | for (qint32 i = 0; i < nCount; i++) { 195 | INFORECORD infoRecord = {}; 196 | 197 | infoRecord.nOffset = i * dynStruct.nSize; 198 | infoRecord.nAddress = nAddress + infoRecord.nOffset; 199 | infoRecord.sType = dynStruct.sName; 200 | infoRecord.sName = QString("%1[%2]").arg(tr("Value"), QString::number(i)); 201 | 202 | infoRecord.sValue = getValue(infoRecord.nAddress, dynStruct.nSize, dynStruct.recordType, 0, 0); 203 | infoRecord.sValueData = getValueData(infoRecord.nAddress, dynStruct.recordType, infoRecord.sType, infoRecord.sValue, 1); 204 | infoRecord.sComment = getComment(infoRecord.nAddress, sStructName, infoRecord.sType, infoRecord.sName); 205 | 206 | result.listRecords.append(infoRecord); 207 | } 208 | } 209 | } 210 | } else if (structType == STRUCTTYPE_POINTER) { 211 | result.bIsValid = true; 212 | 213 | qint32 nPointerSize = sizeof(void *); 214 | 215 | for (qint32 i = 0; i < nCount; i++) { 216 | INFORECORD infoRecord = {}; 217 | 218 | infoRecord.nOffset = i * nPointerSize; 219 | infoRecord.nAddress = nAddress + infoRecord.nOffset; 220 | infoRecord.sType = sStructName + " *"; 221 | infoRecord.sName = QString("Value[%1]").arg(i); // mb TODO translate 222 | 223 | infoRecord.sValue = getValue(infoRecord.nAddress, nPointerSize, RECORDTYPE_POINTER, 0, 0); 224 | infoRecord.sValueData = getValueData(infoRecord.nAddress, RECORDTYPE_POINTER, infoRecord.sType, infoRecord.sValue, 1); 225 | 226 | result.listRecords.append(infoRecord); 227 | } 228 | } 229 | } else { 230 | if (m_nProcessId) { 231 | #ifdef Q_OS_WIN 232 | if (m_ioMode == IOMODE_PROCESS_USER) { 233 | result.bIsValid = true; 234 | result.listRecords.append(getPEB(m_nProcessId)); 235 | result.listRecords.append(getTEBs(m_nProcessId)); 236 | } else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 237 | result.bIsValid = true; 238 | result.listRecords.append(getEPROCESS(m_nProcessId)); 239 | // result.listRecords.append(getKPCRs(m_nProcessId)); 240 | } 241 | #endif 242 | } 243 | } 244 | 245 | return result; 246 | } 247 | 248 | QList XDynStructsEngine::loadFile(QString sFileName) 249 | { 250 | QList listResult; 251 | 252 | QFile file; 253 | file.setFileName(sFileName); 254 | 255 | if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { 256 | QString sJsonData = file.readAll(); 257 | 258 | QJsonDocument jsonDocument = QJsonDocument::fromJson(sJsonData.toUtf8()); 259 | 260 | if (jsonDocument.isObject()) { 261 | QFileInfo fileInfo(sFileName); 262 | 263 | QJsonObject jsonObject = jsonDocument.object(); 264 | 265 | QString sGlobalName = jsonObject.value("name").toString(); 266 | QString sFilePrefix = fileInfo.absolutePath() + QDir::separator() + sGlobalName; 267 | 268 | QJsonArray jsonStructsArray = jsonObject.value("structs").toArray(); 269 | 270 | qint32 nNumberOfStructs = jsonStructsArray.count(); 271 | 272 | for (qint32 i = 0; i < nNumberOfStructs; i++) { 273 | DYNSTRUCT record = {}; 274 | 275 | QJsonObject jsonStruct = jsonStructsArray.at(i).toObject(); 276 | 277 | record.sIUID = XBinary::generateUUID(); // TODO Check 278 | record.sName = jsonStruct.value("name").toString(); 279 | record.nSize = jsonStruct.value("size").toInt(); 280 | record.recordType = getRecordType(record.sName); 281 | 282 | QString sInfoFile = jsonStruct.value("infofile").toString(); 283 | 284 | if (sInfoFile != "") { 285 | record.sInfoFilePrefix = sFilePrefix; 286 | record.sInfoFile = sInfoFile; 287 | } 288 | 289 | QJsonArray jsonPositionsArray = jsonStruct.value("positions").toArray(); 290 | 291 | qint32 nNumberOfPositions = jsonPositionsArray.count(); 292 | 293 | for (qint32 j = 0; j < nNumberOfPositions; j++) { 294 | QJsonObject jsonPosition = jsonPositionsArray.at(j).toObject(); 295 | 296 | QString sName = jsonPosition.value("name").toString(); 297 | QString sType = jsonPosition.value("type").toString(); 298 | qint64 nOffset = jsonPosition.value("offset").toInt(); 299 | qint64 nSize = jsonPosition.value("size").toInt(); 300 | qint32 nBitOffset = jsonPosition.value("bitoffset").toInt(); 301 | qint32 nBitSize = jsonPosition.value("bitsize").toInt(); 302 | RECORDTYPE recordType = RECORDTYPE_AUTO; 303 | qint32 nArrayCount = 0; 304 | 305 | if (sName.contains("[")) { 306 | nArrayCount = sName.section("[", -1, -1).section("]", 0, 0).toInt(); 307 | 308 | nArrayCount = qMax(nArrayCount, 1); 309 | nArrayCount = qMin(nArrayCount, 512); // TODO const 310 | 311 | recordType = RECORDTYPE_ARRAY; 312 | } else if (sType.contains("*")) { 313 | recordType = RECORDTYPE_POINTER; 314 | } else { 315 | recordType = getRecordType(sType); 316 | } 317 | 318 | if (nArrayCount == 0) { 319 | nArrayCount = 1; 320 | } 321 | 322 | DSPOSITION position = {}; 323 | 324 | position.sName = sName; 325 | position.sType = sType; 326 | position.nOffset = nOffset; 327 | position.nSize = nSize; 328 | position.nBitOffset = nBitOffset; 329 | position.nBitSize = nBitSize; 330 | position.recordType = recordType; 331 | position.nArrayCount = nArrayCount; 332 | 333 | record.listPositions.append(position); 334 | } 335 | 336 | listResult.append(record); 337 | } 338 | } 339 | 340 | file.close(); 341 | } else { 342 | #ifdef QT_DEBUG 343 | qDebug("Cannot load file: %s", sFileName.toLatin1().data()); 344 | #endif 345 | emit errorMessage(QString("%1: %2").arg(tr("Cannot load file"), sFileName)); 346 | } 347 | 348 | return listResult; 349 | } 350 | 351 | QList *XDynStructsEngine::getStructs() 352 | { 353 | return &m_listDynStructs; 354 | } 355 | 356 | QString XDynStructsEngine::getValue(quint64 nAddress, quint64 nSize, RECORDTYPE recordType, qint32 nBitOffset, qint32 nBitSize) 357 | { 358 | // TODO Endian 359 | QString sResult; 360 | 361 | if ((recordType == RECORDTYPE_VARIABLE) || (recordType == RECORDTYPE_POINTER)) { 362 | if (nSize == 1) { 363 | quint8 nValue = 0; 364 | 365 | if (m_hProcess) { 366 | if (m_ioMode == IOMODE_PROCESS_USER) { 367 | nValue = XProcess::read_uint8(m_hProcess, nAddress); 368 | } 369 | #ifdef Q_OS_WIN 370 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 371 | nValue = XWinIODriver::read_uint8(m_hDriver, m_hProcess, nAddress); 372 | } 373 | #endif 374 | } else if (m_pBinary) { 375 | if (m_ioMode == IOMODE_DEVICE) { 376 | nValue = m_pBinary->read_uint8(nAddress); 377 | } 378 | } 379 | 380 | nValue = XBinary::getBits_uint8(nValue, nBitOffset, nBitSize); 381 | 382 | sResult = "0x" + XBinary::valueToHex(nValue); 383 | } else if (nSize == 2) { 384 | quint16 nValue = 0; 385 | 386 | if (m_hProcess) { 387 | if (m_ioMode == IOMODE_PROCESS_USER) { 388 | nValue = XProcess::read_uint16(m_hProcess, nAddress); 389 | } 390 | #ifdef Q_OS_WIN 391 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 392 | nValue = XWinIODriver::read_uint16(m_hDriver, m_hProcess, nAddress); 393 | } 394 | #endif 395 | } else if (m_pBinary) { 396 | if (m_ioMode == IOMODE_DEVICE) { 397 | nValue = m_pBinary->read_uint16(nAddress); 398 | } 399 | } 400 | 401 | nValue = XBinary::getBits_uint16(nValue, nBitOffset, nBitSize); 402 | 403 | sResult = "0x" + XBinary::valueToHex(nValue); 404 | } else if (nSize == 4) { 405 | quint32 nValue = 0; 406 | 407 | if (m_hProcess) { 408 | if (m_ioMode == IOMODE_PROCESS_USER) { 409 | nValue = XProcess::read_uint32(m_hProcess, nAddress); 410 | } 411 | #ifdef Q_OS_WIN 412 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 413 | nValue = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress); 414 | } 415 | #endif 416 | } else if (m_pBinary) { 417 | if (m_ioMode == IOMODE_DEVICE) { 418 | nValue = m_pBinary->read_uint32(nAddress); 419 | } 420 | } 421 | 422 | nValue = XBinary::getBits_uint32(nValue, nBitOffset, nBitSize); 423 | 424 | sResult = "0x" + XBinary::valueToHex(nValue); 425 | } else if (nSize == 8) { 426 | quint64 nValue = 0; 427 | 428 | if (m_hProcess) { 429 | if (m_ioMode == IOMODE_PROCESS_USER) { 430 | nValue = XProcess::read_uint64(m_hProcess, nAddress); 431 | } 432 | #ifdef Q_OS_WIN 433 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 434 | nValue = XWinIODriver::read_uint64(m_hDriver, m_hProcess, nAddress); 435 | } 436 | #endif 437 | } else if (m_pBinary) { 438 | if (m_ioMode == IOMODE_DEVICE) { 439 | nValue = m_pBinary->read_uint64(nAddress); 440 | } 441 | } 442 | 443 | nValue = XBinary::getBits_uint64(nValue, nBitOffset, nBitSize); 444 | 445 | sResult = "0x" + XBinary::valueToHex(nValue); 446 | } 447 | } else { 448 | sResult = "..."; 449 | } 450 | 451 | return sResult; 452 | } 453 | 454 | QString XDynStructsEngine::getValueData(quint64 nAddress, RECORDTYPE recordType, QString sType, QString sValue, qint32 nArrayCount) 455 | { 456 | QString sResult; 457 | 458 | if (recordType == RECORDTYPE_POINTER) { 459 | sType = sType.section("*", 0, -2).trimmed(); 460 | sResult = QString("%1&%2").arg(sValue, sType); 461 | } else if (recordType == RECORDTYPE_AUTO) { 462 | sResult = QString("0x%1&%2").arg(XBinary::valueToHex(nAddress), sType); 463 | } else if (recordType == RECORDTYPE_ARRAY) { 464 | STRUCTTYPE structType = STRUCTTYPE_VARIABLE; 465 | 466 | if (sType.contains("*")) { 467 | structType = STRUCTTYPE_POINTER; 468 | } 469 | 470 | sResult = QString("0x%1&%2&%3&%4").arg(XBinary::valueToHex(nAddress), sType, QString::number(structType), QString::number(nArrayCount)); 471 | } 472 | 473 | return sResult; 474 | } 475 | 476 | QString XDynStructsEngine::getComment(quint64 nAddress, QString sStructName, QString sType, QString sName) 477 | { 478 | QString sResult; 479 | 480 | if (sType == "struct _UNICODE_STRING") { 481 | quint16 nStringSize = 0; 482 | quint64 nStringAddress = 0; 483 | QString sString; 484 | 485 | if (m_hProcess) { 486 | nStringSize = XProcess::read_uint16(m_hProcess, nAddress); 487 | 488 | if (sizeof(void *) == 8) { 489 | if (m_ioMode == IOMODE_PROCESS_USER) { 490 | nStringAddress = XProcess::read_uint64(m_hProcess, nAddress + 8); 491 | } 492 | #ifdef Q_OS_WIN 493 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 494 | nStringAddress = XWinIODriver::read_uint64(m_hDriver, m_hProcess, nAddress + 8); 495 | } 496 | #endif 497 | } else { 498 | if (m_ioMode == IOMODE_PROCESS_USER) { 499 | nStringAddress = XProcess::read_uint32(m_hProcess, nAddress + 4); 500 | } 501 | #ifdef Q_OS_WIN 502 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 503 | nStringAddress = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress + 4); 504 | } 505 | #endif 506 | } 507 | } else if (m_pBinary) { 508 | nStringSize = m_pBinary->read_uint16(nAddress); 509 | 510 | if (sizeof(void *) == 8) { 511 | if (m_ioMode == IOMODE_DEVICE) { 512 | nStringAddress = m_pBinary->read_uint64(nAddress + 8); 513 | } 514 | } else { 515 | if (m_ioMode == IOMODE_DEVICE) { 516 | nStringAddress = m_pBinary->read_uint32(nAddress + 4); 517 | } 518 | } 519 | } 520 | 521 | if (m_hProcess) { 522 | if (m_ioMode == IOMODE_PROCESS_USER) { 523 | sString = XProcess::read_unicodeString(m_hProcess, nStringAddress, nStringSize); 524 | } 525 | #ifdef Q_OS_WIN 526 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 527 | sString = XWinIODriver::read_unicodeString(m_hDriver, m_hProcess, nStringAddress, nStringSize); 528 | } 529 | #endif 530 | } else if (m_pBinary) { 531 | if (m_ioMode == IOMODE_DEVICE) { 532 | sString = m_pBinary->read_unicodeString(nStringAddress, nStringSize); 533 | } 534 | } 535 | 536 | sResult = QString("\"%1\"").arg(sString); 537 | } 538 | 539 | if (sStructName == "struct _PEB_LDR_DATA") { 540 | if (sName == "InLoadOrderModuleList") { 541 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 0 * (2 * sizeof(void *))); 542 | } else if (sName == "InMemoryOrderModuleList") { 543 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 1 * (2 * sizeof(void *))); 544 | } else if (sName == "InInitializationOrderModuleList") { 545 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 2 * (2 * sizeof(void *))); 546 | } 547 | } else if (sStructName == "struct _LDR_DATA_TABLE_ENTRY") { 548 | if (sName == "InLoadOrderLinks") { 549 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 0 * (2 * sizeof(void *))); 550 | } else if (sName == "InMemoryOrderLinks") { 551 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 1 * (2 * sizeof(void *))); 552 | } else if (sName == "InInitializationOrderLinks") { 553 | sResult = createListEntryLinks(nAddress, "struct _LDR_DATA_TABLE_ENTRY", 2 * (2 * sizeof(void *))); 554 | } 555 | // else if(sName=="InProgressLinks") 556 | // { 557 | // sResult=createListEntryLinks(pProcess,pBinary,nAddress,"struct 558 | // _LDR_DATA_TABLE_ENTRY",0); 559 | // } 560 | } 561 | 562 | return sResult; 563 | } 564 | 565 | XDynStructsEngine::DYNSTRUCT XDynStructsEngine::getDynStructByName(QString sName) 566 | { 567 | DYNSTRUCT result = {}; 568 | 569 | if (sName != "") { 570 | qint32 nNumberOfStructs = m_listDynStructs.count(); 571 | 572 | for (qint32 i = 0; i < nNumberOfStructs; i++) { 573 | if (m_listDynStructs.at(i).sName == sName) { 574 | result = m_listDynStructs.at(i); 575 | 576 | break; 577 | } 578 | } 579 | } 580 | 581 | return result; 582 | } 583 | 584 | XDynStructsEngine::RECORDTYPE XDynStructsEngine::getRecordType(QString sType) 585 | { 586 | RECORDTYPE result = RECORDTYPE_AUTO; 587 | 588 | // TODO more 589 | if ((sType == "unsigned char") || (sType == "unsigned short") || (sType == "unsigned int") || (sType == "unsigned long") || (sType == "unsigned long long") || 590 | (sType == "signed char") || (sType == "signed short") || (sType == "signed int") || (sType == "signed long") || (sType == "signed long long") || 591 | (sType == "char") || (sType == "short") || (sType == "int") || (sType == "long") || (sType == "long long")) { 592 | result = RECORDTYPE_VARIABLE; 593 | } 594 | 595 | return result; 596 | } 597 | 598 | QString XDynStructsEngine::createListEntryLinks(quint64 nAddress, QString sStructName, qint64 nDeltaOffset) 599 | { 600 | QString sResult; 601 | 602 | quint64 nFlink = 0; 603 | quint64 nBlink = 0; 604 | 605 | if (sizeof(void *) == 8) { 606 | if (m_hProcess) { 607 | if (m_ioMode == IOMODE_PROCESS_USER) { 608 | nFlink = XProcess::read_uint64(m_hProcess, nAddress); 609 | nBlink = XProcess::read_uint64(m_hProcess, nAddress + 8); 610 | } 611 | #ifdef Q_OS_WIN 612 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 613 | nFlink = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress); 614 | nBlink = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress + 8); 615 | } 616 | #endif 617 | } else if (m_pBinary) { 618 | if (m_ioMode == IOMODE_DEVICE) { 619 | nFlink = m_pBinary->read_uint64(nAddress); 620 | nBlink = m_pBinary->read_uint64(nAddress + 8); 621 | } 622 | } 623 | } else { 624 | if (m_hProcess) { 625 | if (m_ioMode == IOMODE_PROCESS_USER) { 626 | nFlink = XProcess::read_uint32(m_hProcess, nAddress); 627 | nBlink = XProcess::read_uint32(m_hProcess, nAddress + 4); 628 | } 629 | #ifdef Q_OS_WIN 630 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 631 | nFlink = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress); 632 | nBlink = XWinIODriver::read_uint32(m_hDriver, m_hProcess, nAddress + 4); 633 | } 634 | #endif 635 | } else if (m_pBinary) { 636 | if (m_ioMode == IOMODE_DEVICE) { 637 | nFlink = m_pBinary->read_uint32(nAddress); 638 | nBlink = m_pBinary->read_uint32(nAddress + 4); 639 | } 640 | } 641 | } 642 | 643 | QString sFlink = QString("0x%1&%2").arg(XBinary::valueToHex(nFlink - nDeltaOffset), sStructName); 644 | QString sBlink = QString("0x%1&%2").arg(XBinary::valueToHex(nBlink - nDeltaOffset), sStructName); 645 | 646 | sResult = QString("Flink Blink").arg(sFlink, sBlink); 647 | 648 | return sResult; 649 | } 650 | 651 | XIODevice *XDynStructsEngine::createIODevice(quint64 nAddress, quint64 nSize) 652 | { 653 | XIODevice *pResult = nullptr; 654 | 655 | if (m_nProcessId) { 656 | if (m_ioMode == IOMODE_PROCESS_USER) { 657 | pResult = new XProcess(m_nProcessId, nAddress, nSize); 658 | } 659 | #ifdef Q_OS_WIN 660 | else if (m_ioMode == IOMODE_PROCESS_KERNEL) { 661 | QString sServiceName = m_pXOptions->getValue(XOptions::ID_IODRIVER_SERVICENAME).toString(); 662 | 663 | pResult = new XWinIODriver(sServiceName, m_nProcessId, nAddress, nSize); 664 | } 665 | #endif 666 | } else if (m_pDevice) { 667 | if (m_ioMode == IOMODE_DEVICE) { 668 | pResult = new SubDevice(m_pDevice, nAddress, nSize); 669 | } 670 | } 671 | 672 | return pResult; 673 | } 674 | 675 | #ifdef Q_OS_WIN 676 | XDynStructsEngine::INFORECORD XDynStructsEngine::getPEB(qint64 nProcessId) 677 | { 678 | INFORECORD result = {}; 679 | 680 | QString sValue = "0x" + XBinary::valueToHexOS(XProcess::getPEBAddress(nProcessId)); 681 | 682 | result.nAddress = -1; 683 | result.nOffset = -1; 684 | result.sType = "struct _PEB *"; 685 | result.sName = "pPeb"; 686 | result.sValue = sValue; 687 | result.sValueData = QString("%1&%2").arg(sValue, "struct _PEB"); 688 | 689 | return result; 690 | } 691 | #endif 692 | #ifdef Q_OS_WIN 693 | QList XDynStructsEngine::getTEBs(qint64 nProcessId) 694 | { 695 | QList listResult; 696 | 697 | QList listTEBAddresses = XProcess::getTEBAddresses(nProcessId); 698 | 699 | qint32 nNumberOfThreads = listTEBAddresses.count(); 700 | 701 | for (qint32 i = 0; i < nNumberOfThreads; i++) { 702 | INFORECORD record = {}; 703 | 704 | QString sValue = "0x" + XBinary::valueToHexOS(listTEBAddresses.at(i)); 705 | 706 | record.nAddress = -1; 707 | record.nOffset = -1; 708 | record.sType = "struct _TEB *"; 709 | record.sName = "pTeb"; 710 | record.sValue = sValue; 711 | record.sValueData = QString("%1&%2").arg(sValue, "struct _TEB"); 712 | 713 | listResult.append(record); 714 | } 715 | 716 | return listResult; 717 | } 718 | #endif 719 | #ifdef Q_OS_WIN 720 | XDynStructsEngine::INFORECORD XDynStructsEngine::getEPROCESS(qint64 nProcessId) 721 | { 722 | INFORECORD result = {}; 723 | 724 | QString sValue = "0x" + XBinary::valueToHexOS(XWinIODriver::getEPROCESSAddress(m_hDriver, nProcessId)); 725 | 726 | result.nAddress = -1; 727 | result.nOffset = -1; 728 | result.sType = "struct _EPROCESS *"; 729 | result.sName = "pEprocess"; 730 | result.sValue = sValue; 731 | result.sValueData = QString("%1&%2").arg(sValue, "struct _EPROCESS"); 732 | 733 | return result; 734 | } 735 | #endif 736 | #ifdef Q_OS_WIN 737 | QList XDynStructsEngine::getKPCRs(qint64 nProcessId) 738 | { 739 | QList listResult; 740 | 741 | QList listKPCRAddresses = XWinIODriver::getKPCRAddresses(m_hDriver, nProcessId); 742 | 743 | qint32 nNumberOfRecords = listKPCRAddresses.count(); 744 | 745 | for (qint32 i = 0; i < nNumberOfRecords; i++) { 746 | INFORECORD record = {}; 747 | 748 | QString sValue = "0x" + XBinary::valueToHexOS(listKPCRAddresses.at(i)); 749 | 750 | record.nAddress = -1; 751 | record.nOffset = -1; 752 | record.sType = "struct _KPCR *"; 753 | record.sName = "pTeb"; 754 | record.sValue = sValue; 755 | record.sValueData = QString("%1&%2").arg(sValue, "struct _KPCR"); 756 | 757 | listResult.append(record); 758 | } 759 | 760 | return listResult; 761 | } 762 | #endif 763 | --------------------------------------------------------------------------------