A Gentle Primer on Reverse Engineering
emily.st
emily.st
One nit, though. There's a subtle error in the main function:
char* input;
printf("Please input a word: ");
scanf("%s", input);
Local variables are not automatically initialized in C, and we never assign input to point to any particular block of memory. This means it's probably pointing off to some random location - basically whatever address happened to be sitting on the stack when main was called. So when scanf writes the user password to input, it's going to go to some unpredictable location with unpredictable results. This could lead to code execution, or at least a straightforward denial of service.Furthermore, I am not sure why not write out the complete code, even if the author knew the code was not correct, even when pointed out, it would have been very trivial to initialize the variable.
In addition, I'm not an expert at this stuff, but it seems like initializing that variable would make the disassembly more complex and thus obfuscate the point just that much further.
I would expect the full code to be correct/complete. This type of bug goes well beyond "I also make some assumptions in string handling that are considered gravely unsafe to use in a modern program, so please do not use this code in the real world." IMO.
A really simple fix would be just to use a character array.
Could they adjust the snippet? Sure. Will it add anything to the essay to do so? Nope.
char input[SIZE];
I really don't think so. I'm all for simplifying example code to get the core concept across, but I wouldn't go as far as to invoke undefined behavior. I also don't understand the use of scanf. At all. A seasoned, competent C user would never consider using scanf.Anyway, I didn't mean to derail things too much here. It's really a nitpick and has little to do with the article itself.
I'm indignant because this happens on almost every marginally interesting article that makes the front page and I'm sick of it. I get that the code was wrong and a bug and C must be correct at all times or the world will literally light on fire. It's just exhausting reading comment after comment about the tiniest little nit in an otherwise perfectly wonderful essay.
Yes, this is frustrating. It's why we try not to write anything in C anymore.
If you think that having undefined behavior in your code is fine as long as it works for you, do not be surprised that one moment a vile dragon appears and starts spewing fire.
I always found it was cleaner to either force (jmp) or remove (nopnop) the jump rather than inversing its condition. It's more explicit.
Also, in the real world, cracking's usually a bit more than finding the right jump to force/remove. Although, if it's enough to reach your goal, you should do it.
If you search amazon.com, "reverse engineering" is in the titles of the first 2 books:
http://www.amazon.com/s/ref=nb_sb_noss_1?&field-keywords=rev...
The way most people use the terminology now, I'd say "reverse engineering" encompasses all the strategies of analyzing and unraveling the logic of assembler code. On the other hand "code disassembling" is more specific about using a tool such as IDA to disassemble the binary executable into assembly before the intellectual task reverse engineering begins.
The basic one cannot accept any flags and when I type `echo "\x01"` it prints `\x01`
The one in bin can accept flags, and requires the -e flag to interpret backslashes.
This changes the echo line of the program to this:
`/bin/echo -e "\x01"`
I found this out because it was changing the byte from 00 to 5C rather than 01, because 5C is the ASCII for \
echo: shell built-in command.
"I always forget, so I wrote it down."
A: What's your password?
B: "I always forget, so I wrote it down."
A: Where?
B: Where what?
A: Where did you write down your password?
B: I don't write down my password.
A: You just told me you did!
B: Why would I do that?
A: Because I was asking you for your password.
B: And I gave it to you.
A: Did you, or did you not, forget your password?
B: No.
A: So let's have it.
B: "I always forget, so I wrote it down."
A: Do you... ah... need to search your pockets?
B: Why?
A: To help you remember.
B: Remember what?
A: Your password.
B: No. It's very distinctive. I always remember it.
foo bar baz buz qux pip pop tut rof art uff dex dom zedIt's such a hard habit to break. Also, if I can name a character in a videogame, it's almost always Dickbutt.
This is false, as of C99 we have booleans in C, just include stdbool.h in your code, e.g.:
#include <stdbool.h>
...
bool test = true;
... #define true 1
#define false 0
http://clang.llvm.org/doxygen/stdbool_8h_source.htmlIMHO this:
bool is_valid(char* password);
is more clear than this: int is_valid(char* password);Furthermore as the examples are given in C, it is implied that the reader needs to be familiar with the language, and as a consequence, knowing about macros, should be if not a given, then at least required.
I'm glad that the OP at least made it a const char *password though, since that's also a must-have. Always const input pointers. And local temporaries. And everything else that you can const, except scalar arguments pretty much.
#define bool _Bool
Since bool wasn't reserved prior to C99, they use the _Bool keyword (which was reserved). [http://stackoverflow.com/questions/8724349/difference-betwee...]http://althing.cs.dartmouth.edu/local/www.acm.uiuc.edu/sigmi...
int is_valid(char* password) {
return strcmp(password, "poop") == 0;
}But maybe it's just a common trait of detail oriented programmer types to be pedantic?