クローズド ソース プログラム用のツールを作成しています。デバッグ後、アクセスしたい構造のベースアドレスを取得しました。よく調べてみると、最初の 3 つの整数がポインターであり、他のすべての値がデータであるマルチリンク リストであることがわかります。
私は自分の分析からこの構造を再構築することに成功しました:
struct UnitsInfo
{
//pointers to UnitsInfo structures, null when no structure available at that location
DWORD * a;//0x00
DWORD * b;//0x04
DWORD * c;//0x08
//data
int unkown_1; //0x0C
unsigned int Type; //0x10
unsigned int Amount;//ox14
};
UnitsInfo * Base_Node = ((UnitsInfo*)( (*(DWORD*)( (*(DWORD*)(0x00400000+0x008E98EC)) + 0x38)) + 0x0C);
さて、私は連結構造、ましてや多重連結構造についてはまったくの初心者です。
私が考えていたのは、マップを作成して、すべてのアドレスを取得するまでブルートフォースを行うことです。(無限ループ可能)?
しかし、これがこのリンクされたリストをトラバースする方法ではないことはわかっています。どのように接続されているかを知らずに、この複数のリンクされたリスト内のすべてのノードを効率的にトラバースするにはどうすればよいでしょうか (そして、既に持っていたノードを回避します)。
編集:答えのおかげで、私はついにそれを作りました!
これが私のコードです。他の人にとっては便利かもしれません。
#define MAX_PLAYERS (6)
#define POINTER(type,addr) (*(type*)(addr))
struct UnitsInfo
{
//pointers to UnitsInfo structures, null when no structure available at that location
DWORD * nodes[3];//0x00
//data
int unkown_1; //0x0C
unsigned int Type; //0x10
unsigned int Amount;//ox14
};
struct pinfo
{
bool in;
enum Controller {Ctrl_UNKNOWN, Ctrl_HUMAN, Ctrl_AI };
enum Nation {N_UNKNOWN, N_ALLIES, N_SOVIET, N_JAPAN };
std::string Name;
Nation Side;
short Team;
Controller Who;
int *Money;
int *Power;
int *Usage;
unsigned int *Color;
bool GotUnits;
DWORD *unit_start_node;
};
std::map<DWORD*,UnitsInfo*> UnitList[MAX_PLAYERS];
void GenerateUnitList(unsigned short slot)
{
std::set<DWORD*> todo;
unsigned int inserted = 1;
while(inserted)
{
inserted = 0;
for(auto it = UnitList[slot].begin(); it != UnitList[slot].end(); ++it)
{
for(short i = 0; i < 3; ++i)
{
if(it->second->nodes[i] != NULL)
{
if(UnitList[slot].find(it->second->nodes[i]) == UnitList[slot].end())
{
todo.insert(it->second->nodes[i]);
++inserted;
}
}
}
}
while(!todo.empty())
{
UnitList[slot][*todo.begin()] = &POINTER(UnitsInfo,*todo.begin());
todo.erase(todo.begin());
}
}
}
pinfo Player[MAX_PLAYERS];
//adding the first node
unsigned int CurrentSlot = (0xD8+(0x4*slot));
if(POINTER(DWORD,POINTER(DWORD,0x00400000+0x008E98EC)+CurrentSlot) != NULL)
{
Player[slot].unit_start_node = &POINTER(DWORD,POINTER(DWORD,POINTER(DWORD,POINTER(DWORD,0x00400000+0x008E98EC)+CurrentSlot) + 0x38) + 0x0C);
}
//adding first unit if available, if yes continue generating list
if(!Player[i].GotUnits)
{
if(POINTER(DWORD,*Player[i].unit_start_node+0x10) != NULL)
{
Player[i].GotUnits = true;
UnitList[i][(Player[i].unit_start_node)] = &POINTER(UnitsInfo,*Player[i].unit_start_node);
}
}
else
{
GenerateUnitList(i);
}
そして何よりも、それは魅力のように機能し、遅れることはありません:)