mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
implemented key extraction from executable resources for encrypted INT archives.
This commit is contained in:
parent
5a5c10d91a
commit
33e83b196d
@ -27,9 +27,9 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.Composition;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Simias.Encryption;
|
||||
using System.Runtime.InteropServices;
|
||||
using GameRes.Formats.Strings;
|
||||
@ -346,5 +346,82 @@ namespace GameRes.Formats.CatSystem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse certain executable resources for encryption passphrase.
|
||||
/// Returns null if no passphrase found.
|
||||
/// </summary>
|
||||
public static string GetPassFromExe (string filename)
|
||||
{
|
||||
var exe = NativeMethods.LoadLibraryEx (filename, IntPtr.Zero, 0x20); // LOAD_LIBRARY_AS_IMAGE_RESOURCE
|
||||
if (IntPtr.Zero == exe)
|
||||
throw new Win32Exception (Marshal.GetLastWin32Error());
|
||||
try
|
||||
{
|
||||
var code = GetResource (exe, "DATA", "V_CODE2");
|
||||
if (null == code || code.Length < 8)
|
||||
return null;
|
||||
var key = GetResource (exe, "KEY", "KEY_CODE");
|
||||
if (null != key)
|
||||
{
|
||||
for (int i = 0; i < key.Length; ++i)
|
||||
key[i] ^= 0xCD;
|
||||
}
|
||||
else
|
||||
{
|
||||
key = Encoding.ASCII.GetBytes ("windmill");
|
||||
}
|
||||
var blowfish = new Blowfish (key);
|
||||
blowfish.Decipher (code, code.Length/8*8);
|
||||
int length = Array.IndexOf<byte> (code, 0);
|
||||
if (-1 == length)
|
||||
length = code.Length;
|
||||
return Encodings.cp932.GetString (code, 0, length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
NativeMethods.FreeLibrary (exe);
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] GetResource (IntPtr exe, string name, string type)
|
||||
{
|
||||
var res = NativeMethods.FindResource (exe, name, type);
|
||||
if (IntPtr.Zero == res)
|
||||
return null;
|
||||
var glob = NativeMethods.LoadResource (exe, res);
|
||||
if (IntPtr.Zero == glob)
|
||||
return null;
|
||||
uint size = NativeMethods.SizeofResource (exe, res);
|
||||
var src = NativeMethods.LockResource (glob);
|
||||
if (IntPtr.Zero == src)
|
||||
return null;
|
||||
|
||||
var dst = new byte[size];
|
||||
Marshal.Copy (src, dst, 0, dst.Length);
|
||||
return dst;
|
||||
}
|
||||
}
|
||||
|
||||
static internal class NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
static internal extern IntPtr LoadLibraryEx (string lpFileName, IntPtr hReservedNull, uint dwFlags);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
static internal extern bool FreeLibrary (IntPtr hModule);
|
||||
|
||||
[DllImport( "kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
static internal extern IntPtr FindResource (IntPtr hModule, string lpName, string lpType);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true)]
|
||||
static internal extern IntPtr LoadResource (IntPtr hModule, IntPtr hResource);
|
||||
|
||||
[DllImport("Kernel32.dll", SetLastError = true)]
|
||||
static internal extern uint SizeofResource (IntPtr hModule, IntPtr hResource);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
static internal extern IntPtr LockResource (IntPtr hResData);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,21 @@
|
||||
<Grid x:Class="GameRes.Formats.GUI.WidgetINT"
|
||||
<StackPanel x:Class="GameRes.Formats.GUI.WidgetINT"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:s="clr-namespace:GameRes.Formats.Strings"
|
||||
xmlns:fmt="clr-namespace:GameRes.Formats.CatSystem"
|
||||
xmlns:local="clr-namespace:GameRes.Formats.GUI"
|
||||
MaxWidth="260">
|
||||
MaxWidth="280" Orientation="Vertical">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Name="ExeMessage" Grid.Column="0" Text="{x:Static s:arcStrings.INTMessage1}" TextWrapping="Wrap" Margin="0,0,10,10"/>
|
||||
<Button Content="{x:Static s:arcStrings.INTExeButton}" Grid.Column="1" Grid.Row="0" Width="75" Height="25"
|
||||
HorizontalAlignment="Left" Margin="0,0,0,10" Click="Check_Click"/>
|
||||
</Grid>
|
||||
<TextBlock Grid.Column="0" Text="{x:Static s:arcStrings.INTMessage2}" Margin="0,0,0,10" TextWrapping="Wrap"/>
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
<local:KeyConverter x:Key="keyConverter"/>
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
@ -21,13 +32,13 @@
|
||||
<ColumnDefinition MinWidth="130" Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label Content="{x:Static s:arcStrings.INTLabelNumericKey}" Target="{Binding ElementName=Passkey}"
|
||||
Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right"/>
|
||||
<TextBox Name="Passkey" Grid.Column="1" Grid.Row="0" Margin="0,3,0,3">
|
||||
Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right"/>
|
||||
<TextBox Name="Passkey" Grid.Column="1" Grid.Row="2" Margin="0,3,0,3">
|
||||
<TextBox.Text>
|
||||
<Binding Path="Key" Converter="{StaticResource keyConverter}" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
@ -51,9 +62,10 @@
|
||||
<TextBox Name="Passphrase" Grid.Column="1" Grid.Row="1" Margin="0,3,0,3"
|
||||
Text="{Binding Path=Password}"/>
|
||||
<Label Content="{x:Static s:arcStrings.LabelScheme}" Target="{Binding ElementName=EncScheme}"
|
||||
Grid.Column="0" Grid.Row="2" HorizontalAlignment="Right"/>
|
||||
<ComboBox Name="EncScheme" Grid.Column="1" Grid.Row="2" Margin="0,3,0,0"
|
||||
Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right"/>
|
||||
<ComboBox Name="EncScheme" Grid.Column="1" Grid.Row="0" Margin="0,3,0,0"
|
||||
ItemsSource="{Binding Source={x:Static fmt:IntOpener.KnownSchemes}, Path=Keys, Mode=OneWay}"
|
||||
Width="{Binding ElementName=Passkey, Path=ActualWidth}"
|
||||
SelectedValue="{Binding Path=Scheme}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
@ -1,15 +1,42 @@
|
||||
using System;
|
||||
//! \brief Code-behind for INT encryption query widget.
|
||||
//
|
||||
// Copyright (C) 2014-2015 by morkt
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using GameRes.Formats.CatSystem;
|
||||
using GameRes.Formats.Strings;
|
||||
using Microsoft.Win32;
|
||||
using System.Windows;
|
||||
using System.IO;
|
||||
|
||||
namespace GameRes.Formats.GUI
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for WidgetINT.xaml
|
||||
/// </summary>
|
||||
public partial class WidgetINT : Grid
|
||||
public partial class WidgetINT : StackPanel
|
||||
{
|
||||
public WidgetINT ()
|
||||
{
|
||||
@ -51,6 +78,36 @@ namespace GameRes.Formats.GUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Check_Click (object sender, System.Windows.RoutedEventArgs e)
|
||||
{
|
||||
var dlg = new OpenFileDialog {
|
||||
CheckFileExists = true,
|
||||
CheckPathExists = true,
|
||||
Multiselect = false,
|
||||
Title = arcStrings.INTChooseExe,
|
||||
Filter = arcStrings.INTExeFiles+"|*.exe",
|
||||
FilterIndex = 1,
|
||||
InitialDirectory = Directory.GetCurrentDirectory(),
|
||||
};
|
||||
if (!dlg.ShowDialog (Window.GetWindow (this)).Value)
|
||||
return;
|
||||
try
|
||||
{
|
||||
var pass = IntOpener.GetPassFromExe (dlg.FileName);
|
||||
if (null != pass)
|
||||
{
|
||||
this.ExeMessage.Text = arcStrings.INTMessage1;
|
||||
Passphrase.Text = pass;
|
||||
}
|
||||
else
|
||||
this.ExeMessage.Text = string.Format (arcStrings.INTKeyNotFound, Path.GetFileName (dlg.FileName));
|
||||
}
|
||||
catch (Exception X)
|
||||
{
|
||||
this.ExeMessage.Text = X.Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ValueConversion(typeof(uint?), typeof(string))]
|
||||
|
58
ArcFormats/Strings/arcStrings.Designer.cs
generated
58
ArcFormats/Strings/arcStrings.Designer.cs
generated
@ -178,6 +178,15 @@ namespace GameRes.Formats.Strings {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Choose game executable file.
|
||||
/// </summary>
|
||||
public static string INTChooseExe {
|
||||
get {
|
||||
return ResourceManager.GetString("INTChooseExe", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Encrypted archives creation is not implemented..
|
||||
/// </summary>
|
||||
@ -196,6 +205,33 @@ namespace GameRes.Formats.Strings {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Check EXE.
|
||||
/// </summary>
|
||||
public static string INTExeButton {
|
||||
get {
|
||||
return ResourceManager.GetString("INTExeButton", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Executable Files.
|
||||
/// </summary>
|
||||
public static string INTExeFiles {
|
||||
get {
|
||||
return ResourceManager.GetString("INTExeFiles", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Key not found within {0}..
|
||||
/// </summary>
|
||||
public static string INTKeyNotFound {
|
||||
get {
|
||||
return ResourceManager.GetString("INTKeyNotFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Numeric key should be a 32-bit hexadecimal integer.
|
||||
/// </summary>
|
||||
@ -215,9 +251,25 @@ namespace GameRes.Formats.Strings {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive directory is encrypted.
|
||||
///Enter archive encryption key or choose
|
||||
///predefined encryption scheme..
|
||||
/// Looks up a localized string similar to Press "Check EXE" button to look for key within game executable file..
|
||||
/// </summary>
|
||||
public static string INTMessage1 {
|
||||
get {
|
||||
return ResourceManager.GetString("INTMessage1", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Alternatively, enter archive encryption key or choose one of the predefined encryption schemes..
|
||||
/// </summary>
|
||||
public static string INTMessage2 {
|
||||
get {
|
||||
return ResourceManager.GetString("INTMessage2", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Archive directory is encrypted..
|
||||
/// </summary>
|
||||
public static string INTNotice {
|
||||
get {
|
||||
|
@ -161,9 +161,7 @@
|
||||
<value>숫자 값</value>
|
||||
</data>
|
||||
<data name="INTNotice" xml:space="preserve">
|
||||
<value>아카이브 폴더가 암호화됨.
|
||||
아카이브 암호값을 입력하거나
|
||||
미리정의된 암호체계를 고르세요.</value>
|
||||
<value>아카이브 폴더가 암호화됨.</value>
|
||||
</data>
|
||||
<data name="KogadoDescription" xml:space="preserve">
|
||||
<value>Kogado 게임 엔진 리소스 아카이브</value>
|
||||
@ -339,4 +337,28 @@
|
||||
암호값 추측이 실패하였습니다.
|
||||
적절한 암호체계를 선택하세요.</value>
|
||||
</data>
|
||||
<data name="INTChooseExe" xml:space="preserve">
|
||||
<value>Choose game executable file</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
<data name="INTExeButton" xml:space="preserve">
|
||||
<value>Check EXE</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
<data name="INTExeFiles" xml:space="preserve">
|
||||
<value>Executable Files</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
<data name="INTKeyNotFound" xml:space="preserve">
|
||||
<value>Key not found within {0}.</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
<data name="INTMessage1" xml:space="preserve">
|
||||
<value>Press "Check EXE" button to look for key within game executable file.</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
<data name="INTMessage2" xml:space="preserve">
|
||||
<value>Alternatively, enter archive encryption key or choose one of the predefined encryption schemes.</value>
|
||||
<comment>translation pending</comment>
|
||||
</data>
|
||||
</root>
|
@ -161,9 +161,7 @@ Choose appropriate encryption scheme.</value>
|
||||
<value>Numeric key</value>
|
||||
</data>
|
||||
<data name="INTNotice" xml:space="preserve">
|
||||
<value>Archive directory is encrypted.
|
||||
Enter archive encryption key or choose
|
||||
predefined encryption scheme.</value>
|
||||
<value>Archive directory is encrypted.</value>
|
||||
</data>
|
||||
<data name="KogadoDescription" xml:space="preserve">
|
||||
<value>Kogado game engine resource archive</value>
|
||||
@ -342,4 +340,22 @@ Choose appropriate encryption scheme.</value>
|
||||
<data name="QLIEDefaultScheme" xml:space="preserve">
|
||||
<value>Use default encryption scheme</value>
|
||||
</data>
|
||||
<data name="INTChooseExe" xml:space="preserve">
|
||||
<value>Choose game executable file</value>
|
||||
</data>
|
||||
<data name="INTExeButton" xml:space="preserve">
|
||||
<value>Check EXE</value>
|
||||
</data>
|
||||
<data name="INTExeFiles" xml:space="preserve">
|
||||
<value>Executable Files</value>
|
||||
</data>
|
||||
<data name="INTMessage1" xml:space="preserve">
|
||||
<value>Press "Check EXE" button to look for key within game executable file.</value>
|
||||
</data>
|
||||
<data name="INTMessage2" xml:space="preserve">
|
||||
<value>Alternatively, enter archive encryption key or choose one of the predefined encryption schemes.</value>
|
||||
</data>
|
||||
<data name="INTKeyNotFound" xml:space="preserve">
|
||||
<value>Key not found within {0}.</value>
|
||||
</data>
|
||||
</root>
|
@ -148,19 +148,35 @@
|
||||
<data name="DPKKeys" xml:space="preserve">
|
||||
<value>Ключи шифрования</value>
|
||||
</data>
|
||||
<data name="INTChooseExe" xml:space="preserve">
|
||||
<value>Выберите исполняемый файл</value>
|
||||
</data>
|
||||
<data name="INTCreationNotice" xml:space="preserve">
|
||||
<value>Создание зашифрованных архивов не реализовано.</value>
|
||||
</data>
|
||||
<data name="INTExeButton" xml:space="preserve">
|
||||
<value>Искать EXE</value>
|
||||
</data>
|
||||
<data name="INTExeFiles" xml:space="preserve">
|
||||
<value>Исполняемые файлы</value>
|
||||
</data>
|
||||
<data name="INTKeyNotFound" xml:space="preserve">
|
||||
<value>В файле {0} ключа не обнаружено.</value>
|
||||
</data>
|
||||
<data name="INTKeyRequirement" xml:space="preserve">
|
||||
<value>Цифровой ключ должен быть 32-битным шестнадцатиричным числом</value>
|
||||
</data>
|
||||
<data name="INTLabelNumericKey" xml:space="preserve">
|
||||
<value>Цифровой ключ</value>
|
||||
</data>
|
||||
<data name="INTMessage1" xml:space="preserve">
|
||||
<value>Нажмите кнопку "Искать EXE", чтобы попытаться найти ключ в исполняемом файле игры.</value>
|
||||
</data>
|
||||
<data name="INTMessage2" xml:space="preserve">
|
||||
<value>Или же выберите один из известных методов шифрования, либо введите ключ вручную.</value>
|
||||
</data>
|
||||
<data name="INTNotice" xml:space="preserve">
|
||||
<value>Заголовок архива зашифрован.
|
||||
Введите ключ шифрования или выберите
|
||||
один из предопределённых вариантов.</value>
|
||||
<value>Оглавление архива зашифровано.</value>
|
||||
</data>
|
||||
<data name="ISFIgnoreEncryption" xml:space="preserve">
|
||||
<value>Игнорировать шифрование</value>
|
||||
|
Loading…
x
Reference in New Issue
Block a user