Actually not tricky at all. Here's two basic forms...there are more, but these are good places to start.
1. Basic bullet shout
Set up a variable to track HP on the object to be damaged. (iHP = 100);
When a bullet hits something, you can make it shout (set the collision_start event in the bullet script to shout something like "damage," + the detected key of the thing it hit). Make sure your bullets die immediately after the shout.
On the object that you want to take damage, set up a listener that listens for the call "damage," + it's own key.
So, if the bullet hits some random object, it will shout "damage," + some random key. The object that needs to take damage will ignore it, since it is listening for "damage," + it's own key (llGetKey());
When the object to take damage hears "damage," + it's own key, that means the bullet hit that object, so subtract the object-to-be-damaged's HP from the HP variable (HP = HP - whatever). When HP hits 0, llDie.
2. Basic Bullet recognition
Name your bullets something recognizeable (i.e., "My Uber Bullet"

.
Set up the collission event on the object to be damaged to check for the name of the object colliding with it (so now the bullet never needs to shout).
If something hits the object to be damaged, check the llDetectedName of the object. If that name is "My Uber Bullet", then the object knows it has been hit by a bullet, and you subtract HP. Note that this method can be spoofed (people can create objects named My Uber Bullet). There are ways around this though, but for now we keep it simple.
These are the MOST basic methods to get you started. Naturally, you can also feed in damage dynamically, check for ownership to prevent spoofing, use more filters to reduce shouting, and so on. I do a great deal of this sort of thing in the games I build in SL.