Of course, even if you hashed the password (which is what most real programs do, by the way), that's not the end of the story. If someone had access to the actual executable, they could just modify the code. Figure out where the check is being performed, and replace that assembly with (e.g.) a whole bunch of 0x90's (which is the machine code for a NO-OP). They could just eliminate the branch entirely. Or make it an unconditional branch. Or whatever.
So then you might have to perform a checksum on the executable to ensure that the code hasn't been modified. But then you have to check that checksum somewhere else, which is itself vulnerable. And so on. You can see why digital protection mechanisms are difficult to do well.
By the way, I have actually legitimately used the insert-noops technique before. I had a binary-only program that was supposed to run as a non-root user, but it was a virtual machine and root was the only user. It exited and refused to run. So I ran it in gdb until it exited, found the branch, and squelched it with noops. And I didn't have to create new user accounts just to run the silly program. (It was a version control system, one of the ones that used to be popular before sensible systems like git came into being.) Yes, creating a new user might have been easier, but I would have had to do it every time I rebooted....
Finally: there's a program called "strings" (at least on UNIXes with GCC) which will go through the data section of your executable and look for anything that looks like a string. Here's the output on a hello world program:
As you can see, it doesn't take much effort to just dump all the strings and get an idea of what's going on. Notice the "Hello, World!"? So even if you manage to hide how the code is accessing the data, you might still have to hide the data itself. The nice thing about this technique is that you don't need any gdb skills at all, just type "strings".Code:$ strings hello /lib64/ld-linux-x86-64.so.2 __gmon_start__ libc.so.6 puts __libc_start_main GLIBC_2.2.5 fff. fffff. l$ L t$(L |$0H Hello, World!
Last edited by dwks; 08-14-2012 at 02:38 PM.
dwk
Seek and ye shall find. quaere et invenies.
"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell
Other boards: DaniWeb, TPS
Unofficial Wiki FAQ: cpwiki.sf.net
My website: http://dwks.theprogrammingsite.com/
Projects: codeform, xuni, atlantis, nort, etc.
Just to clarify: it has been mentioned already that this board doesn't support cracking, and we won't post about that. But I think it's important to understand how security *can* be defeated, I mean the types of actions that are technically feasible. Especially if you want to write software that does things like prompting for passwords. If you don't understand how security can be broken there's no way to write secure programs.
Also it's kind of fun to poke around and see how executables and assembly and debuggers work. It leads to a better understanding of how computers really tick, and that's all to the good. If you want to see true magic, look up nm and ldd and objdump. Cheers.
dwk
Seek and ye shall find. quaere et invenies.
"Simplicity does not precede complexity, but follows it." -- Alan Perlis
"Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
"The only real mistake is the one from which we learn nothing." -- John Powell
Other boards: DaniWeb, TPS
Unofficial Wiki FAQ: cpwiki.sf.net
My website: http://dwks.theprogrammingsite.com/
Projects: codeform, xuni, atlantis, nort, etc.
I'll mention that while the world is complex, and cracking programs is easy, there are ways to get around this.
To ensure no one modifies your executable, we use a digital signature. It's a proven technology used in many places on the web today, for example in encrypted SSL connections. Not going to explain how it works (google is your friend!).
As for how to prevent in-memory executable modification, typically the alternatives in the real world are either:
- No allowing writing to memory of another executable where its code resides (can be overridden, but typically requires admin privileges to do so).
- DEP prevents programs from writing some code into memory and executing that (DEP can be turned off, but doing so typically requires admin privileges).
- Sandboxing - essentially running all programs in a little virtual machine so whatever they do cannot affect other programs.