0

I'm writing an application that encrypts its data. It can then display it unencrypted using the app's UI after a user enters password. My goal is to minimize exposure of plaintext data while in RAM. For that I want to prevent swapping it to disk as much as possible.

I know that I can adjust my process's working set (by calling SetProcessWorkingSetSize API) and then lock those sensitive pages in RAM (by calling VirtualLock.) That, in theory, should minimize the chances of it being written to disk.

The question I have is, can I do the same with the memory that is used by the common controls in my dialog window, namely in Edit boxes, combo boxes, and most importantly RichEdit control?

PS. I'm assuming that they all use data from the heap for my process. Correct?

EDIT: Seeing all the comments below I need to clarify. By saying "lock", I don't mean, "lock it with a padlock and key so that no one can see it." I meant, lock it as with the VirtualLock API.

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • The attackers aren't going to hunt for this on the disk. They can just read it out of memory. – David Heffernan May 20 '17 at 16:57
  • @DavidHeffernan: I'm not asking for that. – c00000fd May 20 '17 at 16:59
  • Have you hired a white hat to attack your app? – David Heffernan May 20 '17 at 17:02
  • @DavidHeffernan: The app that hasn't been written yet. Did you have your coffee today? – c00000fd May 20 '17 at 17:02
  • Great. Now is the perfect time to get some expert help in so that you have confidence that you design it right. – David Heffernan May 20 '17 at 17:08
  • 1
    now yes - all common controls allocate memory from heap. even more concrete from this - `GetProcessHeap` heap. heap is only several blocks of memory allocated by `VirtualAlloc`. all it can be enumerated via `HeapWalk` and lock. another question - are this really have sense. but this formally possible – RbMm May 20 '17 at 17:10
  • @RbMm: Good info. Thank you. Can I ask, where are you taking this information from? And again -- **I AM NOT** trying to protect against malicious process "piping into" my running app. In despite of the condescending remarks above, I understand that that is impossible to do (on a Windows platform.) – c00000fd May 20 '17 at 17:13
  • that common controls allocate memory from main process heap - primary from my experience - this is not documented and not guarantee - but from where, if not from heap ? about concrete edit control - look [`EM_GETHANDLE`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb761576(v=vs.85).aspx) - this prove that edit control allocate own buffer from main process heap - `LocalLock` worked only with memory allocated by `LocalAlloc` which always allocated only from main process heap. that heap memory allocated by `VirtualAlloc` this already 100%. – RbMm May 20 '17 at 17:23
  • @RbMm: Yeah, I see your point. Thanks. Obviously all user-mode memory allocations boil down to using `VirtualAlloc` (or `ZwAllocateVirtualMemory` or whatever it's called.) So, yeah, I guess if I periodically `HeapLock` from a worker thread, then do `HeapWalk` and quickly collect all virtual memory pages used, then `HeapUnlock` and then call `VirtualLock` on the result. That should hypothetically do the job, hah? – c00000fd May 20 '17 at 17:33
  • 1
    [this](https://pastebin.com/nYPqc91t) code enumerate all heap blocks allocated by `VirtualAlloc` on current time – RbMm May 20 '17 at 19:22
  • @RbMm: Hey, sorry for the delay. I just got to reviewing your code, but I'm struggling to understand what exactly you're doing there. For instance, why are you calling `VirtualQuery` twice on a `PROCESS_HEAP_REGION` block, first with `Entry.lpData` and then with `mbi.AllocationBase`? – c00000fd May 30 '17 at 03:12
  • @c00000fd - yes, this is my mistake here. in general *AllocationBase != BaseAddress* in case this [code](https://pastebin.com/m43bjNDA) need single *VirtualQuery* only – RbMm May 30 '17 at 07:28
  • @RbMm: I implemented your suggestions. Although ran into a new issue. Can you [take a look](https://stackoverflow.com/q/44316994/843732)? – c00000fd Jun 01 '17 at 21:01

2 Answers2

2

You can use EM_SETHANDLE to set a handle for an edit control's initial allocation, then respond to EN_ERRSPACE when (if) it runs out of space and needs more.

From there, it's up to you to also use VirtualLock on that block of memory to keep it in RAM as much as possible. If you're going to do this a lot, you probably want to consider superclassing the control(s) to keep from duplicating the code everywhere.

For better or worse, I don't believe there's an equivalent for rich text controls though.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • Hmm. Interesting. I didn't know that such style existed. I'm [reading though](https://msdn.microsoft.com/en-us/library/windows/desktop/ff729172(v=vs.85).aspx), "Applies to 16-bit applications only." Also what about RichEdit? Can you clarify. – c00000fd May 20 '17 at 17:46
  • The reference to DS_LOCALEDIT was probably misplaced--a reflection of my advanced age, I'm afraid. – Jerry Coffin May 20 '17 at 18:02
  • `DS_LOCALEDIT` really was need very many years ago for 16-bit app. now always edit allocated memory from main process heap – RbMm May 20 '17 at 18:06
  • `EN_ERRSPACE` here not useful. it called when *edit control cannot allocate enough memory* - so process out of memory. when text length in edit control is changed and need new buffer - edit simply call `LocalReAlloc` without any notify parent window – RbMm May 20 '17 at 18:12
  • @RbMm: Yes and no. Yes, it can and will reallocate--but if you've given it a handle to a heap that you created with `HeapCreate`, then you set the maximum size for the heap, and when/if it runs out of space, it's up to you to create a large heap and give it a handle into the new heap (at least that seems like how it *should* work--I haven't tested to be sure, at least not recently). – Jerry Coffin May 20 '17 at 18:17
  • *but if you've given it a handle to a heap that you created with HeapCreate* - how ? `EM_SETHANDLE` set address of memory block but not of heap. edit control always worked with `LocalAlloc`, `LocalFree`, `LocalRealloc` functions (this i view under debugger) - it worked only with main process heap. if you pass him block from another heap - `LocalReallock` raise exception (checked) – RbMm May 20 '17 at 18:40
  • @RbMm: You know, if you write up your proposed `HeapWalk` implementation, that may be a better solution. I'm trying to throw in a test code myself now. To see if it works. – c00000fd May 20 '17 at 18:44
0

There is actually a native windows API to help minimize the exposure of crucial items like passwords to memory scraping.

See CryptProtectMemory as a starting point.

Chris Becke
  • 34,244
  • 12
  • 79
  • 148
  • Well, Chris, how would I made an edit box use it, c'mon. I can use it myself to store PBKDF hash. That's true. – c00000fd May 20 '17 at 17:00
  • I don't think you can. The API makes it clear that its intended use is to minimize the exposure of sensitive data, not lock it totally. It is not an end-to-end solution. – Chris Becke May 20 '17 at 17:06
  • That API is to "scramble" my own data. For instance, like I said, I use it to store `PBKDF2` hash while in memory. That works only for the data that you control. Like that hash. – c00000fd May 20 '17 at 17:10
  • You are showing the data on the screen. Any attacker that can read memory or your disk can also see your screen. – David Heffernan May 20 '17 at 17:11
  • @DavidHeffernan: I'm talking about not exposing a user password. And not the data on the screen. – c00000fd May 20 '17 at 17:13
  • Unless you are writing a tool like last pass you don't store passwords – David Heffernan May 20 '17 at 17:16
  • 1
    and if you are getting into storing passwords territory, instead of rolling your own, you should be using the Credentials Management API (https://msdn.microsoft.com/en-us/library/windows/desktop/aa374791(v=vs.85).aspx) – Chris Becke May 20 '17 at 17:21
  • Chris, I appreciate your tidbits of wisdom, but what does this all have to do with the question that I'm asking? – c00000fd May 20 '17 at 17:35
  • It was my recollection that, when I read the CryptProtectMemory docs many years ago, that a section dealt with best practices, around, e.g. how to minimise the chance that sensitive data would be paged out. – Chris Becke May 21 '17 at 06:09