Сейчас на форуме: tyns777, JustLife, zds, 2nd, morgot, Rio, CDK123, tihiy_grom (+4 невидимых)

 eXeL@B —› Программирование —› Как программно увеличить размер уже выделенной области памяти
Посл.ответ Сообщение

Ранг: 329.6 (мудрец), 192thx
Активность: 0.140.01
Статус: Участник

Создано: 16 февраля 2009 16:20 · Поправил: vnekrilov
· Личное сообщение · #1

Вопрос для знающих. При загрузке программы в память машины, с помощью функции VirtualAlloc выделяется какая-то область памяти (например, по адресу 00F10000, и размером - 1000h байтов). Эта область имеет доступ - чтение, запись и исполнение (RWE). Нужно увеличить размер этой области памяти, например, до 3000h байтов. Подскажите, как это можно программно сделать?



Ранг: 301.4 (мудрец), 194thx
Активность: 0.170.01
Статус: Участник

Создано: 16 февраля 2009 16:53
· Личное сообщение · #2

в стандартном C есть realloc



Ранг: 441.3 (мудрец), 297thx
Активность: 0.410.04
Статус: Участник

Создано: 16 февраля 2009 16:56
· Личное сообщение · #3

vnekrilov
Вроде бы таких API нет. Единственное что приходит на ум - это освободить этот диапазон и выделить новый. Если в нём содержатся какие-то данные - предварительно скопировать их, и после расширения диапазона вставить обратно




Ранг: 260.3 (наставник), 2thx
Активность: 0.120
Статус: Участник
PPC-PROTECT author

Создано: 16 февраля 2009 17:11
· Личное сообщение · #4

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

-----
Пиво, сиськи, транс




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 16 февраля 2009 17:14
· Личное сообщение · #5

> Резервируешь область памяти максимального размера, резервирование не выделяет память, а помечает диапазон адресов как занятый. Это делоется посредством NtAllocateVirtualMemory с флагом MEM_RESERVE.
> При необходимости выделяешь область памяти с помощью тогоже сервиса в зарезервированном регионе, указав флаг MEM_COMMIT.
Для каждой страницы из зарезервированного диапазона адресов MEMORY_BASIC_INFORMATION.AllocationBase будет одинакова.




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 16 февраля 2009 21:51
· Личное сообщение · #6

Пример

Code:
  1. .686
  2. .model flat,stdcall
  3.       option casemap :none   ; case sensitive
  4.       include D:\masm32\include\windows.inc
  5.       include D:\masm32\include\user32.inc
  6.       include D:\masm32\include\kernel32.inc
  7.       includelib D:\masm32\lib\user32.lib
  8.       includelib D:\masm32\lib\kernel32.lib
  9. ; --- удобные ммкросы ---
  10. ; для определения строк по ходу кода
  11. zSTR MACRO MyStr
  12. LOCAL addrMyStr 
  13. .data
  14.   addrMyStr db MyStr, 0
  15. .code
  16. EXITM <offset addrMyStr>
  17. ENDM
  18. ; ---
  19. ; для вызова подпрограмм как функций
  20. FUNC MACRO ListArgs:VARARG
  21.   invoke ListArgs
  22.   EXITM <eax>
  23. ENDM
  24. ; --- Собственно программа ---
  25. .data?
  26.    AddrArray dd ? ; Адрес размещения массива в памяти
  27.    zsResult  dd 1024 dup (?) ; статический массив "для компании к динамическому" ;)
  28. .code
  29. start:
  30.    ; Резервируем 1Гб в адресном пространстве нашего процесса
  31.    mov [AddrArray], FUNC(VirtualAlloc, 0, 1024*1024*1024, MEM_RESERVE, PAGE_READWRITE)
  32.    ; 0 означает, что Win сама определит по какому стартовому адресу разместить
  33.    ; запрашиваемый блок зарезервированных адресов
  34.    
  35.    ; Размещаем в нём 10кБ реальной памяти
  36.    invoke VirtualAlloc, [AddrArray], 10*1024, MEM_COMMIT, PAGE_READWRITE
  37.    ; записываем в неё данные:
  38.    invoke wsprintf, [AddrArray], zSTR('Первый блок данных') 
  39.    ; Увеличиваем размер массива до 10Мб
  40.    invoke VirtualAlloc, [AddrArray], 10*1024*1024, MEM_COMMIT, PAGE_READWRITE
  41.    ; записываем данные за пределы первоначальных 10кБ:
  42.    mov edi, [AddrArray]
  43.    add edi, 50*1024        ; смещение в 50кБ
  44.    invoke wsprintf, edi, zSTR('Второй блок данных') 
  45.    ; Выделяем "оторванный" кусок реальной памяти в середине зарезервированного адресного пространства
  46.    mov edi, [AddrArray]
  47.    add edi, 500*1024*1024 ; смещение в 500 Мб
  48.    invoke VirtualAlloc, edi, 4*1024, MEM_COMMIT, PAGE_READWRITE
  49.    ; записываем данные в этот кусок памяти:
  50.    invoke wsprintf, edi, zSTR('Демонстрация работы с разреженными массивами') 
  51.    ; Объединяем разрозненные строки для вывода их на экран
  52.    mov edi, [AddrArray]
  53.    mov esi, edi
  54.    add edi, 50*1024        ; смещение в 50кБ
  55.    add esi, 500*1024*1024 ; смещение в 500 Мб
  56.    invoke wsprintf, addr zsResult, zSTR(<'%s', 13, 10, '%s', 13, 10, '%s', 13, 10>), [AddrArray], edi, esi
  57.    
  58.    invoke MessageBox, NULL, addr zsResult, zSTR(<'Я изучаю ассемблер', 21h>), MB_OK
  59.    
  60.    ; Освобождаем ВСЁ адресной пространство
  61.    invoke VirtualFree, [AddrArray], 0, MEM_RELEASE
  62.    
  63.    invoke ExitProcess, NULL
  64. end start


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 16 февраля 2009 22:25 · Поправил: Clerk
· Личное сообщение · #7

mak
Ога, тока ты не показал главного - два смежные(страницы рядом) региона памяти обьеденяются в один, это и есть расширение области памяти
Если автору необходима расширяемая память не большого размера, то оптимально использовать стек - в нём создатся пограничная траница и если происходит к ней обращение ядро автоматически выделит есчо память.




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 16 февраля 2009 22:52
· Личное сообщение · #8

Вопрос стоял не конкретно, поэтому как вариант спокойно

Code:
  1. .686p
  2. .mmx
  3. .model flat,stdcall
  4. option casemap:none
  5. include \masm32\include\ntdll.inc
  6. includelib \masm32\lib\ntdll.lib
  7. include \masm32\include\kernel32.inc
  8. includelib \masm32\lib\kernel32.lib
  9. include \masm32\include\user32.inc
  10. includelib \masm32\lib\user32.lib
  11. .data
  12. szString      db "строка которую нужно изменить",0
  13. szNewString   db "новая строка с той же длиной",0
  14. .code
  15. FindWriteMemory proc uses esi edi ebx ProcessHandle:dword,lpString:dword,lpNewString:dword,lpStringsLen:dwor d
  16.      local ReturnLength:dword
  17.      local SystemInformation:SYSTEM_BASIC_INFORMATION
  18.      local AllocationBase:dword
  19.      local AllocationSize:dword
  20.      local MemoryInformation:MEMORY_BASIC_INFORMATION
  21.      local RegionLenght:dword
  22.        invoke ZwQuerySystemInformation,SystemBasicInformation,addr SystemInformation,sizeof SYSTEM_BASIC_INFORMATION,addr ReturnLength
  23.         .if eax == 0
  24.            mov AllocationSize,1024*2024
  25.            mov AllocationBase,0
  26.            invoke ZwAllocateVirtualMemory,-1,addr AllocationBase,0,addr AllocationSize,MEM_COMMIT,PAGE_READWRITE
  27.             .if eax == 0
  28.                mov edi,AllocationBase
  29. NextRegionMemory:
  30.                invoke ZwQueryVirtualMemory,ProcessHandle,SystemInformation.LowestUserAddress ,MemoryBasicInformation,addr  MemoryInformation,sizeof MEMORY_BASIC_INFORMATION,addr ReturnLength
  31.                 .if eax == 0
  32.                    cmp MemoryInformation.State,MEM_COMMIT or MEM_RESERVE
  33.                    jz NextRegionMemory
  34. NextFragmentMemory:
  35.                    .if MemoryInformation.RegionSize <= 1024*2024
  36.                       mov eax,MemoryInformation.RegionSize
  37.                     .else
  38.                       mov eax,1024*2024
  39.                    .endif
  40.                    mov RegionLenght,eax
  41.                    invoke ZwReadVirtualMemory,ProcessHandle,MemoryInformation.BaseAddress,edi,Re gionLenght,0
  42.                     .if eax == 0
  43.                        mov esi,RegionLenght
  44.                        mov ebx,esi
  45.                     @@:
  46.                        invoke memcmp,edi,lpString,lpStringsLen
  47.                         .if eax == 0
  48.                            mov eax,MemoryInformation.BaseAddress
  49.                            sub eax,RegionLenght
  50.                            add eax,ebx ;определяем адрес
  51.                            invoke ZwWriteVirtualMemory,ProcessHandle,eax,lpNewString,lpStringsLen,0
  52.                         .endif
  53.                        inc edi
  54.                        inc ebx
  55.                        dec esi
  56.                        jnz @B
  57.                     .endif
  58.                    .if MemoryInformation.RegionSize <= 1024*2024
  59.                       mov eax,MemoryInformation.BaseAddress
  60.                       add eax,MemoryInformation.RegionSize
  61.                       mov SystemInformation.LowestUserAddress,eax
  62.                       cmp eax,SystemInformation.HighestUserAddress
  63.                       jc NextRegionMemory
  64.                     .else
  65.                       mov eax,1024*2024
  66.                       sub MemoryInformation.RegionSize,eax
  67.                       add MemoryInformation.BaseAddress,eax
  68.                       jmp NextFragmentMemory
  69.                    .endif
  70.                 .endif
  71.                invoke ZwFreeVirtualMemory,-1,addr AllocationBase,addr AllocationSize,MEM_RELEASE
  72.             .endif
  73.         .endif        
  74.        ret
  75. FindWriteMemory endp
  76. start proc
  77.      local Buffer[1024]:byte
  78.        invoke lstrcpy,addr Buffer,offset szString
  79.        invoke FindWriteMemory,-1,offset szString,offset szNewString,sizeof szString
  80.        invoke MessageBox,0,offset szString,addr Buffer,0
  81.        invoke ExitProcess,0
  82. start endp
  83. end start


-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 17 февраля 2009 00:39
· Личное сообщение · #9

mak
Хоть один кодес нормальный тут увидел, спасибо



Ранг: 329.6 (мудрец), 192thx
Активность: 0.140.01
Статус: Участник

Создано: 17 февраля 2009 08:04
· Личное сообщение · #10

mak пишет:
Вопрос стоял не конкретно, поэтому как вариант спокойно


Уточню вопрос. Имеется такая ситуация. Протектор Asprotect, при запуске программы, создает области памяти, куда помещает украденный код. На эти области памяти имеются прыжки в главной области программы. При восстановлении эмулированных инструкций в этих областях памяти, восстановленные инструкции записываются в конец конкретной области памяти. В некоторых случаях свободного места в конце области памяти - недостаточно. Нужно добавить 500 - 1000 КБ памяти, и все становится ОК. Скрипт, который я пишу для этих целей, должен увеличить размер той области памяти, в которой не хватает свободного места. Сама проверка размера свободного места - тривиальная, но после выполнения этой проверки, если места мало, то его нужно добавить. В предыдущих моих скриптах, там, где не хватало свободного места, я дописывал восстановленные инструкции в последней секции распаковываемого файла, но мне встречаются программы, где не хватает этой 1000h байтов. Пока я это делал так. Находил место в коде Asprotect.dll, где создается область памяти с недостающим размером, и вручную исправлял параметр размера создаваемой области памяти. Однако - это гемморно. Вот почему и возник этот вопрос. Хочется, чтобы все было красиво.




Ранг: 673.3 (! !), 400thx
Активность: 0.40.31
Статус: Участник
CyberMonk

Создано: 17 февраля 2009 15:03
· Личное сообщение · #11

Это другой вопрос тогда , а как ты правил размер ? скриптом самим имеется ввиду вручную ? Если память динамическая , то в какой промежуток создается буффер ? Что приходит на голову так это наверное полностью убирать аллокацию памяти скриптом или пропускать , и алокацию самому делать со своими параметрами , играясь как те вздумается с памятью. Я так пологаю колы в область тоже динамические , поэтому сьедят и твои буфера с памятью. Подставной буфер короче будет. С одной стоороны тож геморойно а с другой ок ..

-----
RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube




Ранг: 255.8 (наставник), 19thx
Активность: 0.150.01
Статус: Участник
vx

Создано: 17 февраля 2009 15:53
· Личное сообщение · #12

> Скрипт, который я пишу для этих целей, должен увеличить размер той области памяти, в которой не хватает свободного места.
Ну так просто выдели страниц скока нужно и всё.



Ранг: 500.5 (!), 8thx
Активность: 0.230
Статус: Участник

Создано: 17 февраля 2009 16:32 · Поправил: Smon
· Личное сообщение · #13

vnekrilov пишет:
Пока я это делал так. Находил место в коде Asprotect.dll, где создается область памяти с недостающим размером, и вручную исправлял параметр размера создаваемой области памяти

Единственное верное решение для этого случая имхо, только искать и править не вручную а скриптом по сигне, расширить по другому уже выделенный аспром регион не выйдет (сам он ничего не резервирует, копирование кода в больший регион и смена значения адреса в переменных аспра тоже вызовет глюки если код не базонезависисимый, поэтому лучшее решение - искать по сигне скриптом ту точку в библиотеке и править её на нужную до выделения. Можно и хук поставить на саму процедуру (если заранее неизвестен нужный размер) после распаковки аспр.длл, можно и просто в 10 раз больше выделять сразу и всё

-----
"Пусть видят, что мы не шутим. Стволы для понта, ножи для дела" Lock, Stock & Two Smoking Barrels




Ранг: 213.5 (наставник)
Активность: 0.120
Статус: Участник
забанен

Создано: 18 февраля 2009 02:10
· Личное сообщение · #14

А можно мне - мну в вопросе сабжа не шаред %)), но..
Smon пишет:
поэтому лучшее решение - искать по сигне скриптом ту точку в библиотеке и править её на нужную до выделения

А че мешает грамотно захучить "по-условию" VirtualAlloc и когда условие становиццо истеным.. – подменить 1000h байтов на 3000h байтов(при передаче параметров), мну лично так и сделал бы тупо с разбегу (в лучших традициях дзена %) вроде как, да универсальность имеецца), а вообще хз может эти олькины скрипты такую задачу и не асилят? Тогда ф топку их нах %))) шучу!
При этом выделять память больше всегда(тут и тривиальные проверки в скрипте уже нах не нужны будут), а потом когда выделилось 3000h байтов просто снимать/килять хук(если больше не нужен) да и фсе..
ЗЫ: К примеру ставим бряк на "волшебную точку" после нее(как сработает) на VirtualAlloc и как только сработает бряк на VirtualAlloc удаляем его и в стеке меняем параметр 1000h на 3000h и далее RUN
И че-то подобное, где-то уже в ахренено здоровой теме по аспру обсуждалось, только там вообще ПЕ заголовок расширить надо было чтоли, если память не изменяет...
Короче как-то так наверное

-----
ЗЫ: истЕна где-то рядом, Welcome@Google.com




Ранг: 500.5 (!), 8thx
Активность: 0.230
Статус: Участник

Создано: 18 февраля 2009 07:53
· Личное сообщение · #15

Demon666 пишет:
А че мешает грамотно захучить "по-условию" VirtualAlloc и когда условие становиццо истеным.. – подменить 1000h байтов на 3000h

Можно еще проще сделать тогда - захучить VA и все 1000h подменять на 3000h без дополнительных проверок

-----
"Пусть видят, что мы не шутим. Стволы для понта, ножи для дела" Lock, Stock & Two Smoking Barrels




Ранг: 329.6 (мудрец), 192thx
Активность: 0.140.01
Статус: Участник

Создано: 18 февраля 2009 09:19 · Поправил: vnekrilov
· Личное сообщение · #16

Demon666 пишет:
VirtualAlloc удаляем его и в стеке меняем параметр 1000h на 3000h и далее RUN


Я кстати так и делал. Только делал это вручную. Кстати, в одной программе у меня было 28 областей памяти со спертыми байтами. Во всех областях хватало свободного места, чтобы записать туда восстановленные инструкции. А вот в одной области памяти - НЕТ. Кроме того, размеры все областей памяти были разными - от 1000h байтов до 6000h байтов. Поэтому все-таки есть резон выполнять проверку свободного места в конце области памяти (оно должно быть примерно 30% от размера этой области памяти), т.е.нужно каждую такую область памяти увеличивать в 1,3 раза. Но дело еще обстоит в том, что протектор создает много разных областей памяти, но для стыренных байтов их всего лишь несколько, остальные такие области памяти создаются для других целей (например, для записи кода подпрограмм, которые извлекают информацию из массивов данных), где увеличивать размер области памяти нет необходимости.



Ранг: 213.5 (наставник)
Активность: 0.120
Статус: Участник
забанен

Создано: 18 февраля 2009 11:42 · Поправил: Demon666
· Личное сообщение · #17

Smon
Если честно, то у моего бота crackrss было в логах
Smon пишет:
Единственное верное решение для этого случая имхо
;)
Хз. остальная часть мессаги где-то в сети потом значит отламилась
Мну написал постенг - когда зашел.. вижу, а у тебя считай что тоже самое написано
Но я все равно, взял да и отпостил ;)

vnekrilov
Но ты же должен понимать что это я так для примера написал ;)
написать можно что хочеццо, а тебе уже потом решать что юзать или вообще не юзать ;)
vnekrilov пишет:
Поэтому все-таки есть резон выполнять проверку свободного места в конце области памяти (оно должно быть примерно 30% от размера этой области памяти), т.е.нужно каждую такую область памяти увеличивать в 1,3 раза

Ну можно просто - узнаем длину выделяемой памяти и умножаем ее на(ну к примеру) 1,5
vnekrilov пишет:
Однако - это гемморно. Вот почему и возник этот вопрос. Хочется, чтобы все было красиво

Хз просто в кодинге(чтобы было красиво) всегда такие весчи заворачивают в тег try и если уже когда конкретно не хватило памяти(произошло исключение), дополнительно ее выделяют в except, finally, etc..
Я хз есть ли у оли механизм обработки исключений, но во всех скриптовых движках, которые я знаю - он присутствует, если нет - то его надо дописывать(если юзаешь часто этот скриптовый двиг)
Механизм обработчика исключений в скриптовом двиге позволяет значительно сократить объемы написания скриптого кодеса(до 50%) и упростить понимание логики скрипта третьим лицам ;) – ИМХО..

-----
ЗЫ: истЕна где-то рядом, Welcome@Google.com




Ранг: 20.8 (новичок), 7thx
Активность: 0.010.02
Статус: Участник

Создано: 18 февраля 2009 13:24
· Личное сообщение · #18

я аспр ломал т.о. - в virtualloc в кернел32.длл вставляется джамп на мой код в библе, котрый эмулировал вызовы virtualloc из аспра, а другие пропускал, и создавал кучу в предварительно добавленной дополнительной секции. при этом весь распакованный и сворованный код уже оказывается в экзешнике )) который дампишь потом и все
При запуске подгружается моя длл, далее вызывается heapcreate, в то месте где HeapCreate вызывает zwallocatevirtualmemory надо подсунуть адрес дополнительной секции
далее вызовы аспром virtualalloc переделываешь в heapalloc


 eXeL@B —› Программирование —› Как программно увеличить размер уже выделенной области памяти
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати