Здравствуйте! Как происходит выделение стека операционной системой процессу? Почему при задании фиксированного базового адреса(к примеру 400000h) при компилировании в VisualStudio 2010 под семеркой я вижу адрес начала стека 0018FFFC, а под вистой 0012FFFC? Почему при компиляции в FASM с заданием того же базового адреса я вижу начало стека 000CFFFC?
pashe4ka13 Память стека выделяется потоку, а не процессу. Как самая обычная память. ZwAllocateVirtualMemory. Адрес дна стека никак не связан с адресами проекции образа. Различие в адресах дна стека определяется картой памяти процесса на момент выделения стековой памяти и собственно размером стековой памяти. Раз семёрка выделяет стек первичного потока по старшим адресам, значит память по младшим адресам уже чем-то занята. По умолчанию fasm указывает максимальный размер стека по умолчанию (тавтология оправдана) в 0x1000, а студия в 0x100000. Дырка по младшим адресам в карте памяти, в которую умещается 0x1000 на момент выделения стековой памяти, не может вместить 0x100000.
l_inc Спасибо, все так как я и подозревал. На свой последний вопрос я уже сам себе ответил поменяв размер стека в РЕ заголовке фасмовского файла. Но моя проблема в другом. Я надеялся, что у одного и того же файла, при запуске его на различных ОС, при создании потока, стек выделяется по одинаковым адресам. Мне надо передать управление ret'ом обратно на стек. Как осуществить подобное? Может есть такие модули которые грузятся в память не рандомно? Например в моем приложении используются MSVCR100.dll,WSOCK32.dll,CRIPTBAS.dll,SspiCli.dll,WS2_32.dll,kernel32.dll,RPCRT4.dll, sechost.dll,NSI.dll,msvcrt.dll,ntdll.dll.
valterg да мне хотя бы на одной при перезагрузке , просто в идеале хотелось бы, что б какой нибудь из них грузился везде по одному и тому же адресу. Ладно сам посмотрю, хотя заранее уверен в неуспехе.
Вот здесь вроде бы есть информация как найти адрес функции динамически https://rdot.org/forum/showthread.php?t=1318
kravich да проблема не в поиске функций, а в передаче управления шеллу. Для передачи управления я использую подмену адреса возврата в стеке, но при запуске на разных системах стек выделяется по разным адресам. По этой причине я не могу жестко задать адрес перехода на шелл. Я хотел сделать по типу ROPa, расчетать адрес возврата, но в связи с тем, что все модули грузятся рандомно не могу понять как это сделать?
pashe4ka13 Ну значит придётся почитать память процесса штатными средствами. В TIB найдёте адрес стека. Только не забывайте, что неисполняемость стека надо тоже ещё обойти.
l_inc Что чем почитать? Шелл заливается удаленно. Как передать на него управление? Например я бы мог затереть адрес возврата так что бы он указывал на jmp esp(call esp) в эксплуатируемой программе, но она настолько мала, что в ней не встречается нужная последовательность байт.
Блин, я наверное плохо объяснил. Вообщем есть сетевое приложение с переполняющимся буфером. Буфер выделяется в стеке. Я могу удаленно переполнить буфер, залить шелл и подменить адрес возврата на свой шелл. Но если я уязвимое приложение запускаю на другой машине, то стек расположен уже по другим адресам. Соответственно адрес возврата на шелл надо будет менять. Как с этим бороться? Должно же быть решение.
pashe4ka13 А ты думаешь, что мелкософты замутили DEP+ASLR для того, чтобы их можно было легко и просто обойти "как два пальца.."? Отсюда пара вопросов: 1) грузится ли твоя подопытная прога по фикс.адресу или по dynamicbase - если по фикс, то и изучай ее на предмет ROP, если нет, то ... 2) работает ли она (или может работать) с включенным DEP - если да, то простая передача управление на шелл в стеке тоже может обломиться и соотв-но нужно доп-но искать\юзать ROP-ы c VirtualProtect или VirtualAlloc+CopyMemory
pashe4ka13 Ага. Ранее об удалённом исполнении не упоминалось. А приложить программку сюда можно, чтобы другим на кофейной гуще гадать не приходилось?
zer Каким образом? leo ни чего уже не думаю, весь ASLR моск вынесло Будем считать, что грузится. Я её скомпилировал с фиксированным базовым адресом 400000, НО pashe4ka13 leo стек исполнимый l_inc Она давно уже здесь http://www.wasm.ru/forum/attachment.php?item=4676
pashe4ka13 Ну, честно говоря, я здесь особых проблем не вижу. Например, есть две очень простые rop-цепочки: Код (Text): 009E11F1 |? 95 ||XCHG EAX,EBP 009E11F2 |? C3 ||RETN Код (Text): 009E1B1B |. 48 DEC EAX 009E1B1C |. 5D POP EBP 009E1B1D \. C3 RETN Я полагаю, что в момент переполнения разница между esp и ebp не очень большая и постоянная. Посредством этих двух цепочек можно переместить ebp в eax и дотянуть eax до нужного значения, где уже будет Ваш код в стеке. Ну и в бинарнике, разумеется, есть парочка call eax, одним из которых можно прыгнуть на этот код.
pashe4ka13 И что, это реальная прога или просто "Hello, world!" для домашних упражнений?! Даже стек "исполнимый", ну просто "подарок судьбы"!
l_inc В конце процедуры, перед возвратом: Код (Text): mov esp,ebp pop ebp retn После этого в ebp ноль. Я его затираю сам, так как он лежит в стеке выше адреса возврата. leo Это простой привет мир для домашних упражнений. Написал его специально с багом переполнения буфера.
Обрати внимание на ("хитрую" и видимо "стандартную") процедуру установки SEH-фрейма по адресу 0х401CD0. Она сохраняет в eax и ebp значения, зависящие от текущего esp - если не путаю, то в eax = esp_retn-4, а в ebp = esp_retn+0Ch, где esp_retn - значение esp адреса возврата из твоей переполняемой функи
Еще вчера обратил (правда она у меня уже давно по другому адресу на нее внимание, но попробовать не смог, так как не было уже сил бороться с усталостью и сном. leo,l_inc спасибо вам ребята ОГРОМНОЕ!!!