Burning strings lazarus / 31-LCL ---------------------------------------------------------------------- JohnnieK · 2020-11-16 14:01 Hi I am busy developing a TOTP app and in order to keep people from dumping the application memory and getting to the TOTP values, I need to burn all strings when I don't use them anymore. This is done by just overwriting the strings with random characters before disposing of the varialble. Unfortunately the LCL keeps the input values for inputbox in a string somewhere so it stays visible in the memory dump. I was wondering if there is a single place in the source code of the underlying objects that I can add the burn code to, so that all strings will be securely disposed of. Thanx ---------------------------------------------------------------------- marcov · 2020-11-16 15:00 *UNTESTED* My guess would be to go to rtl/inc/astrings.inc and make the last part of fpc_ansistr_decr_ref look a little bit something like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  If declocked(p^.ref) then  begin      if p^.len>0 then        fillchar(s[1],p^.len,#0);      FreeMem(p);  end;  and possibly something similar for wide/unicdestrings.  Shortstring will be impossible, since as they are static arrays, there is no finalization for them. There is some minor internal RTL use, but not that much, so that might not be a problem. And then recompile everything (FPC and lazarus) since this is unit system and everything depends on that. There of course will be a performance penalty, but for non performance apps not too bad I hope. ---------------------------------------------------------------------- Martin_fr · 2020-11-16 17:33 Write your own MemMananger? Like Heaptrc. (Actually you can probably forward most calls to an existing mem manager) Any mem get freed (incl any string) and you can overwrite it. This  should also allow to catch mem-realloc => in case the string grows. --- Note: The OS may allocate memory and hold data belonging to TEdit. => that memory will not be cleared. If you want to be sure of that too, then use a custom-drawn input. ---------------------------------------------------------------------- marcov · 2020-11-16 17:39 Quote from: Martin_fr on November 16, 2020, 06:33:25 pmWrite your own MemMananger? Like Heaptrc. That would NIL all allocations, not just strings. More performance impact, but also more secure since possible buffers are also nilled. But any zeroing strategy relies on that no unnecessary strings (or buffers containing them) are kept alive, e.g. setting fields that are no longer needed to '' etc, zeroing static buffers, and setlength()ing old buffers. QuoteThis  should also allow to catch mem-realloc => in case the string grows. If reallocing a string allocates a new string, decref is called on the old one. astrings.inc:808 in trunk QuoteNote: The OS may allocate memory and hold data belonging to TEdit. => that memory will not be cleared. If you want to be sure of that too, then use a custom-drawn input. Yes, strings might exist in OS/widget structures too. P.s. I'm not really a programmer with security aspirations or experience. This is just what I can think of quickly ---------------------------------------------------------------------- ASerge · 2020-11-16 18:17 Quote from: Martin_fr on November 16, 2020, 06:33:25 pmWrite your own MemMananger? This may not help. Made an example (under Windows). Exe without debugging information, runs without a debugger. However, the dump contains the string. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit uBurnMemManager; {$mode objfpc}{$H+} interface implementation var  OldMM: TMemoryManager; function BurnFreeMem(P: Pointer): PtrUInt;begin  if Assigned(P) then    FillChar(P^, OldMM.MemSize(P), 0);  Result := OldMM.Freemem(P);end; procedure InitBurnMemManager;var  NewMM: TMemoryManager;begin  GetMemoryManager(OldMM);  NewMM := OldMM;  NewMM.Freemem := @BurnFreeMem;  SetMemoryManager(NewMM);end; initialization  InitBurnMemManager;end. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i {$MODE OBJFPC}{$LONGSTRINGS ON}{$APPTYPE CONSOLE} uses uBurnMemManager; procedure Test;var  S: string;begin  S := StringOfChar('~', 40);  Writeln(S);end; begin  Writeln('Make program dump and search multiple ~ chars');  Test;  Readln;end. In this case, the answer is obvious - the Writeln procedure contains its own buffer. In a complex program, there may be other "helpers" that store a copy of the string. ---------------------------------------------------------------------- marcov · 2020-11-16 19:36 Quote from: ASerge on November 16, 2020, 07:17:59 pmIn this case, the answer is obvious - the Writeln procedure contains its own buffer. In a complex program, there may be other "helpers" that store a copy of the string. This is normal. A temp in the mainprogram  is essentially a global and thus alive for possibly the whole program. But in most lazarus gui programs, the main program is minimal, so I think this is an exception