Some code that may aid you in creating an actual unpacker or unwrapper:
Yes, this is actual working sources (only partial!!) - and I've chosen to release this publically since EADRM/OriginDRM is more or less dead nowadays anyways...
(The code is crude, and not optimized at all!)
Code:
/// <summary>
/// Struct for OEP & IAT + Version of OriginStub + Par file...
/// </summary>
public struct OriginParameters
{
public OriginVersion VersionDetected;
public OepIatSet OEPnIAT;
public string ParamFileString;
}
/// <summary>
/// Struct for .par file...
/// </summary>
public struct Parameters
{
public string ContentId;
public string InstalledDistro;
public string SupportedDistros;
}
/// <summary>
/// Struct for Version of OriginStub...
/// </summary>
public enum OriginVersion
{
Error = -1,
V1 = 0, //IREW
V2 = 1 //AE64
}
/// <summary>
/// Struct for OEP & IAT...
/// </summary>
public struct OepIatSet
{
public string OEP;
public string IAT;
}
/// <summary>
/// Struct for OEP & IAT + Version of OriginStub + Par file...
/// </summary>
public struct OriginParameters
{
public OriginVersion VersionDetected;
public OepIatSet OEPnIAT;
public string ParamFileString;
}
internal static OriginVersion DetectOriginVersion()
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsDetections::DetectOriginVersion]");
var sOldBytes = Encoding.ASCII.GetBytes("IREW");
var sNewBytes = Encoding.ASCII.GetBytes("AE64");
sFileBytes = File.ReadAllBytes(szFileName);
var fSearch1 = SearchBytes(sFileBytes, sOldBytes, 0L);
if (fSearch1 == -1)
{
fSearch1 = SearchBytes(sFileBytes, sNewBytes, 0L);
if (fSearch1 == -1)
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsDetections::DetectOriginVersion] Returned: " + OriginVersion.Error);
return OriginVersion.Error;
}
else
{
sAddr = fSearch1;
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsDetections::DetectOriginVersion] Returned: " + OriginVersion.V2);
return OriginVersion.V2;
}
}
sAddr = fSearch1;
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsDetections::DetectOriginVersion] Returned: " + OriginVersion.V1);
return OriginVersion.V1;
}
internal static OriginParameters LoadExePar()
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::LoadExePar]");
var myParams = new OriginParameters();
var myOepIat = new OepIatSet();
myParams.VersionDetected = clsDetections.DetectOriginVersion();
var outOEP = "";
var outIAT = "";
clsDetections.GrabOEPnIAT(out outOEP, out outIAT);
myOepIat.IAT = outIAT;
myOepIat.OEP = outOEP;
myParams.OEPnIAT = myOepIat;
myParams.ParamFileString = clsDetections.GetParFile();
myParameters = clsDetections.ReadParameters(myParams.ParamFileString);
myPrvt = myParams;
return myParams;
}
public static bool PatchChecks()
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::PatchChecks]");
//var parCrcCheckBytes = "56 57 E8 ?? ?? ?? ?? 83 C4 08 39 ?? ??"; //Generic to both EXE & DLL
//var requiredToPlayV1Bytes = "83 C4 08 85 C0 0F 94 C3"; //Generic to both EXE & DLL
//var actExe = DetectEACoreExe();
//var actDll = DetectEACoreDll();
//var mFileBytesExe = new byte[1];
//var mFileBytesDll = new byte[1];
clsXor.xorList = clsXor.CreateNewCheckSumTable();
var xorKey = Encoding.ASCII.GetBytes("q@pO3o#5jNA6$sjP3qwe1");
var szParFileName = clsDetections.DetectParFile();
if (szParFileName != String.Empty)
{
var parFileBytes = File.ReadAllBytes(szParFileName);
var bytes4 = new byte[4];
Array.Copy(parFileBytes, 0, bytes4, 0, 4);
if (clsDetections.FirstBytes(bytes4, xorKey))
{
//OLD NO CRC
bwWorker.ReportProgress(0, "[PatchChecks] Returned: PATCHED_PAR_FILE_COMPLETED");
File.WriteAllBytes(szParFileName, AddNoOrigin(Encoding.ASCII.GetString(clsXor.Xor(parFileBytes, xorKey)), false));
return true;
}
else
{
Array.Copy(parFileBytes, 4, bytes4, 0, 4);
if (clsDetections.FirstBytes(bytes4, xorKey))
{
//CRC
var parFileBytes2 = new byte[parFileBytes.Length - 4];
Array.Copy(parFileBytes, 4, parFileBytes2, 0, parFileBytes2.Length);
bwWorker.ReportProgress(0, "[PatchChecks] Returned: PATCHED_PAR_FILE_COMPLETED_CRC_VER");
File.WriteAllBytes(szParFileName, AddNoOrigin(Encoding.ASCII.GetString(clsXor.Xor(parFileBytes, xorKey)), true));
return true;
}
else
{
bwWorker.ReportProgress(0, "[PatchChecks] Returned: FAILED_TO_FIND_XOR_CRC");
return false;
}
}
}
else
{
bwWorker.ReportProgress(0, "[PatchChecks] Returned: FAILED_TO_FIND_PARAMETER_FILE");
return false;
}
//var patchOffsets = new EACorePatch
//{
// crcOffset = -1,
// reqToPlayOffset = -1,
// szActivationFName = String.Empty
//};
//if (actExe != String.Empty) mFileBytesExe = File.ReadAllBytes(actExe);
//else
//{
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: FAILED_TO_READ_EXE_FILE");
// return false;
//}
//if (actDll != String.Empty) mFileBytesDll = File.ReadAllBytes(actDll);
//else
//{
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: FAILED_TO_READ_DLL_FILE");
// return false;
//}
//long fOffset = 0;
//if (Pattern.Find(mFileBytesExe, Pattern.Transform(parCrcCheckBytes), out fOffset))
//{
// for (int i = 0; i < 20; i++)
// {
// if (mFileBytesExe[fOffset + Pattern.Transform(parCrcCheckBytes).Length + i] == 0x74)
// {
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: CRC_JE_FOUND_EXE");
// patchOffsets.crcOffset = fOffset + Pattern.Transform(parCrcCheckBytes).Length + i;
// }
// }
// if (Pattern.Find(mFileBytesExe, Pattern.Transform(requiredToPlayV1Bytes), out fOffset))
// {
// for (int i = 0; i < 20; i++)
// {
// if (mFileBytesExe[fOffset + Pattern.Transform(requiredToPlayV1Bytes).Length + i] == 0x72)
// {
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: REQUIRETOPLAYV1_JB_FOUND_EXE");
// patchOffsets.reqToPlayOffset = fOffset + Pattern.Transform(requiredToPlayV1Bytes).Length + i;
// patchOffsets.szActivationFName = actExe;
// return PatchActivation(patchOffsets, bwWorker);
// }
// }
// }
//}
//else if (Pattern.Find(mFileBytesDll, Pattern.Transform(parCrcCheckBytes), out fOffset))
//{
// for (int i = 0; i < 20; i++)
// {
// if (mFileBytesDll[fOffset + Pattern.Transform(parCrcCheckBytes).Length + i] == 0x74)
// {
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: CRC_JE_FOUND_DLL");
// patchOffsets.crcOffset = fOffset + Pattern.Transform(parCrcCheckBytes).Length + i;
// }
// }
// if (Pattern.Find(mFileBytesDll, Pattern.Transform(requiredToPlayV1Bytes), out fOffset))
// {
// for (int i = 0; i < 20; i++)
// {
// if (mFileBytesDll[fOffset + Pattern.Transform(requiredToPlayV1Bytes).Length + i] == 0x72)
// {
// bwWorker.ReportProgress(0, "[PatchChecks] Returned: REQUIRETOPLAYV1_JB_FOUND_DLL");
// patchOffsets.reqToPlayOffset = fOffset + Pattern.Transform(requiredToPlayV1Bytes).Length + i;
// patchOffsets.szActivationFName = actDll;
// return PatchActivation(patchOffsets, bwWorker);
// }
// }
// }
//}
//bwWorker.ReportProgress(0, "[PatchChecks] Returned: FAILED_TO_FIND_PATCH_PATTERNS");
//return false;
}
internal static string GetLicense()
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::GetLicense]");
var licPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
+ "\\Electronic Arts\\EA Services\\License";
if (myParameters.ContentId.Trim().Contains(","))
{
var a = myParameters.ContentId.Trim().Split(new char[] { ',' });
foreach (var VARIABLE in a)
{
if (File.Exists(licPath + "\\" + VARIABLE.Trim() + ".dlf"))
{
var tmpBytes = File.ReadAllBytes(licPath + "\\" + VARIABLE.Trim() + ".dlf");
var bMore = new BoyerMoore(new byte[] { 0xC0, 0x1E, 0x0F, 0x86, 0xDA, 0xF1, 0xF8, 0x5F }, tmpBytes);
if (bMore.Match() > -1)
{
bwWorker.ReportProgress(0, "[GetLicense] BOYERMOORE_MATCH_FOUND_SIG");
var myArray = new byte[tmpBytes.Length - bMore.Match()];
Array.Copy(tmpBytes, bMore.Match(), myArray, 0, tmpBytes.Length - bMore.Match());
var tmpXml = clsHelpers.ParseXml(clsAes.AesDecrypt(myArray));
bwWorker.ReportProgress(0, "[GetLicense] XML_CIPHERKEY_FOUND");
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::GetLicense] Returned: " + tmpXml.CipherKey);
return tmpXml.CipherKey;
}
}
}
}
else if (File.Exists(licPath + "\\" + myParameters.ContentId.Trim() + ".dlf"))
{
var tmpBytes = File.ReadAllBytes(licPath + "\\" + myParameters.ContentId.Trim() + ".dlf");
var bMore = new BoyerMoore(new byte[] { 0xC0, 0x1E, 0x0F, 0x86, 0xDA, 0xF1, 0xF8, 0x5F }, tmpBytes);
if (bMore.Match() > -1)
{
bwWorker.ReportProgress(0, "[GetLicense] BOYERMOORE_MATCH_FOUND_SIG");
var myArray = new byte[tmpBytes.Length - bMore.Match()];
Array.Copy(tmpBytes, bMore.Match(), myArray, 0, tmpBytes.Length - bMore.Match());
var tmpXml = clsHelpers.ParseXml(clsAes.AesDecrypt(myArray));
bwWorker.ReportProgress(0, "[GetLicense] XML_CIPHERKEY_FOUND");
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::GetLicense] Returned: " + tmpXml.CipherKey);
return tmpXml.CipherKey;
}
}
else
{
bwWorker.ReportProgress(0, "[GetLicense] GAME_NOT_RUN_FIRST");
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " GetLicense] Returned: Game Never Ran before!");
return "ERROR: Run game once first!";
}
bwWorker.ReportProgress(0, "[GetLicense] XML_CIPHERKEY_NOT_FOUND");
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::GetLicense] Returned: NULL");
return string.Empty;
}
internal static byte[] AddNoOrigin(string toFix, bool useChecksum)
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::AddNoOrigin]");
if (!toFix.Contains("RequiredToPlayV1"))
{
var a =
clsXor.Xor(
Encoding.ASCII.GetBytes(
toFix.Replace("InstalledDistro = ", "InstalledDistro = RequiredToPlayV1,")),
Encoding.ASCII.GetBytes("q@pO3o#5jNA6$sjP3qwe1"));
var b = clsXor.Xor2(clsHelpers.CreateCorrectTable(a));
var bitBugA = new byte[1];
if (useChecksum)
{
bitBugA = new byte[a.Length + b.Length];
Array.Copy(b, 0, bitBugA, 0, b.Length);
Array.Copy(a, 0, bitBugA, b.Length, a.Length);
return bitBugA;
}
else
{
return a;
}
}
else
{
var a = clsXor.Xor(Encoding.ASCII.GetBytes(toFix), Encoding.ASCII.GetBytes("q@pO3o#5jNA6$sjP3qwe1"));
var b = clsXor.Xor2(clsHelpers.CreateCorrectTable(a));
var bitBugA = new byte[1];
if (useChecksum)
{
bitBugA = new byte[a.Length + b.Length];
Array.Copy(b, 0, bitBugA, 0, b.Length);
Array.Copy(a, 0, bitBugA, b.Length, a.Length);
return bitBugA;
}
else
{
return a;
}
}
}
internal static bool PatchActivation(EACorePatch patchDetails)
{
Debug.WriteLine(DateTime.Now.ToShortTimeString() + " clsAnalyse::PatchActivation]");
if (patchDetails.crcOffset != -1 && patchDetails.reqToPlayOffset != -1
&& patchDetails.szActivationFName != String.Empty)
{
var mBytes = File.ReadAllBytes(patchDetails.szActivationFName);
File.Copy(patchDetails.szActivationFName, patchDetails.szActivationFName + ".bak", true);
mBytes[patchDetails.crcOffset] = 0xEB;
mBytes[patchDetails.reqToPlayOffset] = 0xEB;
try
{
File.WriteAllBytes(patchDetails.szActivationFName, mBytes);
bwWorker.ReportProgress(0, "[PatchActivation] Returned: FILE_PATCHED_AND_SAVED");
return true;
}
catch (Exception ex)
{
bwWorker.ReportProgress(0, "[PatchActivation] Returned: FILE_PATCH_FAILED (" + ex.Message + ")");
return false;
}
}
bwWorker.ReportProgress(0, "[PatchActivation] Returned: FILE_PATCH_FAILED_MISSING_DETAILS");
return false;
}
As I said earlier in this reply; this code is far from complete, its just something that may or may not help an experienced coder create something they want with - and yes, the code is entirely mine and mine alone ;)
Anywho; use this code as you wish, but credit me if you do :)
|