После того как пользователь пообщался в IRCC (чат клиент) и вышел из него, логи чата и личных сообщений из области данных программы - могут остаться в оперативной памяти, а это угроза безопасности! Поэтому нужно вставить в код обработки нажатия крестика в верхней панели функцию стирания области данных. У меня уже есть функция которая принимает на вход два аргумента: адрес (откуда стирать) и размер (сколько стирать). Но как узнать эти значения?
Очень важно правильно определить начало области данных, но этого недостаточно: если мы укажем слишком маленький размер то сотрём не всё, а если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс
Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?
Если ты внутри программы, то ты и так знаешь буфер и его размер, если вне её то ничего сделать не сможешь из-за защиты страниц (получить исключение #PF).
Не совсем понимаю сути проблемы, но в любом случае, это не задача самого процесса.
Ведь процесс можно прибить, ничего ему не сказав, безо всякого "нажатия крестика" — через диспетчер задач.
Ведь процесс можно прибить, ничего ему не сказав, безо всякого "нажатия крестика" — через диспетчер задач.
я ищу способ получить адрес начала области данных и её размер каким-то универсальным способом вроде системного вызова, который не будет зависеть от внутреннего устройства конкретной программы0CodErr wrote:Не совсем понимаю сути проблемы
Когда юзер закроет программу таким способом, будет сам виноват что его чат остался в оперативке Моя цель - обеспечить безопасность юзера когда он правильно выходит из программы0CodErr wrote:это не задача самого процесса.
Ведь процесс можно прибить, ничего ему не сказав, безо всякого "нажатия крестика" - через диспетчер задач.
Если я нахожусь внутри программы, как определить адрес области данных и весь её размер? Просто если я буду очищать только конкретный буфер - то могу что-то упустить из виду: например неправильно определить его размеры и стереть не всё, или не заметить второй небольшой буфер который промежуточно где-то используется и содержит небольшие фрагменты чатаRay wrote:Если ты внутри программы, то ты и так знаешь буфер и его размер, если вне её то ничего сделать не сможешь из-за защиты страниц (получить исключение #PF).
Поэтому я и ищу универсальный способ просто стереть всю область данных. А для этого мне нужно правильно определить её адрес и размер. Должен же быть какой-то способ получить эти значения? Начало и конец области данных как-то помечаются в оперативке, может быть специальными заголовками?
Такое, наверное, только через драйвер реализовать можно. Фишка в том, что сначала прога получает кусок оперативы в границах от 0 до цифры указанной в заголовке проги. Дальше прога может вызвать ф68.12 и она будет выделен уже после памяти проги, причём через промежуток. Ну то есть виртуальное пространство проги будет что-то вроде: 0..4000h, 5000h..6000h. Если взять цифру из ф9 с инфой о потраченой опервативе, и зачистить с 0 по эту цифру... то вывалится в эксэпшн. А узнать, какие именно страницы выделены проге можно только от ядра. Так что гляди в сторону ядра. Реализовать реально, но несколько сложновато.
"если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс" - это точно не светит. Попытка писать в закрытую область убивает процесс.
"если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс" - это точно не светит. Попытка писать в закрытую область убивает процесс.
Чем больше сыра, тем больше в нём дыр. Чем больше дыр, тем меньше в нём собственно сыра. Значит, чем больше сыра, тем меньше сыра!
Это не решит проблему, когда программа убивается диспетчером задач. Как вариант - хранить данные зашифрованными, расшифровывать маленькими кусочками, выводить на экран и тут-же обнулять область памяти с расшифрованными данными.GerdtR wrote:Такое, наверное, только через драйвер реализовать можно.
Кстати, да, не можем: каждый процесс выполняется в своём адресном пространстве.GerdtR wrote:"если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс" - это точно не светит.
Действительно, не решит.tsdima wrote:GerdtR писал(а):
Такое, наверное, только через драйвер реализовать можно.
Это не решит проблему, когда программа убивается диспетчером задач.
Но можно попытаться без драйвера обойтись(хотя всё равно так делать не рационально).
Можно попробовать вариант с SysFn68.24:SetExceptionHandler, у Page-Fault Exception (#PF) номер 14.
Сам я не использовал ни разу эту функцию, просто предположу:
- Пройтись по каждой странице адресного пространства и попробовать обратиться(читать\писать).
Если #PF не возникло, то эта страница в данный момент выделена.
Но страницы могли быть освобождены во время работы ещё до выхода.
Если только сделать свою HeapFree, делающую что-то до вызова системной HeapFree.
Размер выделенной области кратен размеру страницы.floppy121 wrote:Если я нахожусь внутри программы, как определить адрес области данных и весь её размер?
В справке так и написано:
А указатель возвращает системная функция при выделении памяти — просто сохраняй этот указатель для дальнейшего использования.Функция выделяет целое число страниц (4 Кб)
Ещё один не менее тупой способ:
- попытаться освободить каждую страницу адресного пространства(кроме области кода, ещё каких-либо нужных для продолжения работы данных)
а затем выделить один большой кусок и делать с ним, что хочешь
floppy121 wrote:Если я нахожусь внутри программы, как определить адрес области данных и весь её размер?
Вот правильное решение, то, что я имел в виду: http://websvn.kolibrios.org/filedetails ... e-368[code]; Erase RAM areas which could contain the connection details0CodErr wrote:Но самое логичное решение: если нужны указатели и размеры областей — нужно хранить эту информацию в программе и обращаться к ней по мере необходимости.
xor eax, eax
mov edi, irc_server_name
mov ecx, MAX_SERVER_NAME
rep stosb
mov edi, user_nick
mov ecx, MAX_NICK_LEN
rep stosb
mov edi, user_real_name
mov ecx, MAX_REAL_LEN
rep stosb
mov edi, sockaddr1
mov ecx, SOCKADDR1_SIZE
rep stosb[/code]
ОСистема заботится о стирании и недоступности данных из других/новых процессов. Тема бесполезна.
Да, это единственное решение которое пока работает: вручную искать все места в оперативке где могло что-то остаться,0CodErr wrote:Вот правильное решение, то, что я имел в виду: http://websvn.kolibrios.org/filedetails ... 0#line-368
и заполнять их нулями до того как программа высвободит память обратно в ОС. Полного успеха мы пока не добились:
осталось как минимум три буфера где остались важные данные, про это написал в WARNING здесь - viewtopic.php?f=11&p=70875
Возможно, проще было бы модифицировать код системной функции 68 - http://wiki.kolibrios.org/wiki/SysFn68/ru
- чтобы при вызове mcall 68, 13 для любой области памяти она заполнялась нулями перед освобождением,
но боюсь такой вариант не примут в "официальные исходники", а число "локальных модов" не хочется увеличивать
Прежде, чем чесать своим языком, стоило заглянуть в код ядра и убедиться, что никто ничего не стирает.Siemargl wrote:ОСистема заботится о стирании и недоступности данных из других/новых процессов. Тема бесполезна.
А потому что зачем?
Кому надо(приложению) — тот и обнуляет память.
А для тех, у кого всё-таки есть желание разбираться с кодом, вот тестовый пример, суть вот в этом месте:
Code: Select all
.................................................
szAllZero db "All Zero",0
szSomeNotZero db "Some Not Zero",0
Result dd szAllZero
.................................................
SECTION .bss
MemoryBuffer resb 1024 * 1024 * 1024
.end:
.................................................
mov edi, MemoryBuffer
mov ecx, MemoryBuffer.end - MemoryBuffer
xor eax, eax
repe scasb
je .ok
mov Dword [Result], szSomeNotZero
.ok:
push Dword [Result]
call [con_write_asciiz]
.................................................
А ты сам не в состоянии исходник посмотреть?Siemargl wrote:Serge писал
Code: Select all
f68:
..............................................
.12:
stdcall user_alloc, ecx
mov [esp+SYSCALL_STACK._eax], eax
ret
..............................................
proc user_alloc stdcall, alloc_size:dword
push ebx esi edi
mov ebx, [current_process]
lea ecx, [ebx+PROC.heap_lock]
call mutex_lock
mov ecx, [alloc_size]
add ecx, (4095+PAGE_SIZE)
and ecx, not 4095
mov esi, dword [ebx+PROC.heap_base] ; heap_base
mov edi, dword [ebx+PROC.heap_top] ; heap_top
.scan:
cmp esi, edi
jae .m_exit
mov ebx, esi
shr ebx, 12
mov eax, [page_tabs+ebx*4]
test al, FREE_BLOCK
jz .test_used
and eax, 0xFFFFF000
cmp eax, ecx ;alloc_size
jb .m_next
jz @f
lea edx, [esi+ecx]
sub eax, ecx
or al, FREE_BLOCK
shr edx, 12
mov [page_tabs+edx*4], eax
@@:
or ecx, USED_BLOCK
mov [page_tabs+ebx*4], ecx
shr ecx, 12
inc ebx
dec ecx
jz .no
@@:
mov dword [page_tabs+ebx*4], 2
inc ebx
dec ecx
jnz @B
.no:
mov edx, [current_process]
mov ebx, [alloc_size]
add ebx, 0xFFF
and ebx, not 0xFFF
add [edx+PROC.mem_used], ebx
lea ecx, [edx+PROC.heap_lock]
call mutex_unlock
lea eax, [esi+4096]
pop edi
pop esi
pop ebx
ret
.test_used:
test al, USED_BLOCK
jz .m_exit
and eax, 0xFFFFF000
.m_next:
add esi, eax
jmp .scan
.m_exit:
mov ecx, [current_process]
lea ecx, [ecx+PROC.heap_lock]
call mutex_unlock
xor eax, eax
pop edi
pop esi
pop ebx
ret
endp
Похоже проблема только с выделением .bss, а HeapAlloc вроде отрабатывает.
Хмм... а какую конкретно помять имел в виду Serge?
Хмм... а какую конкретно помять имел в виду Serge?
Serge wrote:память, выделяемую для приложения
Если бы это было действительно так, то в дампе памяти виртуальной машины, снятой после закрытия приложения IRCC, я бы ничего не обнаружил (и этой темы бы не было). Но к сожалению там осталось по крайней мере три буфера, а это значит: после закрытия IRCC система не стала занулять память освобождённую IRCC, а просто пометила её страницы как доступные для использования новыми процессамиSiemargl wrote:ОСистема заботится о стирании и недоступности данных из других/новых процессов
Who is online
Users browsing this forum: No registered users and 10 guests