Как увеличить размер локального буфера(массива) в стеке без лишних телодвижений?

Тема в разделе "WASM.RESEARCH", создана пользователем CyberRSR, 22 окт 2024.

  1. CyberRSR

    CyberRSR New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2022
    Сообщения:
    4
    Есть глючная прога работы с оборудование, без него не запускается и работать не будет чтоб проверить. Предположительно вылетает молча из-за переполнения буфера, если задать слишком большой диапазон сканирования. Прога написана на borland C++ 5.0 вроде в 200х лохматом году.
    В ней есть локальный массив LastMeasStr, который нужно увеличить в 128 раз или больше. Массив локальный для функции, которая хрен пойми где вызывается, есть только смещение.
    upload_2024-10-22_2-2-28.png
    Как безболезненно увеличить размер массива и стека под него?
    Чет я забыл как там стек выделяется в exe.
    Начало функции типа такое:
    upload_2024-10-22_2-3-7.png
    Обращение к массиву так происходит:
    upload_2024-10-22_2-4-16.png
    где
    upload_2024-10-22_2-4-41.png

    И в функции везде подобные вызовы, фиг поймешь как он esp сдвигает под все переменные функции:
    upload_2024-10-22_2-5-27.png
     

    Вложения:

  2. Ahimov

    Ahimov Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    40
    Резервный размер стека установить в параметрах пе. Затем пофиксить число выделяемых страниц(0x85). Прежде наверно нужно посмотреть допустимый размер стека, иначе не пройдёт создание процесса(bad pe format..).
     
    CyberRSR нравится это.
  3. Prober

    Prober Member

    Публикаций:
    0
    Регистрация:
    4 дек 2008
    Сообщения:
    43
    Не слишком ли много непонятного?

    Если прога вылетает - значит, запускается. Значит, отладчик в помощь, выясняйте конкретную причину вылета. Без неё будет тыканье вслепую с минимальными шансами угадать.
     
    MaKsIm нравится это.
  4. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    101
    Добавлю. Отладчик есть даже в IDA, откуда все эти скрины
     
  5. CyberRSR

    CyberRSR New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2022
    Сообщения:
    4
    Прога запускается только вместе с устройством. Запустить ее до этой функции без устройства очень сложно. Отлаживать на работающем устройстве опасно, может сдохнуть, оно и так пищит и плачет при вылете проги.
    --- Сообщение объединено, 22 окт 2024 ---
    Точно, чет я сразу цикл выделения стека не заметил.
    А где прописан допустимый размер стека? В PE?
    И расширенный массив уже в конце стека добавлять и работать с ним, чтоб ниче не сдвигать?
     
  6. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    101
    CyberRSR нравится это.
  7. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    456
    SizeOfStackReserve/SizeOfStackCommit: The maximum value for SizeOfStackReserve is 4 GB for PE32 and 16 EB (exabytes) for PE32+
     
    CyberRSR нравится это.
  8. Ahimov

    Ahimov Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    40
    CyberRSR

    Да, так как размер массива ограничен переменными и что бы не фиксить их смещения, лучше пофиксить смещение массива LastMeastStr.
     
  9. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    196
    ого планка.. это где было видано, чтобы под стек выделялось всё доступное ап?
    и вообще из 64-бит десктопные ос используют всего 48, а это 256 тера, по 128 юзеру и кернелу.
    поэтому ре может и унести столько, а вот ос наврядли.
     
  10. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    456
  11. CyberRSR

    CyberRSR New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2022
    Сообщения:
    4
    upload_2024-10-29_1-26-24.png

    Так там SizeOfStackCommit всего 0x2000, явно меньше, чем в этой функции выделяется, из-за этого не может вылетать? Или я чего-то не понимаю?
    "The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest is made available one page at a time until the reserve size is reached."
    В итоге весь Reserve доступен или только Commit? Чет первый раз с таким сталкиваюсь, всегда думал что ограничено Reserve. И в PE особо никогда не заглядывал.
     
  12. MaKsIm

    MaKsIm Active Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    101
    Значит так. Для каждой нити/ветви/thread система резервирует SizeOfStackReserve блок адресов. А вот выделяет она сразу только SizeOfStackCommit страниц памяти для размещения стека. Когда указатель стека пересекает границу выделенного блока памяти (т.е. размер стека превышает SizeOfStackCommit), тогда выделяется еще одна страница памяти, но не более чем SizeOfStackReserve (одна страница это 4 кб). При этом перепрыгнуть эту страницу памяти нельзя. Т.е. если вы хотите выделить единовременно в стеке больше 4 Кб, тогда вам надо двигать указатель стека постранично и производить хотя бы одну попытку записи на новую страницу памяти, чтобы произошло срабатывание ловушки и была выделена страница памяти. При этом под наблюдением находятся только адреса ближайшей страницы памяти, а не всего диапазона (SizeOfStackReserve - SizeOfStackCommit). Обратно страницы памяти стека высвобождаются только при уничтожении нити/ветви/thread.
     
    Последнее редактирование: 29 окт 2024
    CyberRSR нравится это.
  13. CyberRSR

    CyberRSR New Member

    Публикаций:
    0
    Регистрация:
    4 ноя 2022
    Сообщения:
    4
    Короче, делаем SizeOfStackCommit = SizeOfStackReserve и не паримся, а иначе я не представляю как перенести новую переменную и подправить для нее просто адреса везде, при этом не прыгая по страницам?
    ААА, все я допер зачем там цикл с выделением 85 страниц.
     
    Последнее редактирование: 29 окт 2024
  14. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    196
    Помимо лимитов в РЕ-заголовке, система сама выделяет лимиты для каждого из тредов потока - они прописаны в ТЕВ.
    Код (Text):
    1. 0:000> !teb
    2. TEB at 000007fffffde000
    3.     StackBase:     0000000000070000
    4.     StackLimit:    000000000006d000
    Тогда получаем размер стека на входе 0x70000-0x6d000=0x3000 или 12K.
    Можно проверить атрибуты данного региона, и эти 3 страницы будут полностью доступны в любой момент:
    Код (Text):
    1. 0:000> !address 6d000
    2. Usage:             Stack
    3. Allocation Base:   00000000`00030000
    4. Base Address:      00000000`0006d000
    5. End Address:       00000000`00070000
    6. Region Size:       00000000`00003000         <-----//
    7. Type:              00020000  MEM_PRIVATE
    8. State:             00001000  MEM_COMMIT
    9. Protect:           00000004  PAGE_READWRITE  <-----//
    А вот сл.страница (выше текущего лимита 6d000) уже имеет атрибут сторожевой Guard. Диспетчер исключений имеет обработчик на #PG, так-что выход за пределы трёх страниц проходит безболезненно, и для этого не нужно ничего записывать в стек - просто sub rsp,3000h и всё:
    Код (Text):
    1. 0:000> !address 6c000
    2. Usage:             Stack
    3. Allocation Base:   00000000`00030000
    4. Base Address:      00000000`0006b000
    5. End Address:       00000000`0006d000
    6. Region Size:       00000000`00002000
    7. Type:              00020000  MEM_PRIVATE
    8. State:             00001000  MEM_COMMIT
    9. Protect:           00000104  PAGE_READWRITE | PAGE_GUARD  <----//
    Только после первого #PG система будет выделять по одной странице,
    вставляя на границах сторожевые - здесь уже нужна запись в стек, иначе #AV.

    Если посмотреть на предыдущий блок !address, то необрабатываемое исключение "StackOverflow" получим только выше адреса AllocationBase=0x30000. Тогда получается, что моя Win7-x64 выделяет глобальный лимит для стека одного потока 70000-30000=40000h, или 256K, хотя в доках пишут 1Mb (возможно на Win10). Регион выше этого адреса уже лежит в резерве (а не commit), и его нужно выделять через VirtuaAlloc().
    Код (Text):
    1. 0:000> !address 30000
    2. Usage:             Stack
    3. Allocation Base:   00000000`00030000
    4. Base Address:      00000000`00030000
    5. End Address:       00000000`0006b000
    6. Region Size:       00000000`0003b000
    7. Type:              00020000  MEM_PRIVATE
    8. State:             00002000  MEM_RESERVE  <----//
    9. Protect:           00000000
    Вот код, который выводит инфу о стеке из TEB, после чего выделяет в нём сразу текущий размер. Далее вплоть до 0x30000 нужно чё-нить ложить в стек, чтобы код начал пожирать его.

    Код (ASM):
    1. format   pe64 console 5.0
    2. include 'win64ax.inc'
    3. entry    start
    4. ;//-----------
    5. .data
    6. stackSize   dq  0
    7.  
    8. ;//-----------
    9. section '.text' code readable executable
    10. start:   sub     rsp,8
    11.  
    12.          mov     rax,[gs:60h]   ; PEB addr
    13.          mov     rax,[rax+10h]  ; ImageBase
    14.          mov     ebx,[eax+3ch]  ;
    15.          add     eax,ebx        ; PE header
    16.          mov     r10,[rax+60h]  ; StackReserved
    17.          mov     r11,[rax+68h]  ; StackCommit
    18.         cinvoke  printf,<10,' PE info ========',\
    19.                          10,'   Stack Reserved: 0x%08llx',\
    20.                          10,'   Stack Commit..: 0x%08llx',10,0>,r10,r11
    21. ;-------------
    22.          mov     rax,[gs:08h]  ; StackBase
    23.          mov     rbx,[gs:10h]  ; StackLimit
    24.          mov     r10,rax
    25.          sub     r10,rbx       ; StackSize
    26.          mov     [stackSize],r10
    27.          shr     r10,10        ; ....Kbyte
    28.          mov     r11,r10
    29.          shr     r11,2         ; ....Pages
    30.  
    31.         cinvoke  printf,<10,' System info ====',\
    32.                          10,'   Stack Limit...: 0x%08llx',\
    33.                          10,'   Stack Rsp.....: 0x%08llx',\
    34.                          10,'   Stack Base....: 0x%08llx',\
    35.                          10,'   Stack Size....: 0x%08llx = %d Kb = %d pages',10,0>,\
    36.                          rbx,rsp,rax,[stackSize],r10,r11
    37. ;-------------
    38.          sub     rsp,[stackSize]
    39.          sub     rsp,1000h
    40.  
    41. ;         call    @f           ; для сл.страниц нужна уже запись в стек,
    42. ;@@:      sub     rsp,1000h    ; ...иначе #AV
    43.  
    44.          call    @f      ;<----- Обновить записи в ТЕВ
    45. @@:      mov     rax,[gs:08h]  ; StackBase
    46.          mov     rbx,[gs:10h]  ; StackLimit
    47.          mov     r10,rax
    48.          sub     r10,rbx       ; StackSize
    49.          mov     [stackSize],r10
    50.          shr     r10,10        ; ....Kbyte
    51.          mov     r11,r10
    52.          shr     r11,2         ; ....Pages
    53.  
    54.         cinvoke  printf,<10,' sub  rsp,[stackSize] <------',\
    55.                          10,' sub  rsp,1000h',10,\
    56.                          10,' System info ====',\
    57.                          10,'   Stack Limit...: 0x%08llx',\
    58.                          10,'   Stack Rsp.....: 0x%08llx',\
    59.                          10,'   Stack Base....: 0x%08llx',\
    60.                          10,'   Stack Size....: 0x%08llx = %d Kb = %d pages',10,0>,\
    61.                          rbx,rsp,rax,[stackSize],r10,r11
    62.  
    63. @exit:  cinvoke  _getch
    64.         cinvoke  exit, 0
    65. ;//-----------
    66. section '.idata' import data readable
    67. library  msvcrt,'msvcrt.dll'
    68. include 'api\msvcrt.inc'

    stack1.png

    Ради интереса я увеличил в РЕ-хидере лимит/комит в 16 раз (с дефолтных 0x1000 на 0x10000), и получил такую картину:

    stack2.png
     

    Вложения:

    • StackInfo.zip
      Размер файла:
      735 байт
      Просмотров:
      364
    CyberRSR нравится это.
  15. Ahimov

    Ahimov Member

    Публикаций:
    0
    Регистрация:
    14 окт 2024
    Сообщения:
    40
    Marylin

    Можно размер глобально задать "MinimumStackCommitInBytes" :)
     
  16. Marylin

    Marylin Active Member

    Публикаций:
    0
    Регистрация:
    17 фев 2023
    Сообщения:
    196
    ..может быть, но в дефолте у меня стоит именно 256К.