Page 1 of 2

Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Sun Jun 24, 2018 1:08 am
by floppy121
После того как пользователь пообщался в IRCC (чат клиент) и вышел из него, логи чата и личных сообщений из области данных программы - могут остаться в оперативной памяти, а это угроза безопасности! Поэтому нужно вставить в код обработки нажатия крестика в верхней панели функцию стирания области данных. У меня уже есть функция которая принимает на вход два аргумента: адрес (откуда стирать) и размер (сколько стирать). Но как узнать эти значения?

Очень важно правильно определить начало области данных, но этого недостаточно: если мы укажем слишком маленький размер то сотрём не всё, а если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Sun Jun 24, 2018 8:38 am
by Ray
Если ты внутри программы, то ты и так знаешь буфер и его размер, если вне её то ничего сделать не сможешь из-за защиты страниц (получить исключение #PF).

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Sun Jun 24, 2018 12:28 pm
by 0CodErr
Не совсем понимаю сути проблемы, но в любом случае, это не задача самого процесса.
Ведь процесс можно прибить, ничего ему не сказав, безо всякого "нажатия крестика" — через диспетчер задач.

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Sun Jun 24, 2018 1:16 pm
by floppy121
0CodErr wrote:Не совсем понимаю сути проблемы
я ищу способ получить адрес начала области данных и её размер каким-то универсальным способом вроде системного вызова, который не будет зависеть от внутреннего устройства конкретной программы
0CodErr wrote:это не задача самого процесса.
Ведь процесс можно прибить, ничего ему не сказав, безо всякого "нажатия крестика" - через диспетчер задач.
Когда юзер закроет программу таким способом, будет сам виноват что его чат остался в оперативке :wink: Моя цель - обеспечить безопасность юзера когда он правильно выходит из программы
Ray wrote:Если ты внутри программы, то ты и так знаешь буфер и его размер, если вне её то ничего сделать не сможешь из-за защиты страниц (получить исключение #PF).
Если я нахожусь внутри программы, как определить адрес области данных и весь её размер? Просто если я буду очищать только конкретный буфер - то могу что-то упустить из виду: например неправильно определить его размеры и стереть не всё, или не заметить второй небольшой буфер который промежуточно где-то используется и содержит небольшие фрагменты чата

Поэтому я и ищу универсальный способ просто стереть всю область данных. А для этого мне нужно правильно определить её адрес и размер. Должен же быть какой-то способ получить эти значения? Начало и конец области данных как-то помечаются в оперативке, может быть специальными заголовками?

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jun 28, 2018 9:33 pm
by GerdtR
Такое, наверное, только через драйвер реализовать можно. Фишка в том, что сначала прога получает кусок оперативы в границах от 0 до цифры указанной в заголовке проги. Дальше прога может вызвать ф68.12 и она будет выделен уже после памяти проги, причём через промежуток. Ну то есть виртуальное пространство проги будет что-то вроде: 0..4000h, 5000h..6000h. Если взять цифру из ф9 с инфой о потраченой опервативе, и зачистить с 0 по эту цифру... то вывалится в эксэпшн. А узнать, какие именно страницы выделены проге можно только от ядра. Так что гляди в сторону ядра. Реализовать реально, но несколько сложновато.
"если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс" - это точно не светит. Попытка писать в закрытую область убивает процесс.

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Fri Jun 29, 2018 12:11 pm
by tsdima
GerdtR wrote:Такое, наверное, только через драйвер реализовать можно.
Это не решит проблему, когда программа убивается диспетчером задач. Как вариант - хранить данные зашифрованными, расшифровывать маленькими кусочками, выводить на экран и тут-же обнулять область памяти с расшифрованными данными.

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Sat Jun 30, 2018 9:24 am
by 0CodErr
GerdtR wrote:"если слишком большой - выйдем за пределы области данных и можем повредить соседний процесс" - это точно не светит.
Кстати, да, не можем: каждый процесс выполняется в своём адресном пространстве.
tsdima wrote:GerdtR писал(а):
Такое, наверное, только через драйвер реализовать можно.

Это не решит проблему, когда программа убивается диспетчером задач.
Действительно, не решит.
Но можно попытаться без драйвера обойтись(хотя всё равно так делать не рационально).
Можно попробовать вариант с SysFn68.24:SetExceptionHandler, у Page-Fault Exception (#PF) номер 14.
Сам я не использовал ни разу эту функцию, просто предположу:
  • Пройтись по каждой странице адресного пространства и попробовать обратиться(читать\писать).
    Если #PF не возникло, то эта страница в данный момент выделена.
    Но страницы могли быть освобождены во время работы ещё до выхода.
    Если только сделать свою HeapFree, делающую что-то до вызова системной HeapFree.
Но самое логичное решение: если нужны указатели и размеры областей — нужно хранить эту информацию в программе и обращаться к ней по мере необходимости.
floppy121 wrote:Если я нахожусь внутри программы, как определить адрес области данных и весь её размер?
Размер выделенной области кратен размеру страницы.
В справке так и написано:
Функция выделяет целое число страниц (4 Кб)
А указатель возвращает системная функция при выделении памяти — просто сохраняй этот указатель для дальнейшего использования.

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

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Mon Jul 02, 2018 10:28 am
by 0CodErr
floppy121 wrote:Если я нахожусь внутри программы, как определить адрес области данных и весь её размер?
0CodErr wrote:Но самое логичное решение: если нужны указатели и размеры областей — нужно хранить эту информацию в программе и обращаться к ней по мере необходимости.
Вот правильное решение, то, что я имел в виду: http://websvn.kolibrios.org/filedetails ... e-368[code]; Erase RAM areas which could contain the connection details
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]

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Wed Jul 04, 2018 12:50 am
by Siemargl
ОСистема заботится о стирании и недоступности данных из других/новых процессов. Тема бесполезна.

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Wed Jul 04, 2018 7:20 pm
by floppy121
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 для любой области памяти она заполнялась нулями перед освобождением,
но боюсь такой вариант не примут в "официальные исходники", а число "локальных модов" не хочется увеличивать

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jul 05, 2018 10:09 am
by 0CodErr
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]        
.................................................
testmem.7z (1.09 KiB)
Downloaded 416 times

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jul 05, 2018 7:51 pm
by Siemargl

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jul 05, 2018 8:21 pm
by 0CodErr
Siemargl wrote:Serge писал
А ты сам не в состоянии исходник посмотреть? :lol:

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
Ну и см. пример выше http://board.kolibrios.org/viewtopic.php?p=70878#p70878

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jul 05, 2018 9:38 pm
by 0CodErr
Похоже проблема только с выделением .bss, а HeapAlloc вроде отрабатывает.
Хмм... а какую конкретно помять имел в виду Serge?
Serge wrote:память, выделяемую для приложения

Re: Узнать начало/размер области данных программы, чтобы всё стереть при выходе из неё?

Posted: Thu Jul 05, 2018 11:48 pm
by floppy121
Siemargl wrote:ОСистема заботится о стирании и недоступности данных из других/новых процессов
Если бы это было действительно так, то в дампе памяти виртуальной машины, снятой после закрытия приложения IRCC, я бы ничего не обнаружил (и этой темы бы не было). Но к сожалению там осталось по крайней мере три буфера, а это значит: после закрытия IRCC система не стала занулять память освобождённую IRCC, а просто пометила её страницы как доступные для использования новыми процессами