I think the pattern
<([^>]*<)
will match a < that encounters another < before > (therefore not part of a tag)
...and the pattern
(>[^<]*)>
will match a > that follows another >
var first = Regex.Replace(@"<abc>fd<jkh</abc><def>e>e</def>",@"<([^>]*?<)",@"<$1");
var final = Regex.Replace(first,@"(>[^<]*?)>",@"$1>");
EDIT:
This does work, but you have to pass over it multiple times. I'm sure there's a purer method, but this does work.
class Program
{
    static void Main(string[] args)
    {
        var next = @"<abc>dffs<<df</abc>";
        string current;
        do
        {
            current = next;
            next = Regex.Replace(current, @"<([^>]*?<)", @"<$1");
            next = Regex.Replace(next, @"(>[^<]*?)>", @"$1>");
        } while(next != current);
        Console.WriteLine(current);
        Console.ReadKey();
    }
}