Сегодня неожиданно возник вопрос: одинаков ли адрес загрузки ntdll.dll во всех процессах. Поспорив немного, вопрос разбили на два: влияет ли ASLR на ntdll.dll и как, собственно, работает ASLR: отличаются ли адреса загрузки системных dll в разных процессах. Поскольку практика - мерило истинности, быстренько написали скрипт на питоне и все выяснили. Сам скрипт был написан очень быстро ( по сути, скопипастили пример proclist.py и слегка его модифицировали ). Вот быстрота написания скрипта и сподвигла меня написать этот пост. А заодно хочется продемонстрировать некоторые приемы работы с pykd.
Вот сам код:
Вот сам код:
import sys
from pykd import *
def moduleBase():
nt = loadModule( "nt" )
processList = typedVarList( nt.PsActiveProcessHead, "nt", "_EPROCESS", "ActiveProcessLinks" )
for process in processList:
dbgCommand( ".process /p %x" % process.getAddress() )
dbgCommand( ".reload /user" )
print "process %x " % process.getAddress(), "".join( [ chr(i) for i in process.ImageFileName.values() ] )
ntdll = loadModule("ntdll")
if ntdll != None: print "\tntdll: %x" % ntdll.begin()
kernel32 = loadModule("kernel32")
if kernel32 != None: print "\tkernel32: %x" % kernel32.begin()
if __name__ == "__main__":processList = typedVarList( nt.PsActiveProcessHead, "nt", "_EPROCESS", "ActiveProcessLinks" )
for process in processList:
dbgCommand( ".process /p %x" % process.getAddress() )
dbgCommand( ".reload /user" )
print "process %x " % process.getAddress(), "".join( [ chr(i) for i in process.ImageFileName.values() ] )
ntdll = loadModule("ntdll")
if ntdll != None: print "\tntdll: %x" % ntdll.begin()
kernel32 = loadModule("kernel32")
if kernel32 != None: print "\tkernel32: %x" % kernel32.begin()
moduleBase()
Запустив данный скрипт в отладчике ядра, мы получим что-то вроде:
process ffffffff859fbbb0 System process ffffffff8bbf5460 smss.exe ntdll: 77d50000 kernel32: 76b40000 process ffffffff81f6f6a8 csrss.exe ntdll: 77d50000 kernel32: 76b40000 process ffffffff892435a8 wininit.exe ntdll: 77d50000 kernel32: 76b40000 process ffffffff89269b98 csrss.exe ntdll: 77d50000 kernel32: 76b40000 .......и ответы на свои вопросы. Но не совсем сразу. Перезапустим систему и выполним скрипт еще раз - значения будет другие. Вот теперь уже все ясно. ASLR меняет адреса загрузки при каждом ребуте, в пределах одной загрузки адреса во всех процессах одинаковы.
Хочу обратить внимание на использование функции dbgCommand. Она позволяет выполнять обычные команды windbg. И если какой-то функционал не реализован в pykd, его можно "позаимствовать".
В данном случае, мы позаимстовали команду .process c ключиком /p. Без этого ключика можно было бы использовать функцию setCurrentProcess. Но к сожалению, данная функция не включает неявную трансляцию адресов. В результате, мы не можем получить актуальный список модулей пользовательского режима для каждого процесса. Тут то нам на помощь и пришла спасительная функция dbgCommand.
Комментариев нет:
Отправить комментарий