我们需要使用DEFLATE算法解压缩Java系统创建的一些数据。我们无法控制。
虽然我们不知道确切的变体,但我们可以使用以下Java代码解压缩发送给我们的数据:
public static String inflateBase64(String base64)
{
try (Reader reader = new InputStreamReader(
new InflaterInputStream(
new ByteArrayInputStream(
Base64.getDecoder().decode(base64)))))
{
StringWriter sw = new StringWriter();
char[] chars = new char[1024];
for (int len; (len = reader.read(chars)) > 0; )
sw.write(chars, 0, len);
return sw.toString();
}
catch (IOException e)
{
System.err.println(e.getMessage());
return "";
}
}
不幸的是,我们的生态系统基于C#。我们目前正在使用Process对象来攻击Java程序,但从性能的角度来看,这显然是次优的,所以我们希望尽可能将上面的代码移植到C#。
一些示例输入和输出:
>java -cp . Deflate -c "Pack my box with five dozen liquor jugs."
eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
>java -cp . Deflate -d eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y
Pack my box with five dozen liquor jugs.
>
我们被告知Java系统符合RFC 1951所以我们已经查看了很多库,但它们似乎都没有正确地解压缩数据(如果有的话)。一个例子是DotNetZip:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ionic.Zlib;
namespace Decomp
{
class Program
{
static void Main(string[] args)
{
// Deflate
String start = "Pack my box with five dozen liquor jugs.";
var x = DeflateStream.CompressString(start);
var res1 = Convert.ToBase64String(x, 0, x.Length);
// Inflate
//String source = "eJwLSEzOVsitVEjKr1AozyzJUEjLLEtVSMmvSs1TyMksLM0vUsgqTS/WAwAm/w6Y"; // *** FAILS ***
String source = "C0hMzlbIrVRIyq9QKM8syVBIyyxLVUjJr0rNU8jJLCzNL1LIKk0v1gMA";
var part1 = Convert.FromBase64String(source);
var res2 = DeflateStream.UncompressString(part1);
}
}
}
这根据文档实现了RFC 1951,但没有正确解密字符串(可能是由于实现之间的微妙算法差异)。
从开发的角度来看,我们可以理解我们需要编写的确切变体。是否有任何标题信息或在线工具可用于提供初始转向?感觉就像我们在这里的黑暗中拍摄一样。
https://www.nuget.org/packages/ICSharpCode.SharpZipLib.dll/
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using System;
using System.IO;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
string input = "Pack my box with five dozen liquor jugs.";
string encoded = Encode(input);
string decoded = Decode(encoded);
Console.WriteLine($"Input: {input}");
Console.WriteLine($"Encoded: {encoded}");
Console.WriteLine($"Decoded: {decoded}");
Console.ReadKey(true);
}
static string Encode(string text)
{
byte[] bytes = Encoding.UTF8.GetBytes(text);
using (MemoryStream inms = new MemoryStream(bytes))
{
using (MemoryStream outms = new MemoryStream())
{
using (DeflaterOutputStream dos = new DeflaterOutputStream(outms))
{
inms.CopyTo(dos);
dos.Finish();
byte[] encoded = outms.ToArray();
return Convert.ToBase64String(encoded);
}
}
}
}
static string Decode(string base64)
{
byte[] bytes = Convert.FromBase64String(base64);
using (MemoryStream ms = new MemoryStream(bytes))
{
using (InflaterInputStream iis = new InflaterInputStream(ms))
{
using (StreamReader sr = new StreamReader(iis))
{
return sr.ReadToEnd();
}
}
}
}
}
}