#java #heap-memory
#java #куча-память
Вопрос:
Я хочу проверить, действительно ли работает ASLR, который рандомизирует местоположение кучи для процесса.
Комментарии:
1. Какого рода атаке вы можете подвергнуться в Java, с которой ASLR помогла бы вам?
2. Я просто хотел знать, возможно ли различать предсказуемость ASLR и не ASLR, используя Java-код
Ответ №1:
Вы можете вызвать Unsafe.allocateMemory(size)
на некоторых JVM. Это возвращает местоположение в памяти.
Я не рекомендую вам делать это, и я не рекомендую вам беспокоиться об ASLR с Java.
Комментарии:
1. Следует отметить, что
Unsafe
обычноsun.misc.Unsafe
это класс, специфичный для JVM. Это определенно не стандартный API 😉2. Не вызовет ли Unsafe.getUnsafe() исключение SecurityException, если оно вызвано не из класса из загрузчика классов bootstrap?
3. @Paul Cager, вы не можете использовать
getUnsafe()
для получения экземпляраUnsafe
Я полагаю, если вы не можете решить, как получить экземпляр другим способом, вам не следует использовать Unsafe . 😉
Ответ №2:
Вы не можете сделать это на чистой Java.
-
Машинный адрес (указатели) не предоставляется приложениям Java.
-
Даже если бы они это сделали, нет Java API, который сообщал бы вам, где находится куча.
Я полагаю, что вы могли бы использовать значения, возвращаемые System.identityHashcode()
в качестве эрзац-адресов компьютеров. Если вы написали простое тестовое приложение Java, которое проверяло хэш-код идентификатора образца объекта, затем запускало его несколько раз с включенным и отключенным ASLR, вы могли бы заметить разницу в предсказуемости.
Комментарии:
1. В настоящее время тестируется с System.identityHashCode () Может быть, я могу запустить это в Vista и Windows 7 и сравнить предсказуемость ASLR? Я думаю, что ASLR лучше реализован в Windows 7
Ответ №3:
Вы должны быть в состоянии сделать это с помощью JNI. Выделите массив длинных файлов размером с вашу кучу или чуть меньше и вызовите тестовый метод JNI.
package com.example.aslrtest;
public class Test {
private static native void test(long[] heapa);
public void doTest()
{
long[] a=new long[size_of_available_heap/8];
for (long i=0; i!=a.length; i )
a[i]=i;
test(a);
System.out.println(a[0]);
}
}
Затем с помощью чего-то вроде этого JNI-кода вы можете получить адрес этого массива.
JNIEXPORT void JNICALL Java_com_example_aslrtest_Test_test(JNIEnv * env, jclass jc, jlongArray heapa)
{
jlong* heapp;
jboolean jniNoCopy = JNI_FALSE;
heapp = (*env)->GetLongArrayElements(env, heapa, amp;jniNoCopy);
heapp[0] = (jlong)heapp;
(*env)->ReleaseLongArrayElements(env,heapa,heapp,0);
}
Когда этот код возвращается, первый элемент массива должен содержать адрес массива.
Имеет ли смысл это делать — другой вопрос. Зависит от того, что вы делаете. Я предполагаю, что, вероятно, нет, но это ваше решение.