how would you disassemble it then. |
Using a disassembler such as ndisasm.
and why wouldn't it be the same as the source code? |
A compiler transforms one language (such as C++) into another (e.g. x86 machine instructions).
Using a disassembler, you can get a human-readable version of the machine instructions, but it is not the original C++ source code. For example, this is the compiled version (for x86_64) of the savePassword function I posted earlier (optimized for size, it would be much longer otherwise):
http://pastebin.com/paa1e0Sj
Edit: here's the -O3 version:
http://pastebin.com/5Xxb99va
Part of the reason it's so ridiculously long is that it inlines the entire SHA-1 process.
Although it is much harder to figure out what a program is doing when you don't have the original source code, it is possible and you can change it in any way you want.
Luc said that you can simply find the conditional jump instruction that tests the if condition and make it so that the jump is always taken, regardless of the outcome (or when the passwords don't match).
Example:
1 2 3 4
|
bool arePasswordsEqual(const std::string& password1,const std::string& password2)
{
return password1==password2;
}
|
translates to:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
mov rdx,[rdi]
mov rdi,[rsi]
xor eax,eax
mov rcx,[rdx-0x18]
cmp rcx,[rdi-0x18]
jz 0x1c38
rep ret
nop dword [rax+0x0]
cmp rcx,rcx
mov rsi,rdx
repe cmpsb
setz al
ret
|
This first compares the lengths of the two strings and if they are equal, each byte is compared.
Now you could simply replace the first two instructions with
Which would be equivalent to
return true;
And the password you enter will always be considered correct.