Example #1
0
	public static void Main (string[] args) {
		if (args.Length < 2) {
			Console.WriteLine ("usage:  brute.exe <mpq-file> <output-list.txt>");
			Environment.Exit (0);
		}

		MpqArchive mpq = new MpqArchive (args[0]);
		sw = File.CreateText (args[1]);

		Thread t = new Thread (delegate (object state) {
			for (int count = 8; count < MAX_COUNT; count ++) {
				if (count % 2 == 0)
					continue;
				char[] test = new char [count];
				lock (consolelock) {
					Console.Write ("T{0}", count);
					Console.Out.Flush();
				}
				TestStrings (mpq, "t", count, test, 0);
			}
		});

		t.Start();

		for (int count = 8; count < MAX_COUNT; count ++) {
			if (count % 2 == 1)
				continue;
			char[] test = new char [count];
			lock (consolelock) {
				Console.Write ("M{0}", count);
				Console.Out.Flush ();
			}
			TestStrings (mpq, "m", count, test, 0);
		}
	}
Example #2
0
		internal MpqStream(MpqArchive File, MpqBlock Block)
		{
			mBlock = Block;
			
			mStream = File.BaseStream;
			mBlockSize = File.BlockSize;
			
			if (mBlock.IsCompressed) LoadBlockPositions();
		}
Example #3
0
        internal MpqStream(MpqArchive File, MpqBlock Block)
        {
            mBlock = Block;

            mStream    = File.BaseStream;
            mBlockSize = File.BlockSize;

            if (mBlock.IsCompressed)
            {
                LoadBlockPositions();
            }
        }
Example #4
0
        private byte[] LoadBlock(int BlockIndex, int ExpectedLength)
        {
            uint offset;
            int  toread;

            if (mBlock.IsCompressed)
            {
                offset = mBlockPositions[BlockIndex];
                toread = (int)(mBlockPositions[BlockIndex + 1] - offset);
            }
            else
            {
                offset = (uint)(BlockIndex * mBlockSize);
                toread = ExpectedLength;
            }
            offset += mBlock.FilePos;

            byte[] data = new byte[toread];
            lock (mStream)
            {
                mStream.Seek(offset, SeekOrigin.Begin);
                mStream.Read(data, 0, toread);
            }

            if (mBlock.IsEncrypted && mBlock.FileSize > 3)
            {
                if (mSeed1 == 0)
                {
                    throw new Exception("Unable to determine encryption key");
                }
                MpqArchive.DecryptBlock(data, (uint)(mSeed1 + BlockIndex));
            }

            if (mBlock.IsCompressed && data.Length != ExpectedLength)
            {
                if ((mBlock.Flags & MpqFileFlags.CompressedMulti) != 0)
                {
                    data = DecompressMulti(data, ExpectedLength);
                }
                else
                {
                    data = PKDecompress(new MemoryStream(data), ExpectedLength);
                }
            }

            return(data);
        }
Example #5
0
	static void TestStrings (MpqArchive mpq, string dot, int count, char[] test, int index) {
		if (index == count) {
			entry_count ++;
			if (entry_count % 10000 == 0) {
				lock (consolelock) {
					Console.Write (dot);
					Console.Out.Flush ();
				}
			}

			String entry = new String (test, 0, count);
			if (mpq.FileExists (entry)) {
				lock (iolock) {
					sw.WriteLine (entry);
				}
			}
			return;
		}
		for (int j = 0; j < allowable.Length; j ++) {
			test[index] = allowable[j];
			TestStrings (mpq, dot, count, test, index + 1);
		}
	}
Example #6
0
        // Compressed files start with an array of offsets to make seeking possible
        private void LoadBlockPositions()
        {
            int blockposcount = (int)((mBlock.FileSize + mBlockSize - 1) / mBlockSize) + 1;

            mBlockPositions = new uint[blockposcount];

            lock (mStream)
            {
                mStream.Seek(mBlock.FilePos, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(mStream);
                for (int i = 0; i < blockposcount; i++)
                {
                    mBlockPositions[i] = br.ReadUInt32();
                }
            }

            uint blockpossize = (uint)blockposcount * 4;

            // OW:

            // If the archive if protected some way, perform additional check
            // Sometimes, the file appears not to be encrypted, but it is.
            // Edit: In WoW 1.10+, there's a new flag. With this flag present,
            // there's one additional entry in the block table. If this flag
            // is present, we skip this test to keep the file readable.

            if ((mBlock.Flags & MpqFileFlags.FileHasMetadata) == 0)
            {
                if (mBlockPositions[0] != blockpossize)
                {
                    mBlock.Flags |= MpqFileFlags.Encrypted;
                }
            }

            if (mBlock.IsEncrypted)
            {
                if (mSeed1 == 0)
                {
                    mSeed1 = MpqArchive.DetectFileSeed(mBlockPositions, blockpossize);
                    if (mSeed1 == 0)
                    {
                        throw new MpqParserException("Unable to determine encyption seed");
                    }
                }

                MpqArchive.DecryptBlock(mBlockPositions, mSeed1);
                mSeed1++; // Add 1 because the first block is the offset list
            }

            /*
             * // StormLib takes this to mean the data is encrypted
             * if (mBlockPositions[0] != blockpossize)
             * {
             *  if (mSeed1 == 0)
             *  {
             *      mSeed1 = MpqArchive.DetectFileSeed(mBlockPositions, blockpossize);
             *      if (mSeed1 == 0)
             *          throw new Exception("Unable to determine encyption seed");
             *  }
             *  MpqArchive.DecryptBlock(mBlockPositions, mSeed1);
             *  mSeed1++; // Add 1 because the first block is the offset list
             * }
             */
        }
Example #7
0
        private byte[] LoadBlock(int BlockIndex, int ExpectedLength)
        {
            uint offset;
            int  toread;

            if (mBlock.IsCompressed)
            {
                offset = mBlockPositions[BlockIndex];
                toread = (int)(mBlockPositions[BlockIndex + 1] - offset);
            }
            else
            {
                offset = (uint)(BlockIndex * mBlockSize);
                toread = ExpectedLength;
            }
            offset += mBlock.FilePos;

            byte[] data = new byte[toread];
            lock (mStream)
            {
                mStream.Seek(offset, SeekOrigin.Begin);
                mStream.Read(data, 0, toread);
            }

            if (mBlock.IsEncrypted && mBlock.FileSize > 3)
            {
                if (mSeed1 == 0)
                {
                    uint value0 = BitConverter.ToUInt32(data, 0);
                    uint value1 = BitConverter.ToUInt32(data, 4);
                    mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x2fbfbbef, 0x3d3d3d2f);                     // .J unicode magic
                    if (mSeed1 == 0)
                    {
                        mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x3d3d2f2f, 0x3d3d3d3d); // .J ascii
                        if (mSeed1 == 0)
                        {
                            mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x46464952, mBlock.FileSize - 8); // RIFF
                            if (mSeed1 == 0)
                            {
                                throw new MpqParserException("Unable to determine encryption key");
                            }
                        }
                    }
                }
                MpqArchive.DecryptBlock(data, (uint)(mSeed1 + BlockIndex));
            }

            if (mBlock.IsCompressed && data.Length != ExpectedLength)
            {
                if ((mBlock.Flags & MpqFileFlags.CompressedMulti) != 0)
                {
                    data = DecompressMulti(data, ExpectedLength);
                }
                else
                {
                    data = PKDecompress(new MemoryStream(data), ExpectedLength);
                }
            }

            return(data);
        }
Example #8
0
        /// <summary>
        /// Lists the contents of the archive.
        /// </summary>
        void ListArchive()
        {
            using(MpqArchive archive = new MpqArchive(archiveFile))
            {
                // setup external listfile if specified
                if(listFile != null && listFile != "")
                    archive.ExternalListFile = listFile;

                Console.WriteLine("ucmp. size   cmp. size   ratio   cmp. type   filename");
                Console.WriteLine("----------   ---------   -----   ---------   --------");

                for(int i = 0; i < archive.Files.Length; i++)
                {
                    MpqArchive.FileInfo fi = archive.Files[i];

                    // match pattern
                    if(regex != null && !regex.Match(fi.Name).Success)
                        continue;

                    string srcFile = fi.Name;
                    if(stripPath)
                        srcFile = Path.GetFileName(srcFile);

                    // display info
                    Console.WriteLine("{0, 10}   {1, 9}   {2, 5}   {3, 9}   {4}",
                                      fi.UncompressedSize, fi.CompressedSize,
                                      CompressionRatioString(fi.UncompressedSize, fi.CompressedSize),
                                      CompressionTypeString(fi.Flags), srcFile);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Extracts files from the archive matching the pattern (if any)
        /// </summary>
        void ExtractArchive()
        {
            using(MpqArchive archive = new MpqArchive(archiveFile))
            {
                // destination directory
                if(destDir == null || destDir == "")
                    destDir = Directory.GetCurrentDirectory();    // default to current dir of not specified

                // setup external listfile if specified
                if(listFile != null && listFile != "")
                    archive.ExternalListFile = listFile;

                // buffers
                byte[] buf = new byte[0x40000];

                if(!quietOutput)
                    Console.WriteLine("Extracting to {0}", destDir);

                for(int i = 0; i < archive.Files.Length; i++)
                {
                    MpqArchive.FileInfo fi = archive.Files[i];

                    // WoW contains a lot of files with Flags & FileHasMetadata
                    //if((fi.Flags & MpqFileFlags.FileHasMetadata) != 0)
                    //    continue;
                    // WoW contains a lot of zero length files with Flags & Unknown_02000000
                    //if((fi.Flags & MpqFileFlags.Unknown_02000000) != 0)
                    //    continue;

                    // match pattern
                    if(regex != null && !regex.Match(fi.Name).Success)
                        continue;

                    if(!quietOutput)
                        Console.Write(fi.Name + " .. ");

                    // create destination directory
                    string srcFile = fi.Name;
                    if(stripPath)
                        srcFile = Path.GetFileName(srcFile);

                    string destFile = Path.Combine(destDir, srcFile);
                    string absDestDir = Path.GetDirectoryName(destFile);
                    CreateDirectory(absDestDir);

                    // copy to destination file
                    using(Stream stmIn = archive.OpenFile(fi.Name))
                    {
                        using(Stream stmOut = new FileStream(destFile, FileMode.Create))
                        {
                            while(true)
                            {
                                int cb = stmIn.Read(buf, 0, buf.Length);
                                if(cb == 0)
                                    break;

                                stmOut.Write(buf, 0, cb);
                            }

                            stmOut.Close();
                        }
                    }

                    if(!quietOutput)
                        Console.WriteLine("Done.");
                }
            }
        }
Example #10
0
 public MpqFileInfo(string mpqPath)
 {
     mpqArchive = new MpqArchive(mpqPath);
 }
Example #11
0
		public static void ProcessMPQ(List<string> lstAllMPQFiles)
		{
			// Create a folder to dump all this into
			Directory.CreateDirectory(DBCOutputDir);

			// Go through all the files, getting all DBCs
			for (int i = 0; i < lstAllMPQFiles.Count; i++)
			{
				using (var oArchive = new MpqArchive(lstAllMPQFiles[i]))
				{
					var dbcsFiles = from a in oArchive.Files
					                                    where a.Name.EndsWith(".dbc")
					                                    select a.Name;

					foreach (var strFileName in dbcsFiles)
					{
						var strLocalFilePath = string.Format(@"{0}\{1}", DBCOutputDir, Path.GetFileName(strFileName));

						// Does it already exist? If it does then it'll be one from a previous package, so let's leave it
						if (!File.Exists(strLocalFilePath))
						{
							using (Stream stmOutput = new FileStream(strLocalFilePath, FileMode.Create))
							{
								using (Stream stmInput = oArchive.OpenFile(strFileName))
								{
									// Writing...
									Console.Write(string.Format("Writing File {0}....", Path.GetFileName(strFileName)));

									// Create an 8kb buffer
									var byFileContents = new byte[8192];

									// Loop until we're out of data
									while (true)
									{
										// Read from the MPQ
										int intBytesRead = stmInput.Read(byFileContents, 0, byFileContents.Length);

										// Was there anything to read?
										if (intBytesRead == 0)
											break;

										// Write to the file
										stmOutput.Write(byFileContents, 0, intBytesRead);
									}
								}

								// Close the File
								stmOutput.Close();

								Console.WriteLine("Done");
							}
						}
					}
				}
			}
		}