How to check if sound device connected in AutoHotkey script? - audio

I have AutoHotkey script that can switch between multiple sound devices with a single keystroke.
Everything works fine, I am using nircmd utility to activate the device (Set as Default Device)
Run, Tools\nircmd.exe setdefaultsounddevice "%playback%", where %playback% is the actual sound device name.
So my script basically loops through 3 devices (Headset, Speakers, TV) that I have in Sound Panel.
But, when my TV is OFF (Disconnected), it still loops through all 3 devices.
What I need is to be able to check if the device is disconnected in my script.
I couldn't find any command in nircmd that can do that.
Please let me know if you have any ideas.
Thanks.

Surely very doable, but be warned, the code in this answer gets quite advanced.
This is without using any external utilities.
So we're interested in the EnumAudioEndpoints method of the IMMDeviceEnumerator interface.
With this method we can list desired audio devices based on some criteria.
Problem:
How do we make use of such a method in AHK?
By DllCalling it. And to to that, we need its address in memory (pointer), since DllCall is able to call functions/methods by address.
So we start off by getting the IMMDeviceEnumerator interface's pointer.
For that we require its CLSID and in this case also its IID. I found them via a Google Search.
Then we make use of AHK's ComObjCreate function (and to make it even more complicated, yes, we're working with ComObjects)
And as the AHK documention specifies, we do indeed get a pointer instead of an object from the function, because we specified an IID.
CLSID := "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
IID := "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
pDeviceEnumerator := ComObjCreate(CLSID, IID)
Now that we have the pointer to the interface pDeviceEnumerator, we need a pointer to the EnumAudioEndpoints method of the interface.
So that's our next problem.
Firstly we need to understand, that our desired method is the first method of the interface.
But because the interface inherits from IUnknown the interface's first three methods are actually AddRef, QueryInterface, and Release.
Therefore, our desired method of the interface is actually the fourth method of the interface.
Ok, so we want to get the pointer to 4th method of this interface.
To do this, we first want to get the pointer to the interface's virtual table. The vtable contains every method's pointer. And after we have the pointer the the vtable, we can get our desired method's pointer from that vtable.
To get these pointers, we're going to use AHK's NumGet function.
The vtable is usually located at the beginning of the ComObject (at offset 0), so lets NumGet our pDeviceEnumerator pointer at offset 0 to get to the vtable:
vtable := NumGet(pDeviceEnumerator+0)
+0 is specified so AHK doesn't treat the variable pDeviceEnumerator as a ByRef variable, and instead operates at our desired address in memory.
And we're omitting the second and third parameters to use the default values, offset 0 (which is exactly what we want) and also the UPtr type is fine for us.
Now that we have the memory address of the vtable, lets finally get the pointer of the EnumAudioEndpoints method.
Now remember how it's the first (but actually fourth) method in the vtable (offset 3).
So we want to get the address in memory which is offset 3 methods from the vtable's memory address.
And now remember how the vtable contained pointers, so we want to go forward the size of 3 pointers in memory. The size of a pointer is 4 bytes on a 32bit machine, and 8 bytes on a 64bit machine.
So it's pretty safe to say that nowadays the size of a pointer is always 8 bytes, when our program is ran on a modern desktop computer. We can also make use of the built in AHK variable A_PtrSize. It'll contain 4 or 8.
Visual representation of the pointers being stored in the vtable:
vtable offset (bytes)
AddRef 0
QueryInterface 8
Release 16
EnumAudioEndpoints 24
GetDefaultAudioEndpoint 32
GetDevice 40
...
So we want to NumGet at offset 24 bytes:
pEnumAudioEndpoints := NumGet(vtable+0, 3*A_PtrSize)
(Demonstrating the usage of A_PtrSize to make your script compatible on 32bit machines as well, but you could just as well not have that and specify 24)
Ok, phew, now we finally have the pointer to the IMMDeviceEnumerator::EnumAudioEndpoints method, which means we can finally use it.
So the next problem is, how do we use it?
Firstly we need to decide how we want to use it. I can think of two ways we'd want to use it.
The first being list all active & plugged in devices and doing desired stuff with them and ditching the usage of nircmd altogether, and the second being a little simplification that'll work just for your specific case.
I'll demonstrate the second way for you, and if you want to make a proper implementation, you can yourself try to implement the first way. If you run into problems, you can of course ask for help.
So, the second way, the simplification. For this what I thought of, was listing the unplugged devices and if there is one, you'll know what in your specific case the TV is unplugged.
If there isn't one, you'll know that the TV is plugged in.
Ok, so onto using the method.
It expects three arguments:
dataFlow
For this parameter we specify a value from the EDataFlow enum. Our desired value is eRender, which is the first member of the enum, so 0.
dwStateMask
For this we specify desired bitwise flags. We want only unplugged devices, so we'll be fine with just the DEVICE_STATE_UNPLUGGED flag (0x00000008).
**ppDevices
Here we specify a pointer to a variable, which is going to receive the pointer to the memory address where the resulting IMMDeviceCollection interface is located.
And now onto DllCalling. The way to call a method with DllCall is even more AHK magic, you'll hardly even find it from the documentation even, but it's kind of there.
Methods are called on instances, so for the first parameter of the DllCall we'll pass the pointer of the method, which we have stored in pEnumAudioEndpoints, and for the second parameter we want to pass the pointer of the object (instance of interface) we're acting on, which we have stored in pDeviceEnumerator.
After that, we normally pass arguments to the method.
DllCall(pEnumAudioEndpoints, Ptr, pDeviceEnumerator, UInt, 0, UInt, 0x00000008, PtrP, pDeviceCollection)
The syntax of DllCall is Type followed by Argument.
First we pass a pointer, Ptr.
Then we pass two non-negative numbers, the type unsigned integer, UInt, will do fine.
Then we pass a PtrP to pass the pointer of the variable pDeviceCollection.
You'll notice that this variable was never even declared, but that's fine, AHK is such a forgiving language so it'll automatically create the variable for us.
Ok, now the DllCall is all done and we have a pointer to a resulting IMMDeviceCollection interface.
You'll notice how the interface includes two methods, GetCount and Item.
For the simplified way I'm demonstrating for you, we're interested in the GetCount method.
So once again, we'll get the address of that interface's vtable:
vtable := NumGet(pDeviceCollection+0)
And again, we're interested in the first (but actually fourth) method of the interface (offset 3):
pGetCount := NumGet(vtable+0, 3*A_PtrSize)
And then we can already use the method, so lets DllCall again.
And this time the object we're acting upon is IMMDeviceCollection, and we have its pointer stored in the pDeviceCollection variable.
The functions expects just one argument *pcDevices, a pointer to a variable which is going to receive the number of devices there is on our device collection.
DllCall(pGetCount, Ptr, pDeviceCollection, UIntP, DeviceCount)
And there we go, the simplified way is all done.
We successfully received the number of unplugged, but enabled, audio playback devices.
Now at the end when we know we're done with the ComObjects, we should release them (as the documentation specifies). This is necessarily not 100% required, but is definitely good practice, so lets release the ComObjects:
ObjRelease(pDeviceEnumerator)
ObjRelease(pDeviceCollection)
And here's a full example script for the simplified way:
#NoEnv ;unquoted types in DllCall don't hinder performance
CLSID := "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
IID := "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
pDeviceEnumerator := ComObjCreate(CLSID, IID)
vtable := NumGet(pDeviceEnumerator+0)
pEnumAudioEndpoints := NumGet(vtable+0, 3*A_PtrSize)
DllCall(pEnumAudioEndpoints, Ptr, pDeviceEnumerator, UInt, 0, UInt, 0x00000008, PtrP, pDeviceCollection)
vtable := NumGet(pDeviceCollection+0)
pGetCount := NumGet(vtable+0, 3*A_PtrSize)
DllCall(pGetCount, Ptr, pDeviceCollection, UIntP, DeviceCount)
ObjRelease(pDeviceEnumerator)
ObjRelease(pDeviceCollection)
if (DeviceCount = 0)
MsgBox, % "No unplugged, but enabled, devices found`nI'll assume my TV is plugged in and I have three audio devices enabled"
else if (DeviceCount = 1)
MsgBox, % "One unplugged, but enabled, device found`nI'll assume my TV is unplugged and I have only two audio devices enabled"
else
MsgBox, % "There are " DeviceCount "unplugged audio devices"
If this seems like it isvery complex/hard, that's because it kind of is.
I'd say this is almost as complicated as AHK DllCalling gets.
But well, that's the way it is when you don't use an external utility that does all the cool stuff for you.
If you decide to implement the proper solution for handling your audio devices I talked about, this might be a good library you can use, or take reference from. I haven't used it myself, so can't say if some stuff there is outdated.
It's made by Lexikos himself.

Related

Modifying the data of an array vs seq and passing the address of an array vs seq to asyncnet proc `send`

I've been working on a server that expects data to be received through a buffer. I have an object which is defined like this and some procedures that modify the buffer in it:
Packet* = ref object
buf*: seq[int8]
#buf*: array[0..4096, int8]
pos*: int
proc newPacket*(size: int): Packet =
result = Packet(buf: newSeq[int8](size))
#result = Packet()
proc sendPacket*(s: AsyncSocket, p: Packet) =
aSyncCheck s.send(addr(p.buf), p.pos)
Now the reason I have two lines commented is because that was the code I originally used, but creating an object that initialises an array with 4096 elements every time probably wasn't very good for performance. However, it works and the seq[int8] version does not.
The strange thing is though, my current code will work perfectly fine if I use the old static buffer buf*: array[0..4096, int8]. In sendPacket, I have made sure to check the data contained in the buffer to make sure both the array and seq[int8] versions are equal, and they are. (Or at least appear to be). In other words, if I were to do var p = createPacket(17) and write to p.buf with exactly 17 bytes, the values of the elements appear to be the same in both versions.
So despite the data appearing to be the same in both versions, I get a different result when calling send when passing the address of the buffer.
In case it matters, the data would be read like this:
result = p.buf[p.pos]
inc(p.pos)
And written to like this:
p.buf[p.pos] = cast[int8](value)
inc(p.pos)
Just a few things I've looked into, which were probably unrelated to my problem anyway: I looked at GC_ref and GC_unref which had no effect on my problem and also looked at maybe trying to use alloc0 where buf is defined as pointer but I couldn't seem to access the data of that pointer and that probably isn't what I should be doing in the first place. Also if I do var data = p.buf and pass the addr of data instead, I get a different result, but still not the intended one.
So I guess what I want to get to the bottom of is:
Why does send work perfectly fine when I use array[0..4096, int8] but not seq[int8] which is initialised with newSeq, even when they appear to contain the same data?
Does my current layout for receiving and writing data even make sense in a language like Nim (or any language for that matter)? Is there a better way?
In order not to initialize the array you can use the noinit pragma like this:
buf* {.noinit.}: array[0..4096, int8]
You are probably taking the pointer to the seq, not the pointer to the data inside the seq, so try using addr(p.buf[0]).
A pos field is useless if you are using the seq version since you have p.buf.len already, but you probably know that already and just left it in for the array. If you want to use the seq and expect large packets, make sure to use newSeqOfCap to only allocate the memory once.
Also, your array is 1 byte too big, it goes from 0 to 4096 inclusively! Instead you can use [0..4095, int8] or just [4096, int8].
Personally I would prefer to use a uint8 type inside of buf, so that you can just put in values from 0 to 255 instead of -128 to 127
Using a seq inside of a ref object means you have two layers of indirection when accessing buf, as well as two objects that the GC will have to clean up. You could just make Packet an alias for seq[uint8] (without ref): type Packet* = seq[uint8]. Or you can use the array version if you want to store some more data inside the Packet later on.

How to tell compiler to pad a specific amount of bytes on every C function?

I'm trying to practice some live instrumentation and I saw there was a linker option -call-nop=prefix-nop, but it has some restriction as it only works with GOT function (I don't know how to force compiler to generate GOT function, and not sure if it's good idea for performance reason.) Also, -call-nop=* cannot pad more than 1 byte.
Ideally, I'd like to see a compiler option to pad any specific amount of bytes, and compiler will still perform all the normal function alignment.
Once I have this pad area, I can at run time to reuse these padding area to store some values or redirect the control flow.
P.S. I believe Linux kernel use similar trick to dynamically enable some software tracepoint.
-pg is intended for profile-guided optimization. The correct option for this is -fpatchable-function-entry
-fpatchable-function-entry=N[,M]
Generate N NOPs right at the beginning of each function, with the function entry point before the Mth NOP. If M is omitted, it defaults to 0 so the function entry points to the address just at the first NOP. The NOP instructions reserve extra space which can be used to patch in any desired instrumentation at run time, provided that the code segment is writable. The amount of space is controllable indirectly via the number of NOPs; the NOP instruction used corresponds to the instruction emitted by the internal GCC back-end interface gen_nop. This behavior is target-specific and may also depend on the architecture variant and/or other compilation options.
It'll insert N single-byte 0x90 NOPs and doesn't make use of multi-byte NOPs thus performance isn't as good as it should, but you probably don't care about that in this case so the option should work fine
I achieved this goal by implement my own mcount function in an assembly file and compile the code with -pg.

list_empty returns 1 (non zero) if the list is not empty

I am working on Linux Device Driver code. I cant reveal what exactly this code is used for. I will try my best to explain my situation. Below code will be executed in interrupt context when we receive an USB interrupt stating that there is some data from USB. The data will arrive as URB's and we will convert them into chunks, add them to Linux Circular Doubly linked list for further processing.
spin_lock(&demod->demod_lock);
/* Delete node from free list */
list_del(&chunk->list_head);
/* Add it to full list */
list_add_tail(&chunk->list_head,&demod->ChunkRefList.full);
/* Update chunk status */
chunk->status=CHUNKDESC_FULL_LIST;
/* Increment the chunks assigned to application */
demod->stats.assigned.c++;
spin_unlock(&demod->demod_lock);
printk("Value returned by list_empty is %d ",list_empty(&demod->ChunkRefList.full));
I repeat, this code gets executed in interrupt context. I am using this code as a part of embedded system which displays Audio & Video(AV) forever.
After approx 12 hours, the AV is frozen and when I analyse, I see the value of list_empty(&demod->ChunkRefList.full) returned is always 0x1 forever. Usually in working case where AV is playing fine, its value will be 0x0 stating that the list is not empty.
As you can see, when above code gets executed, it first adds a node to the full list and checks if full list is empty. Ideally, the value should be always 0x0. Why its value is 0x1
I am monitoring the value of list_empty(&demod->ChunkRefList.full) using timedoctor applicaiton which doesn't introduce any overhead in interrupt context. I have used printk above to make you understand that I am printing its value.
Finally, I was able to figure out the issue.
Since the code is implemented in interrupt context, using list_del followed by list_add_tail was causing issue.
So, I removed these two macros and introduced list_move_tail macro which resolved the issue.
By using list_move_tail, there is no need for us to remove the node and add it to the new list. The kernel will takecare of both operations.
So, to conclude, its better to make Linux Linked list manipulations as minimal as possible in interrupt context.

Detouring and GCC inline assembly (Linux)

I'm programming extensions for a game which offers an API for (us) modders. This API offers a wide variety of things, but it has one limitation. The API is for the 'engine' only, which means that all modifications (mods) that has been released based on the engine, does not offer/have any sort of (mod specific) API. I have created a 'signature scanner' (note: my plugin is loaded as a shared library, compiled with -share & -fPIC) which finds the functions of interest (which is easy since I'm on linux). So to explain, I'll take a specific case: I have found the address to a function of interest, its function header is very simpleint * InstallRules(void);. It takes a nothing (void) and returns an integer pointer (to an object of my interest). Now, what I want to do, is to create a detour (and remember that I have the start address of the function), to my own function, which I would like to behave something like this:
void MyInstallRules(void)
{
if(PreHook() == block) // <-- First a 'pre' hook which can block the function
return;
int * val = InstallRules(); // <-- Call original function
PostHook(val); // <-- Call post hook, if interest of original functions return value
}
Now here's the deal; I have no experience what so ever about function hooking, and I only have a thin knowledge of inline assembly (AT&T only). The pre-made detour packages on the Internet is only for windows or is using a whole other method (i.e preloads a dll to override the orignal one). So basically; what should I do to get on track? Should I read about call conventions (cdecl in this case) and learn about inline assembly, or what to do? The best would probably be a already functional wrapper class for linux detouring. In the end, I would like something as simple as this:
void * addressToFunction = SigScanner.FindBySig("Signature_ASfs&43"); // I've already done this part
void * original = PatchFunc(addressToFunction, addressToNewFunction); // This replaces the original function with a hook to mine, but returns a pointer to the original function (relocated ofcourse)
// I might wait for my hook to be called or whatever
// ....
// And then unpatch the patched function (optional)
UnpatchFunc(addressToFunction, addressToNewFunction);
I understand that I won't be able to get a completely satisfying answer here, but I would more than appreciate some help with the directions to take, because I am on thin ice here... I have read about detouring but there is barely any documentation at all (specifically for linux), and I guess I want to implement what's known as a 'trampoline' but I can't seem to find a way how to acquire this knowledge.
NOTE: I'm also interested in _thiscall, but from what I've read that isn't so hard to call with GNU calling convention(?)
Is this project to develop a "framework" that will allow others to hook different functions in different binaries? Or is it just that you need to hook this specific program that you have?
First, let's suppose you want the second thing, you just have a function in a binary that you want to hook, programmatically and reliably. The main problem with doing this universally is that doing this reliably is a very tough game, but if you are willing to make some compromises, then it's definitely doable. Also let's assume this is x86 thing.
If you want to hook a function, there are several options how to do it. What Detours does is inline patching. They have a nice overview of how it works in a Research PDF document. The basic idea is that you have a function, e.g.
00E32BCE /$ 8BFF MOV EDI,EDI
00E32BD0 |. 55 PUSH EBP
00E32BD1 |. 8BEC MOV EBP,ESP
00E32BD3 |. 83EC 10 SUB ESP,10
00E32BD6 |. A1 9849E300 MOV EAX,DWORD PTR DS:[E34998]
...
...
Now you replace the beginning of the function with a CALL or JMP to your function and save the original bytes that you overwrote with the patch somewhere:
00E32BCE /$ E9 XXXXXXXX JMP MyHook
00E32BD3 |. 83EC 10 SUB ESP,10
00E32BD6 |. A1 9849E300 MOV EAX,DWORD PTR DS:[E34998]
(Note that I overwrote 5 bytes.) Now your function gets called with the same parameters and same calling convention as the original function. If your function wants to call the original one (but it doesn't have to), you create a "trampoline", that 1) runs the original instructions that were overwritten 2) jmps to the rest of the original function:
Trampoline:
MOV EDI,EDI
PUSH EBP
MOV EBP,ESP
JMP 00E32BD3
And that's it, you just need to construct the trampoline function in runtime by emitting processor instructions. The hard part of this process is to get it working reliably, for any function, for any calling convention and for different OS/platforms. One of the issues is that if the 5 bytes that you want to overwrite ends in a middle of an instruction. To detect "ends of instructions" you would basically need to include a disassembler, because there can be any instruction at the beginning of the function. Or when the function is itself shorter than 5 bytes (a function that always returns 0 can be written as XOR EAX,EAX; RETN which is just 3 bytes).
Most current compilers/assemblers produce a 5-byte long function prolog, exactly for this purpose, hooking. See that MOV EDI, EDI? If you wonder, "why the hell do they move edi to edi? that doesn't do anything!?" you are absolutely correct, but this is the purpose of the prolog, to be exactly 5-bytes long (not ending in a middle of an instruction). Note that the disassembly example is not something I made up, it's calc.exe on Windows Vista.
The rest of the hook implementation is just technical details, but they can bring you many hours of pain, because that's the hardest part. Also the behaviour you described in your question:
void MyInstallRules(void)
{
if(PreHook() == block) // <-- First a 'pre' hook which can block the function
return;
int * val = InstallRules(); // <-- Call original function
PostHook(val); // <-- Call post hook, if interest of original functions return value
}
seems worse than what I described (and what Detours does), for example you might want to "not call the original" but return some different value. Or call the original function twice. Instead, let your hook handler decide whether and where it will call the original function. Also then you don't need two handler functions for a hook.
If you don't have enough knowledge about the technologies you need for this (mostly assembly), or don't know how to do the hooking, I suggest you study what Detours does. Hook your own binary and take a debugger (OllyDbg for example) to see at assembly level what it exactly did, what instructions were placed and where. Also this tutorial might come in handy.
Anyway, if your task is to hook some functions in a specific program, then this is doable and if you have any trouble, just ask here again. Basically you can do a lot of assumptions (like the function prologs or used conventions) that will make your task much easier.
If you want to create some reliable hooking framework, then still is a completely different story and you should first begin by creating simple hooks for some simple apps.
Also note that this technique is not OS specific, it's the same on all x86 platforms, it will work on both Linux and Windows. What is OS specific is that you will probably have to change memory protection of the code ("unlock" it, so you can write to it), which is done with mprotect on Linux and with VirtualProtect on Windows. Also the calling conventions are different, that that's what you can solve by using the correct syntax in your compiler.
Another trouble is "DLL injection" (on Linux it will probably be called "shared library injection" but the term DLL injection is widely known). You need to put your code (that performs the hook) into the program. My suggestion is that if it's possible, just use LD_PRELOAD environment variable, in which you can specify a library that will be loaded into the program just before it's run. This has been described in SO many times, like here: What is the LD_PRELOAD trick?. If you must do this in runtime, I'm afraid you will need to get with gdb or ptrace, which in my opinion is quite hard (at least the ptrace thing) to do. However you can read for example this article on codeproject or this ptrace tutorial.
I also found some nice resources:
SourceHook project, but it seems it's only for virtual functions in C++, but you can always take a look at its source code
this forum thread giving a simple 10-line function to do this "inline hook" that I described
this a little more complex code in a forum
here on SO is some example
Also one other point: This "inline patching" is not the only way to do this. There are even simpler ways, e.g. if the function is virtual or if it's a library exported function, you can skip all the assembly/disassembly/JMP thing and simply replace the pointer to that function (either in the table of virtual functions or in the exported symbols table).

How can I increase memory security in Delphi?

Is it possible to "wipe" strings in Delphi? Let me explain:
I am writing an application that will include a DLL to authorise users. It will read an encrypted file into an XML DOM, use the information there, and then release the DOM.
It is obvious that the unencrypted XML is still sitting in the memory of the DLL, and therefore vulnerable to examination. Now, I'm not going to go overboard in protecting this - the user could create another DLL - but I'd like to take a basic step to preventing user names from sitting in memory for ages. However, I don't think I can easily wipe the memory anyway because of references. If I traverse my DOM (which is a TNativeXML class) and find every string instance and then make it into something like "aaaaa", then will it not actually assign the new string pointer to the DOM reference, and then leave the old string sitting there in memory awaiting re-allocation? Is there a way to be sure I am killing the only and original copy?
Or is there in D2007 a means to tell it to wipe all unused memory from the heap? So I could release the DOM, and then tell it to wipe.
Or should I just get on with my next task and forget this because it is really not worth bothering.
I don't think it is worth bothering with, because if a user can read the memory of the process using the DLL, the same user can also halt the execution at any given point in time. Halting the execution before the memory is wiped will still give the user full access to the unencrypted data.
IMO any user sufficiently interested and able to do what you describe will not be seriously inconvenienced by your DLL wiping the memory.
Two general points about this:
First, this is one of those areas where "if you have to ask, you probably shouldn't be doing this." And please don't take that the wrong way; I mean no disrespect to your programming skills. It's just that writing secure, cryptographically strong software is something that either you're an expert at or you aren't. Very much in the same way that knowing "a little bit of karate" is much more dangerous than knowing no karate at all. There are a number of third-party tools for writing secure software in Delphi which have expert support available; I would strongly encourage anyone without a deep knowledge of cryptographic services in Windows, the mathematical foundations of cryptography, and experience in defeating side channel attacks to use them instead of attempting to "roll their own."
To answer your specific question: The Windows API has a number of functions which are helpful, such as CryptProtectMemory. However, this will bring a false sense of security if you encrypt your memory, but have a hole elsewhere in the system, or expose a side channel. It can be like putting a lock on your door but leaving the window open.
How about something like this?
procedure WipeString(const str: String);
var
i:Integer;
iSize:Integer;
pData:PChar;
begin
iSize := Length(str);
pData := PChar(str);
for i := 0 to 7 do
begin
ZeroMemory(pData, iSize);
FillMemory(pData, iSize, $FF); // 1111 1111
FillMemory(pData, iSize, $AA); // 1010 1010
FillMemory(pData, iSize, $55); // 0101 0101
ZeroMemory(pData, iSize);
end;
end;
DLLs don't own allocated memory, processes do. The memory allocated by your specific process will be discarded once the process terminates, whether the DLL hangs around (because it is in use by another process) or not.
How about decrypting the file to a stream, using a SAX processor instead of an XML DOM to do your verification and then overwriting the decrypted stream before freeing it?
If you use the FastMM memory manager in Full Debug mode, then you can force it to overwrite memory when it is being freed.
Normally that behaviour is used to detect wild pointers, but it can also be used for what your want.
On the other hand, make sure you understand what Craig Stuntz writes: do not write this authentication and authorization stuff yourself, use the underlying operating system whenever possible.
BTW: Hallvard Vassbotn wrote a nice blog about FastMM:
http://hallvards.blogspot.com/2007/05/use-full-fastmm-consider-donating.html
Regards,
Jeroen Pluimers
Messy but you could make a note of the heap size that you've used while you've got the heap filled with sensitive data then when that is released do a GetMem to allocate you a large chunk spanning (say) 200% of that. do a Fill on that chunk and make the assumption that any fragmentation is unlinkely to be of much use to an examiner.
Bri
How about keeping the password as a hash value in the XML and verify by comparing the hash of the input password with the hashed password in your XML.
Edit: You can keep all the sensitive data encrypted and decrypt only at the last possible moment.
Would it be possible to load the decrypted XML into an array of char or byte rather than a string? Then there would be no copy-on-write handling, so you would be able to backfill the memory with #0's before freeing?
Be careful if assigning array of char to string, as Delphi has some smart handling here for compatibility with traditional packed array[1..x] of char.
Also, could you use ShortString?
If your using XML, even encrypted, to store passwords your putting your users at risk. A better approach would be to store the hash values of the passwords instead, and then compare the hash against the entered password. The advantage of this approach is that even in knowing the hash value, you won't know the password which makes the hash. Adding a brute force identifier (count invalid password attempts, and lock the account after a certain number) will increase security even further.
There are several methods you can use to create a hash of a string. A good starting point would be to look at the turbo power open source project "LockBox", I believe it has several examples of creating one way hash keys.
EDIT
But how does knowing the hash value if its one way help? If your really paranoid, you can modify the hash value by something prediticable that only you would know... say, a random number using a specific seed value plus the date. You could then store only enough of the hash in your xml so you can use it as a starting point for comparison. The nice thing about psuedo random number generators is that they always generate the same series of "random" numbers given the same seed.
Be careful of functions that try to treat a string as a pointer, and try to use FillChar or ZeroMemory to wipe the string contents.
this is both wrong (strings are shared; you're screwing someone else who's currently using the string)
and can cause an access violation (if the string happens to have been a constant, it is sitting on a read-only data page in the process address space; and trying to write to it is an access violation)
procedure BurnString(var s: UnicodeString);
begin
{
If the string is actually constant (reference count of -1), then any attempt to burn it will be
an access violation; as the memory is sitting in a read-only data page.
But Delphi provides no supported way to get the reference count of a string.
It's also an issue if someone else is currently using the string (i.e. Reference Count > 1).
If the string were only referenced by the caller (with a reference count of 1), then
our function here, which received the string through a var reference would also have the string with
a reference count of one.
Either way, we can only burn the string if there's no other reference.
The use of UniqueString, while counter-intuitiave, is the best approach.
If you pass an unencrypted password to BurnString as a var parameter, and there were another reference,
the string would still contain the password on exit. You can argue that what's the point of making a *copy*
of a string only to burn the copy. Two things:
- if you're debugging it, the string you passed will now be burned (i.e. your local variable will be empty)
- most of the time the RefCount will be 1. When RefCount is one, UniqueString does nothing, so we *are* burning
the only string
}
if Length(s) > 0 then
begin
System.UniqueString(s); //ensure the passed in string has a reference count of one
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
{
By not calling UniqueString, we only save on a memory allocation and wipe if RefCnt <> 1
It's an unsafe micro-optimization because we're using undocumented offsets to reference counts.
And i'm really uncomfortable using it because it really is undocumented.
It is absolutely a given that it won't change. And we'd have stopping using Delphi long before
it changes. But i just can't do it.
}
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCnt=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
s := ''; //We want the callee to see their passed string come back as empty (even if it was shared with other variables)
end;
end;
Once you have the UnicodeString version, you can create the AnsiString and WideString versions:
procedure BurnString(var s: AnsiString); overload;
begin
if Length(s) > 0 then
begin
System.UniqueString(s);
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
s := '';
end;
end;
procedure BurnString(var s: WideString);
begin
//WideStrings (i.e. COM BSTRs) are not reference counted, but they are modifiable
if Length(s) > 0 then
begin
ZeroMemory(Pointer(s), System.Length(s)*SizeOf(WideChar));
//if PLongInt(PByte(S) - 8)^ = 1 then //RefCount=1
// ZeroMemory(Pointer(s), System.Length(s)*SizeOf(AnsiChar));
s := '';
end;
end;

Resources