How I compiled TrueCrypt 7.1a for Win32 and matched the official binaries
madiba.encs.concordia.ca
madiba.encs.concordia.ca
"Using the same source and same project directory results in the same pattern of difference in the block starting at 0002CBAC, as the pattern shown between my build from the correct project directory and the original file. This means that this difference is a normal result of the compilation process, and can be considered harmless from our point of view"
I share the author's belief it's probably benign, and on the assumption that the source code contains no crazy obfuscated magic, it'd be pretty hard to actually hide malicious code or behaviour there.
Still if they want to be thorough (and they should), I'd have liked a bit more explanation than waving it away with a "well these bytes seem to change all the time, so that's okay then". That's not really a justification, it's just an explanation. And it's not okay.
You have somewhere char buff[ 32 ] which you don't set all to zeros, then you do strcpy( buff, "something" ) then you write all 32 bytes of buff to the file. What's behind "something"? It can be different in every run.
Now look at the picture: https://madiba.encs.concordia.ca/~x_decarn/truecrypt-binarie...
See the "RSDS"? It's some initial value, just like c:\truec... that follows some bytes later. And what's behind? Some small sequence of random bytes. I've just checked and confirmed that it appears in the ".rdata" (read only data) section of the executable.
Now the fact that this doesn't happen on much more places also means that somebody in Microsoft obviously from time to time does fully clean the code, that is, somebody worries about such effects too, but it seems that from time to time some "late" fix then slips through, misbehaving.
Another explanation would be that there is something in the building code or script that produces some different values in the initialization area. That can be then observed by source inspection.
The third explanation would be some kind of "unique id" generated by the compiler or linker. Then this effect should be observed in all binaries even when the source is fully different (e.g. compile some program which generates Vogon poetry, observe the same effect). This hypothesis doesn't match the observations, according to the pictures presented.
So I believe the highest possibility is the first assumption being true.
CV_RSDS_HEADER = Struct("CV_RSDS",
Const(Bytes("Signature", 4), "RSDS"),
GUID("GUID"),
ULInt32("Age"),
CString("Filename"),
)
So it's a GUID, and one property of GUIDs is that they're "Globally unique", hence regenerated each time. Mystery solved.Edit: Here's a source [1] so you don't have to take my word for it.
The last bit is the signature, which you can't duplicate, but you can also just take out, as it's not code. But, if you're paranoid about that, zero-out or remove the signature after verifying it.
If everyone were using LUKS instead, one would hope that people would attempt to verify that trust in binary distributions LUKS was well-placed as well.
It doesn't matter what you or I personally prefer, if you want what at least seems to be trustworthy and secure[1], cross-platform cryptography, Truecrypt is what you want.
[1]: Obviously, that is the part that is slowly being evaluated and tested. We'll see what'll happen.
Why? What is the benefit of doing so when everyone wants a deterministic build?
Who tried to poke them how, and what happened?
https://blog.torproject.org/blog/deterministic-builds-part-o...
Synopsis:
"deterministic builds" -- packages which are byte-for-byte identical no matter who actually builds them, or what hardware they use.
They produce builds with hashes of the source and all dependencies and tools used, or so I believe after skimming their manuals.
I'd have thought that deterministic builds are really simple unless your toolkit ecosystem is FUBAR. After all, a compiler is a simple function from input to output (unless the FUBAR ecosystem syndrome arises, as I said).
http://stackoverflow.com/questions/1180852/deterministic-bui...
In short, if you ignore certain things when comparing binaries and make sure you build things on absolute path of the same length(!), you can tell binaries are functionally equivalent.
Import the .asc file in the keyring (File > Import certificates).
Now you should mark the key as trusted: right click on the TrueCrypt Foundation public key
in the list under Imported Certificate tab > Change Owner Trust, and set it as I believe checks are casual.
You should also generate your own key pair to sign this key in order to show you really trust
it and get a nice confirmation when verifying the binary. The PGP signature of the binary can be downloaded
through the button PGP Signature, which makes you
download TrueCrypt Setup 7.1a.exe.sig over HTTPS
(*although with the NSA in the middle, it might not
mean much*).
[emphasis mine]cross-referencing the pgp signature with at least one other (public) source would go a long way toward allaying those concerns (that the HTTPS might not mean much).
this criticism is in no way meant to detract from the rest of the work, and i mean only to refer to pgp sig verification best practices here.
How about an vmware/vbox image setup explicitly for that purpose? Not feasible for windows due to licencing issues, i guess.
Also, huge kudos for the effort going into this work. Thanks!
... as long as you also trust the compiler not to introduce any backdoor... (cf. Reflections on Trusting Trust)
So let me throw out an idea that might help justify this trust too. Compile the same TrueCrypt sources with a totally different compiler, then use both binaries in a deterministic way and compare the raw encrypted result. (I'm assuming here that the same encryption keys and data will give the same result, but don't know for sure if that's true.)
(= ((a-binary b-source) b-source) b-binary)
If you trust a-binary, and you trust b-source, then if that returns true you should be able to trust anything created with b-binary. (a-binary b-source) will not equal b-binary, but ((a-binary b-source) b-source) should.If the hardware is not executing binaries as described, then all bets are off. Compiler A could, in theory, be build and run on a homebrew CPU (http://www.homebrewcpu.com/), but if you are putting that much effort into this, this better be your hobby...
Even if that were not the case, if the hypothesis is that GCC was compromised at some point in the past by a shadowy organization, then you have to consider the possibility that this shadowy organization also got to the other compilers. I think that is where probability steps in though; how confident are you that at least some of the compilers are still safe (or perhaps, at least compromised in conflicting ways)?
If you are able to inspect the actual contents of the program, not the output of a program that itself inspects the actual contents of the program, then this problem disappears. You have to examine the machine code without an intermediary program that could lie to you.
(Of course it is very unlikely that IDA Pro, objdump, or even 'od' is compromised in this way, but I would say this class of attack is largely hypothetical and implausible already...)
Edit:
From wikipedia: "What's worse, in Thompson's proof of concept implementation, the subverted compiler also subverted the analysis program (the disassembler), so that anyone who examined the binaries in the usual way would not actually see the real code that was running, but something else instead."
Which the author does, in fact:
"Of course, we need to trust the compiler, but in this case, it is independent of TrueCrypt."
He even links to the "trusting trust" article.
Because TrueCrypt is several orders of magnitude more high-profile of a target (being actual cryptography instead of a compiler) and probably also several orders of magnitude easier to compromise in a useful fashion & spread.
Paranoia is without bound. Who knows, you yourself might be a sleeper agent and you just don't know it yet! Maybe your eyes really were compromised in development! So you approach the problem from the point of view of what is likely, and what is not. You cannot guard against every single paranoia, but you can guard against ones you deem more likely.
The compiler backdoor would have to be very old to exist.
Lets all just stop right here. No, dont mention that cross-compile with different compilers and compare. Just everyone stop.
I seem to remember retrieving from a BBS way back when, an MS-DOS shareware pascal or C compiler of some kind that would leave behind a serial number foot print in executables that the author said he could use to prove that an unregistered version of his product was used. I wish I could remember it now, though
Since the compiler is in charge of generating the layout of the executable, it's in the perfect position to alter it so slightly to patch in a backdoor.
I don't care where your compiler's AST tree or code generation is. For any compromised program (including a compiler) all I need to do is to monitor the files it generates (patch file_open), for any executable output files, patch its main entry point and add in a payload.
When a compromised compiler is generating your compiler, it will patch your compiler's entry point and add in an extra payload. When your compiler compiles another compiler, it will do the same thing, and so to any other programs it generates.
It's virus writing 101.
It's very easy to play "specialist" and come up with theoretical scenarios, like the idiots that think it's possible to attack git using SHA1 collisions
In the purely theoretical sense, RSA is also broken, since you "only" need to gather a lot of computers to factor a key.
If you are not willing to waste money on proving a point, why would you expect me to waste substantial effort to write code to prove my point to you?
And if you are not willing to put money behind your statement, your one-liner talking point is exactly what it says, "talk is cheap."
I at least put in the effort to build detail case to rebut the previous comment poster's point and showed how it can be done. If you think my point was wrong, build a detail case to rebut it. Then we can have a meaningful discussion; otherwise, it's just cheap empty talk.
BTW, what I talked about was not theoretical. That's how viruses are written. You don't have to believe me, but again it's not my job to convince everyone.
I think we're thinking of the A86 shareware assembler:
That's how science works.
edit: not that this seems like a realistic method of injecting malicious code. If you could get away with that in an open source project, you could probably get away with just hiding the malicious code in the app directly.
The disassembly was only there to be cute and emphasize the point.