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); } }
internal MpqStream(MpqArchive File, MpqBlock Block) { mBlock = Block; mStream = File.BaseStream; mBlockSize = File.BlockSize; if (mBlock.IsCompressed) LoadBlockPositions(); }
internal MpqStream(MpqArchive File, MpqBlock Block) { mBlock = Block; mStream = File.BaseStream; mBlockSize = File.BlockSize; if (mBlock.IsCompressed) { LoadBlockPositions(); } }
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); }
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); } }
// 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 * } */ }
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); }
/// <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); } } }
/// <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."); } } }
public MpqFileInfo(string mpqPath) { mpqArchive = new MpqArchive(mpqPath); }
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"); } } } } } }