2017-01-19 7 views
0

У меня нет даже вопроса, я думаю, что это какое-то подтверждение, что я правильно понимаю предмет.
Я занимаюсь реинжинирингом, и вот что у меня есть. Допустим, мы имеем структуру/класс, который выглядит следующим образом:Указатель на массив указателей на структуры

struct { 
    char str[n] 
    int x 
    float a 
} 

И у нас есть массив этих структур в памяти процесса мы смотрим на.

Итак, у меня есть указатель на массив указателей на структуры.
И теперь, пожалуйста, поправьте меня, если я ошибаюсь. Чтобы прочитать значение x первого элемента этого массива (фактическая структура, а не указатель), я должен выполнить следующие шаги:

  1. Прочитайте значение, которое указывает указатель на (4 байта).
  2. Без каких-либо смещений читайте значение, которое ранее прочитало значения точек, а также 4 байта (это приведет меня к адресу, где начинается структура)
  3. Теперь мне нужно добавить смещение к этому, равное n. И прочитайте значение с адреса с шага 2 (step2result + n + 1).

Я прав? Получу ли я фактический X, который содержит первая структура? Чтобы получить значение X из второго, мне просто нужно добавить смещение в step2 (+4 байта)?

Я думаю, что я делаю это правильно, но на самом деле я не могу достичь структур из указателей. Указатель на массив на 100% прав, я бы сказал.

Спасибо за чтение, будем ждать ответов. Если вам нужна дополнительная информация, просто спросите об этом.

p.s. не получая ничего взломанного или всего, что только в образовательных целях

Дополнение:
ОК, я стараюсь упростить это, только затруднило его объяснить и понять. Теперь я попытаюсь это исправить.
Одна структура описывает параметры NPC в игре. Вся структура имеет размер 0x1200. Первые 16 байтов - это только идентификационная информация, а затем после этой информации идет строка, которая составляет 64 байта, это имя. Затем идет координата для X/Y/Z. Все после этого не имеет значения.
Это не было так трудно найти, вот скриншот, как это выглядит:
structure /
Так что я могу найти другие структуры только с добавлением или вычитанием 0x1200 по адресу, где начинается эта структура.
Я искал адрес, в котором начинается структура, и нашел указатель на это. Затем я просмотрел для доступов к найденному указателю и получил что-то вроде этого:

mov [eax+edx*4+00320], ecx 

Тогда я искал для значения eax и нашел указатель, который указывает на eax
Вот почему я думал, что это массив указатели.
Надеюсь, я только немного объяснил это.

+0

Массив структур является только упаковано Структуры один за другим. У вас есть еще один уровень косвенности, чем нужно. – Jester

ответ

0

Hahahahaha ....... Извините, но я не могу остановить свой смех, так как это мой второй день на Stackoverflow, и я задал вопрос, который отвечает на эту дилемму. Я не могу понять, что вы пытаетесь сделать, но я уверен, что вы не учли прописку. Хорошо, что я узнал прокладку вчера, поэтому я попытаюсь помочь вам здесь.

Ну, каждый массив имеет указатель на свой первый элемент в качестве имени массива. У вас есть указатель по умолчанию, или вы можете сделать свой собственный. Это очень простая задача для разделения структуры на массив указателей. Основная проблема, с которой вы сталкиваетесь, - это доступ к элементам структуры.

//This answer is architecture and compiler dependent 
//My settings are TDM GCC 4.9.2 64bit and Windows 10 
const int n = 5; 

#pragma pack(push, 1) 
struct A{ 
    char str[n]; 
    int x; 
    float a; 
}; 
#pragma pack(pop) 

struct B{ 
    char str[n]; 
    int x; 
    float a; 
}; 

int main(){ 

    printf("Size of A is %d\n", sizeof(A)); 
    printf("Size of B is %d\n", sizeof(B)); 
    B k; 

    for(int i=0; i<n; i++) 
     printf("Address of str[%d] in k is %x\n",i, &(k.str[0])); 

    printf("Address of int x in k is %x\n", &(k.x)); 
    printf("Address of float a in k is %x\n", &(k.a)); 

} 
/* 
Result - 

Size of A is 13 
Size of B is 16 
Address of str[0] in k is 9ffe30 Address of array 
Address of str[1] in k is 9ffe30 Address of str[1] in k is 9ffe31 
Address of str[2] in k is 9ffe30 Address of str[2] in k is 9ffe32 
Address of str[3] in k is 9ffe30 And so on.. 
Address of str[4] in k is 9ffe30 
Address of int x in k is 9ffe38 Address of Array + 8Bytes 
Address of float a in k is 9ffe3c //Address of Array + 2*8Bytes 

n -- padding 
4k+1 -- 3 
4k+2 -- 2 
4k+3 -- 1 
4k -- 0 */ 

Посмотрите на код. Структура A упакована, поэтому никаких отступов не производится. Структура B - это дополненная версия A. B - это та, которую вы используете.

Здесь я взял n = 5 для большинства padding.Here первые 5 байтов выделены для массива str. Теперь следующие 3 байта выделены для заполнения. Это делается для того, чтобы оперативная память могла получить доступ к 8 байтам одновременно, а не к одному байту за раз, как это сделано в случае упакованного strcuture. Это увеличивает производительность. Для заполнения не существует стандарта, поэтому он зависит от архитектуры и компилятора. В 64-битной архитектуре одновременно доступны 8 байтов. Вот почему 64-бит быстрее, чем 32 бит, а игры не поддерживают 32-битную. Чтобы получить доступ к int x, вам необходимо смещать адрес массива на 8 байт, а не 5. Чтобы снова открыть поплавок, увеличьте смещение на 8Bytes. Примечание. Здесь выводится только адрес массива не для отдельного элемента массива. Вы можете достичь этого, увеличивая на единицу.

Если вы не получили его, прочитайте выравнивание памяти в C++.

https://en.wikipedia.org/wiki/Data_structure_alignment

3

Ваш вопрос на самом деле полон наземных мин, которые продемонстрируют, почему точность сборки настолько важна, в несчастном образом.

Итак, что я есть ...

Вы показываете синтаксически неправильный анонимную-структуру, и вдруг у вас есть указатель? Это не работает. У вас анонимная структура и пара синтаксических ошибок, не более того.

Теперь я был бы в порядке, чтобы остановиться на ответе, потому что остальная часть вашего вопроса не имеет смысла без фактического определения данных. Но, допустим, вы имели в виду что-то вроде этого:

struct STRUCT_A { 
    char  str[17]; 
    int  x; 
    float a; 
}; 

STRUCT_A testA[3]{ 
    {"a1", 1111, 1.111}, 
    {"a2", 2222, 2.222}, 
    {"a3", 3333, 3.333} 
}; 

int foo(unsigned index) { 
    return testA[index].x; 
} 

Итак, что я здесь массив testA. Массив - это не просто указатель, он немного меньше в C++ во время компиляции, хотя он будет «разлагаться» на указатель при его использовании как таковой, но он не совсем то же самое.

Когда я буду использовать testA в качестве указателя, он не указывает на какие-либо дальнейшие указатели, он указывает непосредственно на данные.

Итак, у вас нет одного уровня, но два уровня дополнительной косвенности в OP. Чтобы прочитать x для первого элемента, вы просто делаете mov eax,[testA + 20]. Не загружен указатель (пример от целевого объекта x86 32b, по другим целям +20 может отличаться).

бы вы были:

STRUCT_A* testA_alias = testA; 
    // now this ^^ alias is no more array, it's just pointer 
    // (array silently decays into pointer during compilation, when asked to) 
STRUCT_A** testA_indirect = &testA_alias; 

Затем принести x второго элемента:

mov eax,[testA_indirect] ; eax = &testA_alias 
mov eax,[eax]    ; eax = testA (or &testA .. not sure how to write it, "address of data") 
mov eax,[eax + 28*1 + 20] ; eax = testA[1].x 

мне удалось создать два уровня косвенности (на самом деле я должен был изменить ответ в этой части, как и Я прочитал сборку с C++ неправильно, неполный синтаксис Intel смутил меня).

Все еще я не уверен, где вы получаете все эти указатели и почему? Это не Java, это C++, вы просто имеете свои данные в памяти напрямую. Как вы можете видеть, мне пришлось приложить немало усилий для получения двух уровней косвенности.

Теперь вы можете задаться вопросом, почему x находится на +20, а не на +17. Поскольку padding, C++ выравнивает элементы структуры в соответствии с их типом, int любит быть выровненным, так оно и есть.

Это также должно объяснить 28, который является размером этой структуры.

Также в вашем вопросе у вас есть:

step2result + п + 1

Откуда что +1 пришел? Может быть, вы смущены этим:

char str[]{"abc"};    // str[4] 

Но это потому, что "abc", как db 'a', 'b', 'c', 0 = четыре байта определены. При определении ее только как а, б, в, как три байта, то массив будет 3 байта:

char str2[]{'a', 'b', 'c'};  // str2[3] 

Как вы определяете, что char массив по [n], нет +1 участвует, что массив имеет ровно n символов , Если вы поместите в него литералы C-string, они могут быть длиннее (n-1) символов, так как n-й байт будет занят нулевым терминатором.


Вы можете проверить, как выглядит этот источник после компиляции here.

Возможно, ответ на ваш вопрос будет наилучшим образом.

Вы можете обратить особое внимание на определение содержимого памяти, я добавил комментарий к исходным линиям определения testA массива:

testA: 
     .string "a1"  ; three bytes 'a', '1', 0 defined 
     .zero 14   ; remaining 14 zeroed to have char[17] 
     .zero 3   ; padding for "int x" 
     .long 1111  ; int x 
     .long 1066284351 ; float a 
     .string "a2"  ; char[17] of second element 
... 
+0

Я перечитываю исходный вопрос, на нем похоже, что у вас может быть некоторая структура данных из внешнего двоичного кода, которая * включает * несколько слоев косвенности и указателей. Если это так, вы не смогли описать его достаточно хорошо в своем вопросе. Если вы не уверены, как правильно определить такую ​​структуру на C++, скорее покажите содержимое самой памяти, всегда лучше иметь необработанные байты вместо высокоуровневой mumbo-jumbo obfuscation теми странными терминами, как структуры, указатели и т. Д. .. пока все по-прежнему просто байт в памяти ... по крайней мере для меня сырые байты лучше всего работают.: D – Ped7g

+0

Добавил некоторую информацию в первый пост, и если бы я понял вас правильно, тогда да, это внешний двоичный файл, так как игровой процесс заканчивается на .bin – WardS

+0

И на самом деле это не проблема с чтением чего-либо из найденной структуры, так как я всегда могу проверить это, если он не работает - измените. Это вопрос о том, почему я не могу повторить действия с фактического указателя на структуру. – WardS

Смежные вопросы