AGI1122 |
I have been playing around with reading the object file in php. So far I have the ability to tell the difference between an encrypted object file and a normal one. Although it doesn't check if it is an AGDS object file or not.
But I am having trouble with figureing out how to decrypt it after I have determined it is encrypted. The docs say something about:
XOR each element of those eleven bytes with the corresponding element in the string "Avis Durgan"
What exactly is "XOR" and how do I go about decrypting it?
And before anyone says that since I am a moderator of the AGI board I should know this... bite me. :P I know AGI's scripting language. But what I don't know is the interpreters inner workings and the format the data is stored in and encrypted, which is what I am attempting to learn now.
|
Eero R |
XOR is a connective in logic. It is true, when one of two conditions is true, but not 0 or 2. When there are two or more conditions, XOR is true when an odd number of conditions are, and false otherwise. When XORring letters it goes like so: a = 01100001 b = 01100010 a XOR b = 00000011 In PHP you could do so: "a" ^ "b"
|
BI lazy |
XOR truth table:
true^true=false false^true=true true^false=true false^false=false
In words: If either element A is true or element B is true, the statement is true. If element A and element B are true or element A and element B are false, the statement is false.
stay safe.
|
AGI1122 |
Ok I get it, so it evaluates to true if either are true, but not both of them or none of them.
Well that part is answered, but I still have to figure out how to decrypt the object file now that I have determined it is encrypted.
|
Perica |
There's an article on XOR encryption at http://www.cprogramming.com/tutorial/xor.html.
If you have trouble understanding it, or need an explanation of something .... just ask and I'll try and explain. It can be pretty confusing at times.
Puting it simply though, to decrypt an XOR-encrypted structure, you would simply need to XOR the decryption key with every byte in the structure (if the key is smaller than the size of the structure, which is usally the case - then you start XOR-ing from the beginning of the key again).
|
AGI1122 |
Hmmmm that site isn't loading, I guess I will have to try it later.
|
sonneveld |
Intro ---------------
XOR stands for "exclusive or". It's a form of OR where if you have two boolean inputs, your output will be true only if one or the other inputs are true.. but NOT both. Hence the exclusive bit.
A B Out 0 0 0 0 1 1 1 0 1 1 1 0
Now if you think of A as the input and B as something you can manipulate, you might notice that the input A is inverted (ie 1->0 and 0->1) when B is set to 1. and that the input A is left alone when B is set to 0.
It's in this way that XOR can be used to invert bits in a file.
Characters ---------------
What about XOR'ing characters? like 'a' ^ 'b' or something like that. (^ is an operator in C [and possibly PHP] that XORs two characters or numbers together)
Well to the computer, 'a' and 'b' are binary sequences 1100001 and 1100010 respectively. So when you XOR them together, it'll look at each bit respectively.
so 1100001 'a' XOR 1100010 'b' -------- 0000011
You can follow the table at the top and see that only the last two binary digits will produce a 1.
"Encryption" ---------------
So what about encryption? For simple encryption, you want to be able to encrypt and decrypt to get the data back.
So if I have 'a' and XOR with 'b' you get 0000011 (as shown above) but if we XOR the answer with 'b' again:
0000011 XOR 1100010 'b' -------- 1100001 = 'a' !!!
So if you have 'a' ^ 'b' ^ 'b' you get 'a' again! This is the basis of XOR encryption in AGI object files.
The only difference is that you use a string "Avis Durgan", so you go through each character in the string you want to encrypt and XOR with 'A' for the 1st, 'v' for the 2nd and so on..
I hope this made sense!
- Nick
|
Joel |
Here's a simple C++ implementation of the encryption. The decryption is exactly the same. Like Nick mentioned, the ^ operator in C++ performs a bitwise xor.
const char AvisDurgan[] = "Avis Durgan"; const int AvisLength = 11;
void Encrypt(char* bytesToEncrypt, unsigned int byteCount) { unsigned int avisPosition = 0; unsinged int i = 0;
for (i = 0; i < byteCount; i++) { // xor the current byte of bytesToEncrypt // against the current byte of "Avis Durgan"
bytesToEncrypt ^= AvisDurgan[avisPosition];
// then advance the position in the "Avis Durgan" // string and use mod to cycle back to the beginning // if we've reached the end
avisPosition++; avisPosition %= AvisLength; } }
|
df |
the easiest way to tell if its in encrypted, since the first bit of data points close to the start of the file, it will always be below a certain number. if its encrypted the first word is huuuge and 99% of the time point beyond te end of the file.
AGDS is just a differeny encrytion key instead of 'avis durgan'
and also, amiga object game file has different size padding to other architectures. amuga uses 4 byte padding inside the object file, every other game system users 3 (mac, atari st, etc).
(the specs on helllabs are more up to date than the ones on nicks agidev site, for teh object file anyway... object specs)
neither have updated info on amiga padding
|
AGI1122 |
Thanks guys, I have the decryption working 100%. I used AGI Studio to create a copy of the object file only unencrypted. And then ran my unencryption routine on the encrypted one. The one decrypted by AGI Studio and the one decrypted by my script are 100% identical. :)
|
Eero R |
Great job! ;)
|
AGI1122 |
Yeah... but I still have a long way to go to learn more about AGI's internals.
After I learn more about object and how the data is stored I will move on to words.tok next. Maybe logics after that... I plan to save views, pictures, and sound for last though.
Although eventually I will need to learn lzw compression so that I can use v3 stuff. :-\
|