Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > General > Decrypting

Reply
 
Thread Tools Search this Thread Display Modes
Old 26th October 2008, 14:45   #281  |  Link
Oopho2ei
Guest
 
Posts: n/a
Some success.
These are the first entries of the plain conversion table as it comes from the vm memory:
Code:
<---- ????? ----> <----  A ----> <---- A' ---->
b6 be 74 2b 32 c7 94 d0 bc cc b2 72 76 b8 af 89  
73 84 14 69 fc ee 88 0a 8a ae 33 41 f8 50 02 ad  
ac 84 f4 00 e2 47 38 0e 56 3e a1 49 0b 82 39 21 
a2 84 04 1e 5c 35 de f6 6a e1 0f bc 92 5d 3a cd
I have calculated the corresponding B and B' for the first segment:
Code:
B  = 3EFDFC42F8
B' = 3F99F3C46C
You can verify that:
Code:
0x94d0bcccb2 XOR B  = 0xAA2D408E4A
0x7276b8af89 XOR B' = 0x4DEF4B6BE5
0x880a8aae33 XOR B  = 0xB6F776ECCB
0x41f85002ad XOR B' = 0x7E61A3C6C1
...
Each of the 5 bytes overwrite a "bad spot" as you can see from posting #13.
  Reply With Quote
Old 27th October 2008, 00:52   #282  |  Link
Oopho2ei
Guest
 
Posts: n/a
Every entry of the first block is xored with the value
Code:
FC A4 D4 78 56 76 3E FD FC 42 F8 3F 99 F3 C4 6C
which can also be found in the player memory. I am currently tracing it to it's source. Anyway the resulting decrypted first block is:
Code:
<---  header ---> <-  piece 0 -> <-  piece 1 ->
4A 1A A0 53 64 B1 AA 2D 40 8E 4A 4D EF 4B 6B E5
8F 20 C0 11 AA 98 B6 F7 76 EC CB 7E 61 A3 C6 C1
50 20 20 78 B4 31 06 F3 AA 7C 59 76 92 71 FD 4D
5E 20 D0 66 0A 43 E0 0B 96 A3 F7 83 0B AE FE A1
B3 1E D0 65 8B 08 02 47 5D 56 F6 55 D3 9A 55 8D
51 26 10 19 3E AB E7 8C 57 D3 80 CF 51 4C 72 4E
BD 11 20 E8 0B 62 03 CF C3 C5 D9 32 7F 0F 21 6F
7F 0D 01 13 B5 B4 EB 25 EC 62 A7 4C AC 61 66 27
7A 05 50 14 77 28 FE 1B B7 DA 6C 5E 1C 7A 2E 69
96 02 10 41 96 2F D1 3E 88 66 BA 01 84 2E 9F 9C
A9 00 B0 3E 59 93 56 18 1A 8B D8 10 00 02 5C 00
AC 08 B0 2B A1 80 A4 30 D1 66 6E AC 17 12 1D 3B
BF 04 10 25 11 5F 60 F9 34 FA 12 4F A7 0E 06 2E
92 02 A0 27 54 14 2D B1 22 AA 27 9B 2A 56 C6 CF
4B 05 40 0D 27 A3 15 75 17 1D B4 46 8F FF 7C B6
75 02 10 26 68 AC AD 05 9A 4B 0E 78 9A 4D BD 4A
AB 06 60 1B AE 4F 4D 33 12 1B 57 17 05 88 B3 71
BF 06 F0 19 94 5B 4F 64 CF 63 4A F7 28 69 62 9A
63 06 60 26 7C 1F B4 45 71 B3 61 09 72 99 D2 A4
A9 04 B0 26 70 0D EB B9 1C A4 D4 09 02 A9 5A 77
53 04 A0 1B 58 15 2B AD E5 64 84 B2 F5 9D 16 DE
40 01 40 17 A1 7E 09 E0 31 AE 1C CA 7C 9C D3 8B
68 06 F0 44 92 9C B6 6B 1A 67 50 CC 59 9E 7D D4
9A 01 20 39 A3 B3 69 9C DF 4E 8F 0A F0 BB 1C 3C
69 04 80 23 2D 4F 0F F6 F7 C6 11 8D 47 0B 49 20
4B 06 D0 0F 5A 57 D8 55 A0 63 EB DA EE AB DF 70
9B 07 90 0E 14 98 C1 29 B3 62 FC 8F F4 D4 BA BF
AB 07 C0 23 7D 35 54 24 38 CA AE 2E 0F 6F 9B 15
8A 05 00 5C A7 73 CA 62 D3 28 CF 8B AD 23 AF 84
68 15 50 1B A6 54 9A D8 6A 98 0D 82 4B 4F 53 6C
79 04 20 35 B1 AD 81 A8 F8 A0 53 15 AD 88 65 54
65 07 50 28 A0 70 69 B7 57 54 C1 F4 25 2C 4F 12
Every row contains the information to fix two broken spots in the media file. The replacement data which overwrites the broken spots is called piece 0 and piece 1 here.
Notice that the last two bytes of the header are the address of the bad spots in the plain TS buffer (size: 0xC0 bytes) for piece 0 and piece 1 respectively. For example the first change occurs at address 0x072D4764 (as you can see in posting #13) so the data is written in the buffer starting at address 0x072D4764 mod 0xC0 = 0x64. The other four bytes of the header probably contain the rest of the address to determine the exact position of the change in the file "00001.m2ts". The first two bits of the header have a special meaning. According to the checks in the code they can either be '01' or '10'.

This file contains a comparison of the outputs of anydvdhd and dumphd for "The Day After Tomorrow". It expands your view beyond what is shown in posting #13. It is not a complete comparison because the file would have been too large so i stopped after a few minutes. The broken spots of the movie are scattered randomly over the entire file with large spaces in between relative to their size so the contents of this file doesn't contain a single frame of the movie or anything you could playback.

Last edited by Oopho2ei; 27th October 2008 at 01:09.
  Reply With Quote
Old 27th October 2008, 18:53   #283  |  Link
Oopho2ei
Guest
 
Posts: n/a
Has anyone searched the vm memory for the following segment keys?
Code:
FC A4 D4 78 56 76 3E FD FC 42 F8 3F 99 F3 C4 6C (first segment)
0E 7B 1F D9 95 E0 37 EE 7E 96 C5 61 63 76 3E FA (second segment)
48 69 0D 2D 9A 41 BE 2E 82 52 64 88 B1 E7 31 9F (third segment)
AA AB 5B E9 44 CC 38 B3 93 21 6D 1C C5 AD E0 DC (fourth segment)
...
Maybe after every event #220 the segment key (corresponding to the segment number passed as third parameter) is stored at 0x000010 in the virtual machine memory for the player to fetch?

You have no idea how often a segment key is copied from one module to another until it is finally applied in my player. I am glad i don't have to do this again

Edit: the Debugger doesn't give the correct value so something is wrong.

Edit: I have checked my player again and after Event #220(0,1,1) i can find FC A4 D4... in the vm memory at address 0x10 before TRAP_Finished is called. Even if i run the debugger with snapshot/trace guidance i get a wrong value at 0x10.

Edit: forget it. The debugger is giving the correct result when running with snapshots/trace guidance:
Code:
#007599 TRAP_DeviceDiscovery   (00000001, 00000001, 00022B48, 001EFA58);
#007600 TRAP_DeviceDiscovery   (00000001, 00000002, 00022B48, 001EFA58);
#007601 TRAP_Finished          ();
FC A4 D4 78 56 76 3E FD FC 42 F8 3F 99 F3 C4 6C 
#000206 Interruption
#000207 Interruption
But sadly without the help of the snapshots and traces the result is wrong:
Code:
#007567 TRAP_DeviceDiscovery   (00000001, 00000001, 00022B48, 001EFA58);
#007568 TRAP_DeviceDiscovery   (00000001, 00000002, 00022B48, 001EFA58);
#007569 TRAP_Finished          ();
60 FC A5 8B 89 59 38 B4 29 F0 9F 81 8C EB B6 EC
#000206 Interruption
#000207 Interruption
I guess this means the content code has detected an implementation error. The problem could be the unfinished implementation of TRAP_DiscoveryRAM like Schluppo suggested. Also note that fewer traps have been executed in this case.

Edit: Schluppo seems to be right. When i change the contents of the virtual player memory the section key is changing too. Therefor i will pay attention to TRAP_DiscoveryRAM now.

Last edited by Oopho2ei; 27th October 2008 at 23:03.
  Reply With Quote
Old 28th October 2008, 03:18   #284  |  Link
Oopho2ei
Guest
 
Posts: n/a
It looks like some values needed for the calculation of the segment keys are stored in slot 0 or at least the contents of slot 0 influences the result. Anyway there was a stupid bug in TRAP_SlotWrite (the slot payload was copied from the same address as the hash ) which caused the calculation to fail. It seems the conversion table and the segment keys (used to decrypt the entries of this table) are correctly calculated now without the help of snapshots or traces.

I've added a switch 'autoEvents' to the event class which determines if an event is generated every time the calculation is interrupted or if the debugger should issue events like the player in the snapshots. The default is to generate events automatically now.

Schluppo made a patch which writes the conversion table into a file "conv_tab.bin". You will get the segment keys one by one starting with event #000004 by pressing F5 or clicking the "run" button. You can compare them with the keys from the previous posting.

That's a snapshot of the debugger with all files needed: Debugger (testing)

Now all that's left to do is decrypting the entries of the conversion table with the segment keys (simple xor) and then patching the *.m2ts files according to the table.
  Reply With Quote
Old 28th October 2008, 03:52   #285  |  Link
schluppo
Guest
 
Posts: n/a
Here's the complete structure of the 'conversion table' (this covers exactly all the data which is given by trap 0x20):

Code:
header
16 bit: [number of tables]

then [number of tables] tables, where a table is as follows:

table
32 bit: [table id]
16 bit: [number of segments]

then [number of segments] times:
32 bit: address of each segment
then [number of segments] segments, where a segment is as follows:

segment
32 bit: [number of entries]
then [number of entries] times: 32 bit indexing value
then [number of entries] times: 16 bytes table entry
In the two examples that we could look at so far, the conversion table consists of 0x24 / 0x42 tables, but all other tables apart from the one with [table id]=1 just contain varying numbers of empty segments (i.e. segments with [number of entries]=0).

So here is an example of how to get to "DAT" table 1, segment 3, entry 8. Be aware that all the mentioned addresses are relative to the starting address of the conversion table. Also notice that the counting of tables starts at 1 whereas counting of segments and entries starts at 0:

Code:
At 0x00000000, check: 1 <= [number of tables]? If not: Error!
Seek to table_offset for [table_id]=1. In this case, this offset is 0x00000006. For [table id]=2, the offset is 0x000FC930 etc.
At 0x00000006, check: 3 < [number of segments]? If not: Error!
Seek to segment_address for segment 3. In this case, this address lies at 0x00000006 + 2 + 3*4 = 0x00000014 and has value 0x00001FC8.
Seek to 0x00001FC8.
At 0x00001FC8, check: 8 < [number of entries]? If not: Error!
Seek to 0x00001FC8 + 4 + 8*4 = 0x00001FEC.
Get indexing value from 0x00001FEC (in this case, the indexing value is 0x001B0E1E).
Seek to 0x00001FC8 + 4 + [number of entries]*4 + 8*16 = 0x00001FC8 + 4 + 0xBA*4 + 8*16 = 0x00002334.
Get table entry from 0x00002334 (in this case, the table entry is 0xC04C9D38 0xD81F55CD 0x95D64326 0x196C2248).
Edit: Also, [number of segments] of table 1 will tell us, how often we have to invoke event 0x220 to get all the segment keys (DAT: 0x153 times, I Robot: 0x141 times).

Last edited by schluppo; 28th October 2008 at 04:01.
  Reply With Quote
Old 28th October 2008, 04:59   #286  |  Link
Accident
Registered User
 
Join Date: Aug 2002
Posts: 111
Having a go at the *Slot functions, and I am curious about this comment
Code:
 The return value is the attached slot number, or an error
  code if the operation failed (e.g., because of a code hash mismatch)
However, the JAVA code that is currently checked in only returns STATUS_OK. So which way is more correct?

Edit: Ah ok thanks Oopho2ei, I will follow the code.
Is it not peculiar the offset from conversion table are only 32bit, can it not then scramble beyond 4GB boundary?

Last edited by Accident; 28th October 2008 at 14:02.
Accident is offline   Reply With Quote
Old 28th October 2008, 06:58   #287  |  Link
schluppo
Guest
 
Posts: n/a
The debugger is now automatically XORing the entries from the correct segment of the conversion table with the current segment key whenever an event 0x220 is finished. Also it will now take the total number of segments from the conversion table and then invoke event 0x220 as often as necessary, until the complete table is decrypted. Once you press 'run' now, it will run until the conversion table is completely decrypted. The table is only dumped once, when the last event 0x220 was finished. The whole process takes around 30 seconds on my machine.

All that's needed now, is a program which replaces the correct parts of the stream-files with the entries from the conversion table

Edit: The conversion table that is generated by the newest version of the debugger coincides with the values from the comparison file in posting #282

Edit 2: I figured out three of the four remaining unknown bytes of an entry in the conversion table. Also I figured out the indexing.

Code:
The first indexing value in the table is:
0x9900A.
The first entry is:
4A 1A A0 53 64 B1 AA 2D 40 8E 4A 4D EF 4B 6B E5

(0x9900A+0x1AA)*0xC0       + 0x64 = 0x72D4764      // offset in the big file where the first 5 bytes are put to
(0x9900A+0x1AA+0x053)*0xC0 + 0xB1 = 0x72D85F1      // offset in the big file where the second 5 bytes are put to

-----

The second indexing value in the table is:
0x99C85.
The second entry is:
8F 20 C0 11 AA 98 B6 F7 76 EC CB 7E 61 A3 C6 C1

(0x99C85+0x20C)*0xC0       + 0xAA = 0x736ED6A      // offset in the big file where the third 5 bytes are put to
(0x99C85+0x20C+0x011)*0xC0 + 0x98 = 0x736FA18      // offset in the big file where the fourth 5 bytes are put to
So, the whole big file is cut down in blocks of 0xC0 bytes. The indexing value points to a section of around 0x300 of these small blocks. Bits 9-20 of the entry select one of the first ~0x26D of these blocks. Bits 21-32 select one of the remaining blocks. The sum of both numbers usually is around 0x1FF except for some cases where the first number is bigger than 0x200. Finally bytes 5 and 6 give the exact position inside the selected blocks.

I don't know the meaning of the first 8 bits of the entries yet (checksum over the other 15 bytes?).

Anyway, it is now possible to code a program which takes a conversion table as input and then goes through a list of .m2ts files, repairing them.

Last edited by schluppo; 28th October 2008 at 14:43.
  Reply With Quote
Old 28th October 2008, 13:47   #288  |  Link
Oopho2ei
Guest
 
Posts: n/a
Quote:
Originally Posted by schluppo View Post
Here's the complete structure of the 'conversion table' (this covers exactly all the data which is given by trap 0x20):
Thanks a lot! Indeed there are 36 (=0x24) m2ts files in the BDVM/STREAM directory. Starting with 00001.m2ts (the main movie) up to 00036.m2ts. So it seems there is a table for every m2ts file. The first file which is played is 00005.m2ts and then the movie starts (00001.m2ts). Is the table id in the table of the first TRAP_Schluppo 5 or is it exactly the same table?

Also thanks for your work on the debugger.

Quote:
Originally Posted by Accident View Post
Having a go at the *Slot functions, and I am curious about this comment
Code:
 The return value is the attached slot number, or an error
  code if the operation failed (e.g., because of a code hash mismatch)
However, the JAVA code that is currently checked in only returns STATUS_OK. So which way is more correct?
Someone has to update the documentation. It's mostly a copied from the patent (which describes a similar system). If in doubt trust the source code.

Last edited by Oopho2ei; 28th October 2008 at 13:50.
  Reply With Quote
Old 28th October 2008, 14:07   #289  |  Link
schluppo
Guest
 
Posts: n/a
Quote:
Originally Posted by Oopho2ei
Is the table id in the table of the first TRAP_Schluppo 5 or is it exactly the same table?
The 'sub-tables' in the conversion table should be lexically ordered, that means, the table for 00001.m2ts should be the first table (with smallest ID) and the table for 00036.m2ts should be the last table (with biggest ID). I assume that the first call of trap 0x20 gives exactly the same conversion table as the second call (but I did not verify that yet).

Also, please take note of my editions of posting #287

Edit: I just thought, that we may need to invoke event 0x220 (0,m,n) with <m>!=1. My guess is, that <m> selects the 'sub-table' number and <n> selects the segment number. The result is then the segment key for the selected segment in the selected 'sub-table'. For <m>!=1, this should allow us to decrypt the 'sub-tables' for other files than 00001.m2ts (could be necessary for e.g. "Die Another Day"). However, for DAT and I Robot, this should be no problem yet, since these movies only use one encrypted file (00001.m2ts).

Last edited by schluppo; 28th October 2008 at 15:47.
  Reply With Quote
Old 28th October 2008, 14:19   #290  |  Link
Oopho2ei
Guest
 
Posts: n/a
Quote:
Originally Posted by schluppo View Post
Also, please take note of my editions of posting #287
Well done!
I will try to repair 00001.m2ts of "The Day After Tomorrow" now.
  Reply With Quote
Old 28th October 2008, 16:58   #291  |  Link
frogman
I swallow bugs!
 
frogman's Avatar
 
Join Date: Jan 2007
Location: Whitehouse corner Office
Posts: 49
The light of day now appear to be coming up on those sony+fox cockroaches. hmm... I think I am having a good day.

Ps: Slysoft just released an open beta "AnyDvD HD"

Feedback is welcome from everybody else.

http://forum.slysoft.com/showthread.php?t=21699
http://sandbox.slysoft.com/beta/SetupAnyDVD6478.exe

6.4.7.8 2008 10 22
- "New (Blu-ray): Added option to disable BD-Live"
- New (Blu-ray): Added removal of region locks from menus
- New (Blu-ray): Added support for new version of the BD+ copy protection
- Some minor fixes and improvements
- Updated languages

Last edited by Doom9; 29th October 2008 at 23:34. Reason: removed quotes from Slysoft's private beta forums
frogman is offline   Reply With Quote
Old 28th October 2008, 19:28   #292  |  Link
Oopho2ei
Guest
 
Posts: n/a
I am glad to announce the first successful restoration of the BD+ protected movie "The Day After Tomorrow" in linux. It was done using a blue ray drive with patched firmware (to get the volume id), DumpHD to decrypt the contents according to the AACS specification and the BDVM debugger from this thread to generate the conversion table. The conversion table is the key information to successfully repair all the broken parts in m2ts files to restore the original video content. This small tool was finally used to repair the main movie file "00001.m2ts" according to the conversion table.

To verify the correctness i compared my 00001.m2ts with the one AnyDVD-HD creates and they both match. The MD5 hash of this 30GB large file is in both cases "0fa2bc65c25d7087a198a61c693a0a72".

Well done everyone!

Last edited by Oopho2ei; 28th October 2008 at 19:40. Reason: fixed verbose console output
  Reply With Quote
Old 28th October 2008, 22:31   #293  |  Link
RunningSkittle
Skittle
 
RunningSkittle's Avatar
 
Join Date: Mar 2008
Posts: 539
Looks like its almost time for me to go get a BR drive
RunningSkittle is offline   Reply With Quote
Old 28th October 2008, 23:05   #294  |  Link
LoRd_MuldeR
Software Developer
 
LoRd_MuldeR's Avatar
 
Join Date: Jun 2005
Location: Last House on Slunk Street
Posts: 13,248
Congratulations

I don't have a BR drive, but it's always nice to know that there's a cure for the DRM disease.
__________________
Go to https://standforukraine.com/ to find legitimate Ukrainian Charities 🇺🇦✊
LoRd_MuldeR is offline   Reply With Quote
Old 29th October 2008, 00:05   #295  |  Link
chavonbravo
Registered User
 
Join Date: Aug 2007
Posts: 17
With this working, we're pretty much at the level of anydvd hd, as long as it's mkbv7 or below, right?
chavonbravo is offline   Reply With Quote
Old 29th October 2008, 00:06   #296  |  Link
Oopho2ei
Guest
 
Posts: n/a
Thanks. I hope that other people try to write their own implementations and make their source code public. The debugger source code and the information from this thread and the repository should be enough to provide basic BD+ support. I am no professional programmer and it might also be better to integrate the core functionality of the debugger into DumpHD instead of having lots of smaller tools.

Quote:
Originally Posted by frogman View Post
- New (Blu-ray): Added support for new version of the BD+ copy protection
I've updated to the latest firmware version (sept. 2008) and couldn't find any major changes in my player. No new command or traps. Not even new AES keys or a different ECDSA certificate.
I believe this statement means the BD+ implementation in AnyDVD-HD is buggy/incomplete (like ours) and new versions of the content code are handled incorrectly because for example a particular trap was never used before (or never used with certain parameters) and was therefor insufficiently tested or not implemented (like TRAP_RunNative).

Quote:
Originally Posted by chavonbravo View Post
With this working, we're pretty much at the level of anydvd hd, as long as it's mkbv7 or below, right?
I currently can't answer that question because i only have 2 BD+ protected movies and only one of them (The Day After Tomorrow) has been tested so far. There is still some work to be done. Also using the debugger to get the conversion table and then repair every m2ts file with the small c program i wrote is too complicated for the average user. I am hoping other people will like KenD00 will integrate the code into their tools to make watching BD+ protected movies in linux possible for the average user.

Quote:
Originally Posted by Accident View Post
Is it not peculiar the offset from conversion table are only 32bit, can it not then scramble beyond 4GB boundary?
Sorry i didn't see you've edited your posting. You will find the answer when you look at the way the address is calculated line 151-156. As you can see it's adjusted with a positive value and then multiplied with 0xC0 (the buffer size). I haven't calculated the highest possible address but it's obviously much larger than 2^32. Also take a look at Schluppos example in posting #287.

Last edited by Oopho2ei; 29th October 2008 at 00:48.
  Reply With Quote
Old 29th October 2008, 00:13   #297  |  Link
kkloster21
Registered User
 
Join Date: Jun 2008
Posts: 117
awesome news! looking forward to seeing you guys release a tool for this! (whether its a separate package or it gets integrated into dumpHD)

a big thanks to Oopho2ei, bmnot, schluppo, Disabled, evdberg and anybody else who contributed!

I regret that i don't have the knowledge to be of any help in the programming but i do have several BD+ discs and a blu-ray drive that i more than happy to test on! let me know when to start!
kkloster21 is offline   Reply With Quote
Old 29th October 2008, 07:55   #298  |  Link
tteich
Registered User
 
Join Date: Jul 2004
Posts: 40
Quote:
Originally Posted by Oopho2ei View Post
I am glad to announce the first successful restoration of the BD+ protected movie "The Day After Tomorrow" in linux. It was done using a blue ray drive with patched firmware (to get the volume id), DumpHD to decrypt the contents according to the AACS specification and the BDVM debugger from this thread to generate the conversion table. The conversion table is the key information to successfully repair all the broken parts in m2ts files to restore the original video content. This small tool was finally used to repair the main movie file "00001.m2ts" according to the conversion table.

To verify the correctness i compared my 00001.m2ts with the one AnyDVD-HD creates and they both match. The MD5 hash of this 30GB large file is in both cases "0fa2bc65c25d7087a198a61c693a0a72".

Well done everyone!
Congratulations!
tteich is offline   Reply With Quote
Old 29th October 2008, 09:20   #299  |  Link
Wimpy
Registered User
 
Wimpy's Avatar
 
Join Date: Feb 2002
Posts: 25
Quote:
Originally Posted by Oopho2ei View Post
I am hoping other people will like KenD00 will integrate the code into their tools to make watching BD+ protected movies in linux possible for the average user.
Excellent work by all involved!

I don't "do" Windows. I have been tinkering with various tools, on and off and with varying success, for over a year now so that I can watch my Blu-Ray films on my Linux computers.

Looking forward the the BD+ tools to getting integrated in DumpHD. I'm fortunate enough to own a GGW-H20L which I flashed with your patched firmware last night. Looking forward to testing the result, on non-BD+ disks, this evening when I am back from work.

Many thanks to all involved, you are helping to get the Linux community on an even footing with regard to Blu-Ray support!
__________________
Regards, Martin.
Wimpy is offline   Reply With Quote
Old 29th October 2008, 09:37   #300  |  Link
Wombler
Affable Wanderer
 
Wombler's Avatar
 
Join Date: Apr 2007
Location: Northern Ireland
Posts: 451
That's fantastic news guys and congratulations to everyone involved.

It's a very significant achievement.


Wombler
Wombler is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:52.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.