Can I write IL programs directly?

Yes.
assembly MyAssembly {}
.class MyApp {
.method static void Main() {
.entrypoint
ldstr "Hello, IL!"
call void System.Console::WriteLine(class System. Object)
ret
}
}
Just put this into a file called hello.il, and then run ilasm hello.il. An exe assembly will be generated.
Can I do things in IL that I can't do in C#?
Yes. A couple of simple examples are that you can throw exceptions that are not derived from System.Exception, and you can have non-zero-based arrays.