[ ] maphack |
, DayZ Mod (Arma 2 OA). , , Battleye , , , .
.
, Ubuntu CyberPack (IRF) fmem, , fmem .
, LiME ~ Linux Memory Extractor. livecd.
TinyCore(TinyCorePure64, 3 ). .
tce-load -iw linux-kernel-sources-env.tcz
cliorx linux-kernel-sources-env.sh
, , make
insmod ./lime.ko "path=/path/mem-image.lime format=lime"
- , . Volatility Framework memdump.
vol.py -f F:\mem-image.lime format=lime pslist
vol.py -f F:\mem-image.lime format=lime memdump dump-dir ./output p 868
Rekall Framework, , volatility
rekal -f F:\mem-image.lime pslist
rekal -f F:\mem-image.lime memdump dump_dir="./output", pids=868
, .
Rekall windows 10, - :
WARNING:rekall.1:Profile nt/GUID/F6F4895554894B24B4DF942361F0730D1 fetched and built. Please consider reporting this profile to the Rekall team so we may add it to the public profile repository.
, :
CRITICAL:rekall.1:A DTB value was found but failed to verify. See logging messages for more information.
, --profile , .
hiberfil.sys, .
, , livecd ( , - TinyCore), (Read-Only) , .
TinyCore ntfs.
tce-load -iw ntfs-3g
fdisk -l,
sudo ntfs-3g -o ro /dev/sda2 /tmp/a1 // Read-Only
sudo ntfs-3g /dev/sdc1 /tmp/a2
cp /tmp/a1/hiberfil.sys /tmp/a2
volatility ( win7 ).
vol.py imagecopy -f hiberfil.sys -O win7.img
win10, .
Hibr2bin, Sandman Framework.
HIBR2BIN /PLATFORM X64 /MAJOR 10 /MINOR 0 /INPUT hiberfil.sys /OUTPUT uncompressed.bin
output, .
Hibernation Recon Free , .
memdump .
File Address Length Virtual Addr
-------------- -------------- --------------
0x000000000000 0x000000001000 0x000000010000
0x000000001000 0x000000001000 0x000000020000
0x000000002000 0x000000001000 0x000000021000
0x000000003000 0x000000001000 0x00000002f000
0x000000004000 0x000000001000 0x000000040000
0x000000005000 0x000000001000 0x000000050000
0x000000006000 0x000000001000 0x000000051000
GUI Qt.
.
class MemoryAPI
{
public:
MemoryAPI(){}
MemoryAPI(QString pathDump, QString pathIDX);
//
quint32 readPtr (const quint32 offset);
qint32 readInt (const quint32 offset);
float readFloat (const quint32 offset);
QString readStringAscii(const quint32 offset, const quint32 size);
QString readArmaString(quint32 offset);
//
void loadIDX (QString path);
void loadDump (QString path);
private:
//
QVector memoryRelations;
quint32 convertVirtToPhys(const quint32 virt) const;
QByteArray readVirtMem(const quint32 baseAddr, const quint32 size);
QFile dumpFile;
};
idx- .
class MemoryRange
{
private:
quint32 baseVirtualAddress;
quint32 basePhysicalAddress;
quint32 size;
};
.
QByteArray MemoryAPI::readVirtMem(const quint32 baseAddr, const quint32 size)
{
QByteArray result;
//
quint32 addr = convertVirtToPhys(baseAddr);
dumpFile.seek(addr);
result = dumpFile.read(size);
return result;
}
( , ).
quint32 MemoryAPI::convertVirtToPhys(const quint32 virt) const
{
for(auto it = memoryRelations.begin(); it != memoryRelations.end(); ++it)
{
if((*it).inRange(virt))
{
const quint32& phBase = (*it).getPhysicalAddress(), vrBase = (*it).getVirtualAddress();
//
if(phBase>vrBase)
return virt + (phBase - vrBase);
else
return virt - (vrBase - phBase);
}
}
//
throw 1;
}
, .
class EntityData
{
public:
friend class WorldState;
//
enum class type {airplane, car, motorcycle, ship, helicopter, parachute, tank,
tent, stash, fence, ammoBox, campFire, crashSite, animals,
players, zombies, stuff, hedgehog, invalid};
type entityType;
EntityData();
EntityData(QString n, QPointF c, type t = type::stuff);
QString shortDescription()const;
QString fullDescription()const;
QPointF getCoords() const {return coords;}
private:
//
QString name;
//
QPointF coords;
// ( )
QMap additionalFields;
};
, ( ).
class WorldState
{
public:
// ,
WorldState(const QString& dumpFile, const QString& idxFile);
// xml-
WorldState(const QString& stateFile);
// xml-,
void saveState(const QString& stateFile);
// , ( )
QMap entityRanges;
QString worldName;
private:
//
QVector entityArray;
//
QVector masterOffsets;
QVector tableOffsets;
quint32 objTableAddress;
void handleEntity (quint32 entityAddress, MemoryAPI& mem);
//
void initRanges();
void initOffsets();
QDomElement makeElement(QDomDocument& domDoc, const QString& name, const QString& strData = QString());
};
.
WorldState::WorldState(const QString& dumpFile, const QString& idxFile)
{
//
initOffsets();
//
QProgressDialog progress;
progress.setCancelButton(nullptr);
progress.setLabelText("Loading dump...");
progress.setModal(true);
progress.setMinimum(0);
progress.setMaximum(masterOffsets.length()+2);
progress.show();
MemoryAPI mem(dumpFile,idxFile);
progress.setValue(1);
for(auto mO = masterOffsets.begin(); mO != masterOffsets.end(); ++mO)
{
quint32 entityTableBasePtr = mem.readPtr(objTableAddress) + (*mO);
for(auto tO = tableOffsets.begin(); tO != tableOffsets.end(); ++tO)
{
qint32 size = mem.readInt(entityTableBasePtr + 0x4 +(*tO));
for(qint32 i = 0; i!=size; ++i)
{
quint32 fPtr = mem.readPtr(entityTableBasePtr + (*tO));
quint32 entityAddress = mem.readPtr(fPtr + 4 * i);
//
handleEntity(entityAddress, mem);
// ,
QCoreApplication::processEvents();
}
}
progress.setValue(progress.value()+1);
}
initRanges();
worldName = "chernarus";
progress.setValue(progress.value()+1);
}
void WorldState::initOffsets()
{
masterOffsets.append(0x880);
masterOffsets.append(0xb24);
masterOffsets.append(0xdc8);
tableOffsets.append(0x8);
tableOffsets.append(0xb0);
tableOffsets.append(0x158);
tableOffsets.append(0x200);
objTableAddress = 0xDAD8C0;
}
. ( , ).
class World
{
public:
char _0x0000[8];
InGameUI* inGameUI; //0x0008
char _0x000C[1520];
EntityTablePointer* entityTablePointer; //0x05FC
VariableTableInfo* variableTableInfo; //0x0600
char _0x0604[428];
__int32 gameMode; //0x07B0
char _0x07B4[4];
float speedMultiplier; //0x07B8
char _0x07BC[196];
EntitiesDistributed table1; //0x0880
char _0x0B00[36];
EntitiesDistributed table2; //0x0B24
char _0x0DA4[36];
EntitiesDistributed table3; //0x0DC8
char _0x1048[849];
BYTE artilleryEnabled; //0x1399
BYTE enableItemsDropping; //0x139A
char _0x139B[13];
UnitInfo* cameraOn; //0x13A8
char _0x13AC[4];
UnitInfo* cplayerOn; //0x13B0
UnitInfo* realPlayer; //0x13B4
char _0x13B8[48];
float actualOvercast; //0x13E8
float wantedOvercast; //0x13EC
__int32 nextWeatherChange; //0x13F0
float currentFogLevel; //0x13F4
float fogTarget; //0x13F8
char _0x13FC[32];
__int32 weatherTime; //0x141C
char _0x1420[8];
BYTE playerManual; //0x1428
BYTE playerSuspended; //0x1429
char _0x142A[30];
__int32 N0D09AD19; //0x1448
char _0x144C[92];
ArmaString* currentCampaign; //0x14A8
char _0x14AC[4];
__int32 N0D09B79F; //0x14B0
char _0x14B4[52];
float viewDistanceHard; //0x14E8
float viewDistanceMin; //0x14EC
float grass; //0x14F0
char _0x14F4[36];
__int32 initTableCount; //0x1518
__int32 initTableMaxCount; //0x151C
char _0x1520[4];
};//Size=0x1524
, ( , ). objTableAddress. masterOffsets 3 , .
class EntitiesDistributed
{
public:
char _0x0000[8];
Entity* table1; //0x0008
__int32 table1Size; //0x000C
char _0x0010[160];
Entity* table2; //0x00B0
__int32 table2Size; //0x00B4
char _0x00B8[160];
Entity* table3; //0x0158
__int32 table3Size; //0x015C
char _0x0160[160];
Entity* table4; //0x0200
__int32 table4Size; //0x0204
char _0x0208[120];
};//Size=0x0280
4 ( tableOffsets).
. , .
void WorldState::handleEntity(quint32 entityAddress, MemoryAPI &mem)
{
QString objType;
QString objName;
float coordX;
float coordY;
try{
quint32 obj1 = entityAddress;
quint32 pCfgVehicle = mem.readPtr(obj1 + 0x3C);
quint32 obj3 = mem.readPtr(pCfgVehicle + 0x30);
quint32 pObjType = mem.readPtr(pCfgVehicle + 0x6C);
objType = mem.readArmaString(pObjType);
objName = mem.readStringAscii(obj3 + 0x8, 25);
quint32 pEntityVisualState = mem.readPtr(obj1 + 0x18);
coordX = mem.readFloat(pEntityVisualState + 0x28);
coordY = mem.readFloat(pEntityVisualState + 0x30);
}catch(int a)
{
qDebug() << " .";
return;
}
//
EntityData ed(objName, QPointF(coordX, coordY));
//
if(objType == "car")
ed.entityType = EntityData::type::car;
else if(objType == "motorcycle")
ed.entityType = EntityData::type::motorcycle;
else if(objType == "airplane")
ed.entityType = EntityData::type::airplane;
else if(objType == "helicopter")
ed.entityType = EntityData::type::helicopter;
else if(objType == "ship")
ed.entityType = EntityData::type::ship;
else if(objType == "tank")
ed.entityType = EntityData::type::tank;
else if(objType == "parachute")
ed.entityType = EntityData::type::parachute;
else if(objName.indexOf("TentStorage")!=-1)
ed.entityType = EntityData::type::tent;
else if(objName.indexOf("Stash")!=-1)
ed.entityType = EntityData::type::stash;
else if(objName.indexOf("WoodenGate")!=-1 || objName.indexOf("WoodenFence")!=-1)
ed.entityType = EntityData::type::fence;
else if(objName.indexOf("DZ_MedBox")!=-1 || objName.indexOf("DZ_AmmoBox")!=-1)
ed.entityType = EntityData::type::ammoBox;
else if(objName.indexOf("Hedgehog_DZ")!=-1)
ed.entityType = EntityData::type::hedgehog;
else if(objName.indexOf("Land_Camp_Fire_DZ")!= -1)
ed.entityType = EntityData::type::campFire;
else if(objName.indexOf("CrashSite")!= -1)
ed.entityType = EntityData::type::crashSite;
else if(objName.indexOf("WildBoar")== 0 || objName.indexOf("Rabbit")== 0 ||
objName.indexOf("Cow")== 0 || objName.indexOf("Sheep")== 0 ||
objName.indexOf("Goat")== 0 || objName.indexOf("Hen")== 0)
ed.entityType = EntityData::type::animals;
else if(objName.indexOf("Survivor2_DZ")!= -1 || objName.indexOf("Sniper1_DZ")!=-1 ||
objName.indexOf("Camo1_DZ")!=-1 || objName.indexOf("Survivor3_DZ")!=-1 ||
objName.indexOf("Bandit1_DZ")!= -1 || objName.indexOf("Soldier1_DZ")!= -1)
ed.entityType = EntityData::type::players;
else
ed.entityType = EntityData::type::stuff;
entityArray.append(ed);
}
class Entity
{
public:
char _0x0000[24];
EntityVisualState* entityVisualState; //0x0018
char _0x001C[32];
CfgVehicle* cfgVehicle; //0x003C
char _0x0040[476];
EntityInventory* entityInventory; //0x021C
};//Size=0x0220
.
CfgVehicle .
ArmaString* entityName; //0x0030
ArmaString* objectType; //0x006C
class EntityVisualState
{
public:
char _0x0000[4];
D3DXVECTOR3 dimension; //0x0004
D3DXVECTOR3 rotation1; //0x0010
D3DXVECTOR3 direction; //0x001C
D3DXVECTOR3 coordinates; //0x0028
char _0x0034[20];
D3DXVECTOR3 velocity; //0x0048
float angularVelocity; //0x0054
float zVelocity2; //0x0058
float Speed; //0x005C
D3DXVECTOR3 acceleration; //0x0060
char _0x006C[16];
D3DXVECTOR3 direction2; //0x007C
D3DXVECTOR3 rotation2; //0x0088
D3DXVECTOR3 direction3; //0x0094
char _0x00A0[12];
float fuelLevel; //0x00AC
char _0x00B0[92];
D3DXVECTOR3 headCoordinates; //0x010C
D3DXVECTOR3 torsoCoordinates; //0x0118
char _0x0124[244];
float N047F1D6C; //0x0218
char _0x021C[200];
};//Size=0x02E4
EntityVisualState , .
D3DXVECTOR3 coordinates;
struct D3DXVECTOR3 {
FLOAT x;
FLOAT y;
FLOAT z;
};
x y( z), :
coordX = mem.readFloat(pEntityVisualState + 0x28);
coordY = mem.readFloat(pEntityVisualState + 0x30);
, additionalFields, EntityData, . , .
, - , QPainter.
.
class InteractiveMap : public QWidget
{
Q_OBJECT
public:
InteractiveMap(QWidget* pwgt = nullptr);
virtual ~InteractiveMap();
protected:
virtual void paintEvent(QPaintEvent* pe);
private:
// ( )
const float minScale = 1.0f;
const float maxScale = 8.0f;
const float scaleStep= 2.0f;
void updateScale(const qreal value, const QPointF& dpos);
void updateTranslate(const QPointF& value);
bool getFilterValue(EntityData::type t);
bool getFilterValue(QString t);
void mousePressEvent (QMouseEvent* pe);
void mouseMoveEvent (QMouseEvent* pe);
void wheelEvent (QWheelEvent *pe);
void findCloseObjects(QPointF coords);
QVector* input;
QPainter* painter;
QPixmap* image;
WorldState* worldState;
qreal scale;
QPointF translate;
QPoint startMove;
//
QPixmap cache;
QMutex renderMutex;
// ,
QFutureWatcher closeObjWatcher;
QFuture closeObjFuture;
public slots:
//
void loadState(QString stateFile);
void loadDump(QString dumpFile, QString idxFile);
void closeState();
void saveState(QString stateFile);
void updateCache();
void sendCloseObjects();
signals:
void showCloseObjects(QString str);
void saveStateChanged(bool state);
};
. QPixmap ( ).
void InteractiveMap::paintEvent(QPaintEvent *pe)
{
renderMutex.lock();
painter->begin(this);
//////////////////////////////////////////////////
QTransform mat;
painter->setTransform(mat);
painter->scale(scale, scale);
painter->translate(translate);
painter->drawPixmap(0,0, *image);
if(cache.isNull())
{
// DPR,
cache = QPixmap(image->size()*4);
cache.setDevicePixelRatio(4);
cache.fill(Qt::transparent);
QPainter cachePaint(&cache);
//
for(QMap::const_iterator it = worldState->entityRanges.cbegin(); it!=worldState->entityRanges.cend();++it)
{
//
if(getFilterValue(it.key()))
{
for(QVector::const_iterator i = it.value().start; i!= it.value().end; ++i)
{
float x = i->getCoords().x();
float y = i->getCoords().y();
//
x = (((x) / (15360.0f / 975.0f)));
y = (((15360.0f - y) / (15360.0f / 970.0f)) - 4.0f);
//
QFont font("Arial");
QPen pen;
pen.setWidthF(4.0f/scale);
pen.setStyle(Qt::SolidLine);
font.setPointSizeF(qMax(float(8.0f*1.0f/scale),2.0f));
cachePaint.setFont(font);
cachePaint.setPen(pen);
cachePaint.drawPoint(x,y);
// ,
if(getFilterValue(QString("name")))
cachePaint.drawText(x,y,i->shortDescription());
}
}
}
}
painter->drawPixmap(0,0,cache);
//////////////////////////////////////////////////
painter->end();
renderMutex.unlock();
}
, , QCheckBox- ( ). , QSettings, , , , , .
class SettingsManager : public QObject
{
Q_OBJECT
public:
SettingsManager();
~SettingsManager();
static SettingsManager& instance();
QVariant value(const QString &key, const QVariant &defaultValue = QVariant());
void setValue(const QString &key, const QVariant &value);
SettingsManager(SettingsManager const&) = delete;
SettingsManager& operator= (SettingsManager const&) = delete;
private:
QMap data;
QSettings settings;
signals:
void updateMap();
};
( ) ( -). ( ).
//
void InteractiveMap::updateScale(qreal value, const QPointF& dpos)
{
qreal newScale = scale * value;
if(newScale >= minScale && newScale <= maxScale)
{
scale = newScale;
//
translate += dpos/scale;
updateCache();
}
}
//
void InteractiveMap::updateTranslate(const QPointF& value)
{
QPointF newV = translate + (value * 1/scale);
translate = newV;
update();
}
//
void InteractiveMap::mousePressEvent(QMouseEvent *pe)
{
//
if(pe->buttons() & Qt::LeftButton)
startMove = pe->pos();
//
else if(pe->buttons() & Qt::MidButton)
{
if(worldState)
{
// ,
QPointF pos = pe->pos()/scale - translate;
if(pos.x() >= 0.0f && pos.x() <= image->width() && pos.y() >= 0.0f && pos.y() <= image->height())
{
//
pos.rx() = pos.x() * (15360.0f / 975.0f);
pos.ry() = -((15360.0f/970.0f)*(pos.y()+4.0f)-15360.0f);
//
findCloseObjects(pos);
}
}
}
}
void InteractiveMap::mouseMoveEvent(QMouseEvent *pe)
{
//
if(pe->buttons() & Qt::LeftButton)
{
updateTranslate(pe->pos() - startMove);
startMove = pe->pos();
}
}
void InteractiveMap::wheelEvent(QWheelEvent *pe)
{
//
float dScale = (pe->angleDelta().y() < 0) ? 1/scaleStep : scaleStep;
QPointF nPos = pe->pos() * (dScale);
QPointF dPos = pe->pos() - nPos;
updateScale(dScale,dPos);
}
QtConcurrent, MapReduce.
//Reduce
void addToAnswer(QString& result, const QString& interm)
{
if(!interm.isEmpty())
result += interm;
}
void InteractiveMap::findCloseObjects(QPointF coords)
{
if(!closeObjWatcher.isRunning())
{
//
input = new QVector;
for(QMap::iterator it = worldState->entityRanges.begin(); it!=worldState->entityRanges.end();++it)
{
if(getFilterValue(it.key()))
{
//
CloseObjects obj(&it.value(), coords);
input->append(obj);
}
}
closeObjFuture = QtConcurrent::mappedReduced(*input, &CloseObjects::findCloseObjects, addToAnswer);
//
connect(&closeObjWatcher, &QFutureWatcher::finished, this, &InteractiveMap::sendCloseObjects);
//
closeObjWatcher.setFuture(closeObjFuture);
}
}
void InteractiveMap::sendCloseObjects()
{
//
emit showCloseObjects(closeObjWatcher.result());
//
delete input;
input = nullptr;
}
.
class CloseObjects
{
public:
CloseObjects() {}
CloseObjects(EntityRange *r, QPointF p): range(r), coords(p) {}
QString findCloseObjects() const;
private:
EntityRange* range;
QPointF coords;
};
Map , , , ( + ) .
QString CloseObjects::findCloseObjects() const
{
QString result;
QTextStream stream(&result);
// 2
stream.setRealNumberNotation(QTextStream::FixedNotation);
stream.setRealNumberPrecision(2);
for(QVector::const_iterator it = range->start; it != range->end; ++it)
{
float len = qSqrt(qPow((it->getCoords().x() - coords.x()),2) + qPow((it->getCoords().y() - coords.y()),2));
if(len <= 350)
{
stream << it->fullDescription() << "\n" << QVariant(it->getCoords().x()/100).toFloat() << " " << QVariant((15360 - it->getCoords().y())/100).toFloat() << "\n";
}
}
return result;
}
. , , .
pull-request.
: