finished extraction logic

master
VollRagm 4 years ago
parent 6aad238354
commit 2a68816353

@ -12,23 +12,28 @@ namespace apphost_extract
private FileStream FileStream; private FileStream FileStream;
public AppHostFileHeader Header { get; set; } public AppHostFileHeader Header { get; set; }
private const int HEADER_OFFSET_PTR = 0x27600;
public AppHostFile(FileStream fileStream) public AppHostFile(FileStream fileStream)
{ {
FileStream = fileStream; FileStream = fileStream;
Header = new AppHostFileHeader(FileStream);
var buffer = new byte[sizeof(int)];
FileStream.Seek(HEADER_OFFSET_PTR, SeekOrigin.Begin);
FileStream.Read(buffer, 0, buffer.Length);
Header = new AppHostFileHeader(FileStream, BitConverter.ToInt32(buffer, 0));
} }
public static AppHostFile Open(string path) public static AppHostFile Open(string path)
{ {
if (!File.Exists(path)) Log.Fatal("File not found.");
try try
{ {
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite); FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
AppHostFile file = new AppHostFile(fs); AppHostFile file = new AppHostFile(fs);
Log.Info("File opened successfully!");
return file; return file;
} }
catch(Exception ex) catch(Exception ex)
@ -37,5 +42,33 @@ namespace apphost_extract
return null; return null;
} }
} }
public void ExtractAll(string outputDir)
{
Directory.CreateDirectory(outputDir);
foreach (var fileEntry in Header.Manifest.FileEntries)
{
try
{
var bytes = fileEntry.Read();
var name = fileEntry.Name;
var filePath = Path.Combine(outputDir, name);
File.WriteAllBytes(filePath, bytes);
Log.Critical($"Extracted {name}");
}
catch (Exception ex)
{
Log.Error($"Could not extract {fileEntry.Name}: {ex.Message}");
}
}
}
public void Close()
{
FileStream.Close();
}
} }
} }

@ -9,23 +9,39 @@ namespace apphost_extract
{ {
public class AppHostFileEntry public class AppHostFileEntry
{ {
public int Offset { get; set; } public long Offset { get; set; }
public int Size { get; set; } public int Size { get; set; }
public string RelativePath { get; set; } public string Name { get; set; }
private byte[] Raw; private byte[] Raw;
private FileStream FileStream;
private const int FILE_ENTRY_SIZE = 0x12; private const int FILE_ENTRY_SIZE = 0x12;
public AppHostFileEntry(FileStream File) public AppHostFileEntry(FileStream File)
{ {
FileStream = File;
byte[] entryBuffer = new byte[FILE_ENTRY_SIZE]; byte[] entryBuffer = new byte[FILE_ENTRY_SIZE];
File.Read(entryBuffer, 0, entryBuffer.Length); File.Read(entryBuffer, 0, entryBuffer.Length);
Raw = entryBuffer; Raw = entryBuffer;
Offset = BitConverter.ToInt64(Raw, 0);
//hopefully nobody embeds a file larger than 2GB :D
Size = (int)BitConverter.ToInt64(Raw, 0x8);
byte[] stringBuffer = new byte[Raw[0x11]]; byte[] stringBuffer = new byte[Raw[0x11]];
File.Read(stringBuffer, 0, stringBuffer.Length); File.Read(stringBuffer, 0, stringBuffer.Length);
RelativePath = Encoding.UTF8.GetString(stringBuffer); Name = Encoding.UTF8.GetString(stringBuffer);
}
public byte[] Read()
{
//jumps to the offsets and reads the bytes
byte[] buffer = new byte[Size];
FileStream.Seek(Offset, SeekOrigin.Begin);
FileStream.Read(buffer, 0, Size);
return buffer;
} }
} }
} }

@ -9,19 +9,17 @@ namespace apphost_extract
{ {
public class AppHostFileHeader public class AppHostFileHeader
{ {
private const int HEADER_OFFSET = 0x1DE7E2;
private const int HEADER_SIZE = 0xD; private const int HEADER_SIZE = 0xD;
private byte[] Raw; private byte[] Raw;
public string Path { get; set; } public string Path { get; set; }
public int EmbeddedFilesCount { get; set; }
public AppHostManifest Manifest { get; set; } public AppHostManifest Manifest { get; set; }
public AppHostFileHeader(FileStream File) public AppHostFileHeader(FileStream File, int HeaderOffset)
{ {
File.Seek(HEADER_OFFSET, SeekOrigin.Begin); File.Seek(HeaderOffset, SeekOrigin.Begin);
byte[] headerBuffer = new byte[HEADER_SIZE]; byte[] headerBuffer = new byte[HEADER_SIZE];
File.Read(headerBuffer, 0, HEADER_SIZE); File.Read(headerBuffer, 0, HEADER_SIZE);
Raw = headerBuffer; Raw = headerBuffer;
@ -29,8 +27,11 @@ namespace apphost_extract
byte[] stringBuffer = new byte[Raw[0xC]]; byte[] stringBuffer = new byte[Raw[0xC]];
File.Read(stringBuffer, 0, stringBuffer.Length); File.Read(stringBuffer, 0, stringBuffer.Length);
Path = Encoding.UTF8.GetString(stringBuffer); Path = Encoding.UTF8.GetString(stringBuffer);
Log.Info("Header parsed successfully!");
Manifest = new AppHostManifest(File, BitConverter.ToInt32(Raw, 0x8)); Manifest = new AppHostManifest(File, BitConverter.ToInt32(Raw, 0x8));
} }

@ -20,6 +20,9 @@ namespace apphost_extract
AppHostFileEntry entry = new AppHostFileEntry(File); AppHostFileEntry entry = new AppHostFileEntry(File);
entries.Add(entry); entries.Add(entry);
} }
FileEntries = entries.AsReadOnly();
Log.Info("Manifest parsed successfully!");
} }
} }
} }

@ -1,6 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,9 +12,49 @@ namespace apphost_extract
{ {
static void Main(string[] args) static void Main(string[] args)
{ {
string path = "testapp.exe"; Log.Info("apphost-extract by VollRagm\n", ConsoleColor.Yellow);
var file = AppHostFile.Open(path); var path = GetPath(args);
var file = AppHostFile.Open(path.FullName);
Log.Info($"{file.Header.Manifest.FileEntries.Count} embedded file(s) found.");
var directory = Path.Combine(path.DirectoryName, path.Name.Remove(path.Name.Length - path.Extension.Length) +"_extracted");
Console.WriteLine();
Log.Info("Extracting...");
file.ExtractAll(directory);
Console.WriteLine();
Log.Info("Done.");
file.Close();
Console.ReadLine();
}
static FileInfo GetPath(string[] args)
{
try
{
var fileName = new FileInfo(Assembly.GetExecutingAssembly().Location).Name;
if (args.Length > 0)
{
if (File.Exists(args[0]))
{
return new FileInfo(args[0]);
}
else
{
Log.Fatal($"{args[0]} could not be found. Usage: {fileName} <exe-path>");
}
}
else
{
Log.Fatal($"No File provided. Usage: {fileName} <exe-path>");
}
}catch(Exception ex)
{
Log.Fatal($"Could not get file: {ex.Message}");
}
return null;
} }
} }
} }

Loading…
Cancel
Save