The first thing to know is that Elisp has almost no special syntax--
defun is just an Elisp macro for defining functions. Its expansion is rather simple, as you can see from running a quick macroexpansion:
(lambda nil "Insert defun function."
(insert "(defun name ()
\"Insert description here.\"
An important thing to note: the name of the function being defined in
defun is just an argument to a macro. Since
defun is a macro, it does not evaluate its arguments immediately.
defalias, on the other hand, is a built-in function, so it takes a quoted version of the function name--otherwise it would try to evaluate the function name as a variable.
Elisp is incredibly flexible, so it is more than happy to re-define
defun to be a function rather than a macro, which is what you did in your code, and for functions (unlike macros) all arguments are immediately evaluated. The error I got was slightly different than yours--I got
hello being undefined as a variable (I'm guessing your error was caused by some sort of byte-compilation or double-evaluation). Once you understand how function evaluation works in Elisp, this makes perfect sense--the interpreter first evaluates
hello as a variable in order to pass that value to the new function
hello were defined, you would probably get a "wrong number of arguments" error instead (since your new version of
defun takes no arguments).
The moral of the story: Elisp lets you do pretty much anything, but that doesn't mean you should. Never re-define built-in functions or macros unless you want debugging hell.