Начальные значения регистров после загрузки PE

Тема в разделе "WASM.BEGINNERS", создана пользователем TriX, 21 дек 2009.

  1. TriX

    TriX Member

    Публикаций:
    0
    Регистрация:
    7 мар 2008
    Сообщения:
    68
    Обратил внимание на то, что после загрузки РЕ-файла регистры eax..edi инициализируются определенными значениями. Хотелось бы знать, откуда эти значения собсно берутся (особенно интересуют esi и edi, т.к. под разными отладчиками эти значения разные, по крайней мере у меня). Поделитесь инфой, плиз, что почитать и тд...

    PS: Поиском пользовался, набрел на http://wasm.ru/forum/viewtopic.php?id=10496, да вот только по ссылке bogrus перебрасывает в список форумов:dntknw:
     
  2. Rockphorr

    Rockphorr Well-Known Member

    Публикаций:
    0
    Регистрация:
    9 июн 2004
    Сообщения:
    2.625
    Адрес:
    Russia
    добавь в здраствуй мир подпрограмму принтхекс для своих регистров и посмотри что будет выдавать
     
  3. Blackbeam

    Blackbeam New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2008
    Сообщения:
    960
    наверное не имеет особого значения... скорее всего в секции Крит их какая-то функция не почистила за собой
     
  4. TriX

    TriX Member

    Публикаций:
    0
    Регистрация:
    7 мар 2008
    Сообщения:
    68
    Rockphorr
    посмотрел. Из того,что меня интересует: в ebx лежит указатель на peb, в edx - на KiFastSystemCallRet, а вот esi/edi - когда как, по-разному - в Олли1.10 одни значения, в бете 2й другие, без отладчика третьи.

    Blackbeam
    может быть, так оно и есть...
     
  5. Flint_ta

    Flint_ta New Member

    Публикаций:
    0
    Регистрация:
    25 май 2008
    Сообщения:
    312
    + На разных системах разные начальные значения регистров. ТС, для антидебага хочешь заюзать?
     
  6. JCronuz

    JCronuz New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    1.240
    Адрес:
    Russia
    Esi при Оле равен -1 поэтому используют это правильно как антиотладку
    http://vx.eof-project.net/viewtopic.php?id=142
     
  7. TriX

    TriX Member

    Публикаций:
    0
    Регистрация:
    7 мар 2008
    Сообщения:
    68
    Flint_ta
    Насчет разных не знаю, пока одна только машинка под рукой, гляну на днях вин2к, хр, висту. Для начала разобраться хотелось-бы, а там видно будет ;)
     
  8. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Прежде всего, информация, откуда вообще берутся значения регистров. Скажу сразу, что изучал всё это довольно давно, так что проверял поведение 2k и XP. Впрочем, не думаю, что что-то существенно поменялось.
    Новый Win32-процесс создаётся функцией kernel32.CreateProcess[Internal]W (в 2k была CreateProcessW, начиная с XP это переходник к CreateProcessInternalW, которая и работает).
    В процессе работы эта функция делает много чего и, в частности, вызывает NtCreateThread для создания нового потока. NtCreateThread принимает в качестве одного из аргументов контекст потока. В случае CreateProcess[Internal]W контекст формирует процедура BaseInitializeContext. Она инициализирует сегментные регистры в стандартные значения cs=18h, ds=es=ss=20h, fs=38h, gs=0 (позднее ядро добавит к этим значениям CPL=3), заполняет eax=указатель на entrypoint PE-файла, ebx=указатель на PEB, eip=BaseProcessStartThunk, esp=указатель на последний dword в стеке. Все прочие регистры не инициализируются, и их фактические значения представляют собой мусор из стека (в частности, зависят от того, что программа-создатель процесса делала со стеком до вызова CreateProcess*).
    Следующий этап в жизни процесса - инициализация (включающая загрузку dll и вызов их точек входа с DLL_PROCESS_ATTACH) - реализована посредством APC и на значения регистров не влияет (за исключением случаев, когда какая-то точка входа dll либо tls callback поставила себе целью напакостить), поэтому этот этап можно пропустить.
    Далее в действие вступает BaseProcessStartThunk. Эта функция устанавливает SEH-фрейм, вызывает NtSetInformationThread, вызывает точку входа PE и (если оттуда вернулось управление) вызывает ExitThread с кодом, возвращённым точкой входа.
    Изменения в состоянии регистров, произведённые BaseProcessStartThunk, следующие.
    Volatile-регистры eax,ecx,edx устанавливаются при последнем вызове NativeAPI. eax принимает значение статуса операции, а поскольку она всегда успешна, то eax=0. ecx и edx зависят от используемого механизма системного вызова, в случае sysenter/sysexit из XP SP1 ecx=esp-8, edx=7FFE0304h, начиная с SP2 edx=KiFastSystemCallRet.
    Значение ebx не трогается, так что там остаётся указатель на PEB, записанный в BaseInitializeContext. Значения esi и edi не трогаются, так что там остаётся мусор из стека CreateProcess*.
    ebp и esp устанавливаются соответственно стековому фрейму, то есть ebp=(верхушка стека - 10h), esp=(верхушка стека - 3Ch).
     
  9. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    "реализована посредством APC и на значения регистров не влияет (за исключением случаев, когда какая-то точка входа dll либо tls callback поставила себе целью напакостить)"
    мм, как она сможет напакостить?
     
  10. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    При user-mode APC контекст прерванного потока хранится в пользовательском стеке (в данном случае - естественно, близко к верхушке), ничто не мешает значения в этом стеке немного подкорректировать. (Смотреть, например, ntdll.KiUserApcDispatcher - в процессе начальной инициализации она самая верхняя по стеку вызовов.)
     
  11. TriX

    TriX Member

    Публикаций:
    0
    Регистрация:
    7 мар 2008
    Сообщения:
    68
    diamond
    Респект! Полезная инфа.
     
  12. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    >При user-mode APC контекст прерванного потока хранится в пользовательском стеке
    ...И именно на этот контекст будет указывать третий аргумент DllMain\TlsCallback ("LPVOID lpvReserved").
    diamond, спасибо за чёткое описание.
     
  13. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    я смотрю, а там мусор :)
    top-0x10 же?
     
  14. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Перед KiInitializeUserApc esp=top-4 (из исходного контекста), дальше так:
    esp = (esp & ~3) - sizeof(CONTEXT) - 0x10
    dword [esp] = <apc routine> (для рассматриваемого случая LdrInitializeThunk; KiUserApcDispatcher затирает значение адресом возврата в себя)
    dword [esp+4] = context (0; LdrInitializeThunk затирает значение указателем на сохранённый контекст)
    dword [esp+8] = arg1 (база ntdll.dll)
    dword [esp+12] = arg2 (0)
    CONTEXT [esp+16] = сохранённый контекст
    eip = KiUserApcDispatcher
    Так что контекст располагается по top-2D0h.
     
  15. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    точно
    Код (C++):
    1.         TopOfStack = (ContextFrame.Esp & ~(__alignof(EXCEPTION_REGISTRATION_RECORD)-1));
    2.         Length = CONTEXT_ALIGNED_SIZE + sizeof(KAPC_RECORD);
    3.         UserStack = ((TopOfStack - sizeof (EXCEPTION_REGISTRATION_RECORD)) & ~CONTEXT_ROUND) -
    4.             Length;
    5.      ...
    6.         TrapFrame->HardwareEsp = UserStack;