Срыв стека, затираемые переменные...

Тема в разделе "WASM.RESEARCH", создана пользователем zag2art, 4 ноя 2005.

  1. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    Здравствуйте.



    Это задача на переплнение буфера.



    В моей программе после переполняющегося буфера идут несколько переменных, которые надо затереть для того, чтобы изменить адрес возврата. Но возникла одна проблема:

    одна из переменный (по адресу ebp+adata_p) сразу же после

    переполнения используется вот-так: ( программа на Делфях, а сама переменная хранит адрес объекта TStream и всегда храниться в разных местах памяти)


    Код (Text):
    1.  
    2.         ;здесь происходит переполнение
    3.         mov     eax, [ebp+adata_p]; eax = ад.пер. TStream
    4.         mov     edx, [eax]; таблица функций    
    5.         call    dword ptr [edx]; eax=TStream.GetSize;
    6.  




    Если я затираю эту переменныю, сробатывает иксепшн.



    Может кому-нибудь придет в голову как можно использовать

    эту констукцию, чтобы по цепочке вызвать, то, что нужно.



    Или, как бы затереть ее так, чтобы без иксепшинов.



    Че-то в голову пока ниче не лезет...



    Возможет еще такой вариант: кто-нибудь может знает такую функцию, которую можно вызвать подобным образом, так, чтобы как говориться без иксепшинов...
     
  2. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    если по простому, то задача в том, чтобы чтото засунуть в стек вместо этой переменной, чтобы:

    1 - не было иксепшина

    2 - желательно на выходе, eax<8000



    PS

    почему происходят иксупшины мне очень даже понятно,

    по этому поводу я много перепробовал, находил даже такую

    цепочку, что вызовы шли именно в TStream.GetSize,

    но безрезультатно, так, как я заранее не знаю где

    нахадиться моя переменная типа TStream...
     
  3. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    это все дело находится в обработчике от TUDPServer

    при приходе датаграммы, программа чата, под UDP протокол.

    Буфер переполняется при приеме пакета примерно так:
    Код (Text):
    1.  
    2. var
    3.     arr:array[1..8000] of byte;
    4.     str: TStream;
    5.     ....
    6. begin
    7.    ....
    8.    data.ReadBuffer(arr,adata.Size);
    9.    //здесь тот код, который я приводил
    10.  




    >A_Must_Loll

    намек конечно понял, но жить то как-то надо...



    идею класса на делфи не усек (или эта издевка такая),

    хотелось бы ченить конструктивное...



    ищу пока другие переполнения...
     
  4. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    >A_Must_Loll

    ну так, я и херачу больше размера буфера, и дальше прога мирно умирает, записывая в свой лог ошибку при чтении UDP.

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



    код который использует эту ссылку на TStream я уже приводил. для полного счастья мне нужен такой адресок в памяти, который можно три раза разименовать и потом сделать call туда, это ясно из фрагмента кода выше...
     
  5. bober

    bober New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2005
    Сообщения:
    153
    zag2art



    А тебе не приходило в голову спросить про свою проблему на форуме по дельфи? Кто его знает как дельфи шлет UDP.

    Может ты какие-нибудь свойсва (TStream и TUDPServer)неправильно установил - это луше всего знают те кто работает с этими объктами. А низкоуровневое програмирование это ближе к API.
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    zag2art

    > "для полного счастья мне нужен такой адресок в памяти, который можно три раза разименовать"

    Ну дык покапайся в импорте - наверняка найдешь GetLastError, GetCurrentThreadID и т.п. функции без параметров. Смещаешь адрес на 2 байта чтобы обойти JMP и получаешь свои три безопасных разименования. Правда не факт, что после этого еще на что-нибудь не нарвешься ;)
     
  7. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    спасибо leo, активно этим занимаюсь (я так понимаю не все JMP для этого подойдут?)
     
  8. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    zag2art

    > "активно этим занимаюсь (я так понимаю не все JMP для этого подойдут?)"

    Не понял, о чем это ты ;)

    Если прога у тебя под рукой, то грузишь ее в Олю, делаешь Search for Names и с вероятностью 99.9(9)% находишь ссылку на GetLastError. Это адрес из таблицы импорта (секция .idata), по которому лежит адрес самой функции GetLastError. Тебе нужен не этот адрес, а адрес JMP из секции CODE (в дельфях все вызовы импортируемых функций идут через джампы JMP m32, опкод FF25). Поэтому делаешь Find references to import и в первой строчке получаешь адрес этого JMP, переходишь по Follow in Disassembler и убеждаешься в том, что это действительно JMP по адресу в idata. Готово, твой искомый адрес равен адресу инструкции JMP плюс 2 байта. Можешь писать его в стек на место переменной strm:TStream и смотреть что будет дальше ;)))

    (А дальше видимо будет не менее интересно, т.к. по кр.мере в конце функции д.б. вызов strm.Free ;))



    Ес-но вместо GetLastError можно использовать другие апишные функции без параметров (GetCurrentThreadID и т.п, GetActiveWindow и т.д.)
     
  9. zag2art

    zag2art New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2005
    Сообщения:
    40
    Спасибо, leo, все работает как надо...

    GetLastError прокатил.