最近又遇到 ODP.NET 版本問題。(警告:本文涉及邪門歪道雞鳴狗盜之技,正義魔人與衛道人士請自行迴避)

古老 ASP.NET 網站參照 ODP.NET 9207 版,移到 x64 平台必須改用新版 ODP.NET,而 ODP.NET 存在版號從 9.2 10.1 降回 2.102 的鬼問題,新版號比舊版號數字小在某些情況下會讓「bindingRedirect 大絕」破功。很無奈,必須調整參照版號才能解決,重新取原始檔編譯太麻煩,於是我找到 ildasm 反組譯成 MSIL 程式碼,修改參數版號再 ilasm 編譯回 DLL 的奧步妙招,後來更進一步寫了自動化懶人工具

多年後再遇老茶包,遇上小麻煩。由於古老網站採用 .NET 2.0,發現在 Windows 8.1 平台上就算用 .NET 2.0 SDK ilasm 編譯出的 DLL 還是 .NET 4 版本,得翻出老機器用 VS2008 開發環境處理才能產出 .NET 2.0 版本。另一方面,網站為 Web Site Project 使用部署專案編譯成一個資料夾一顆 DLL,換句話說,總共有數十個 DLL 要處理。沒耐性的我又動起歪腦筋,索性不要 ildasm / ilasm 了,直接將 DLL 裡的 ODP.NET 版號資料改掉更快。

於是,花十分鐘寫了以下工具,用二進位資料比對的方法 1 秒鐘內把數十個 DLL 的 ODP.NET 版號從 9.2.0.700 換成 2.112.3.0!與之前一個個 DLL ildasm/ilasm 的繁瑣過程相比,威力直逼核武等級呀~

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace OdpNet9207RefFixer
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var file in Directory.GetFiles("x:\\src-bin", "*.dll"))
            {
                byte[] buff = File.ReadAllBytes(file);
                var idx = 0;
                var foundCount = 0;
                while (idx < buff.Length - 8)
                {
                    if (buff[idx] == 9 && buff[idx + 1] == 0 &&
                        buff[idx + 2] == 2 && buff[idx + 3] == 0 &&
                        buff[idx + 4] == 0 && buff[idx + 5] == 0 &&
                        buff[idx + 6] == 0xbc && buff[idx + 7] == 0x02
                        )
                    {
                        buff[idx] = 2;
                        buff[idx + 2] = 112;
                        buff[idx + 4] = 3;
                        buff[idx + 6] = 0;
                        buff[idx + 7] = 0;
                        foundCount++;
                    }
                    idx++;
                }
                if (foundCount == 1)
                {
                    File.WriteAllBytes(file.Replace("src-bin\\", "fixed-bin\\"), buff);
                }
            }
        }
    }
}

這個做法的風險在於誤判,若好死不死 DLL 裡程式碼或資源的二進位資料剛好組成 0x090002000000bc02 就會被錯換,因此我加了一道保險,若在 DLL 中發現一處以上吻合,就不進行置換。所幸 9.2.0.700 這串內容夠特殊,一般程式內容撞上的機率不高,故不再投資心力閃避,而是補上事後使用 JustDecompile 檢查參照版號做為第二道防線,降低誤改風險。

就這樣,原本預估要花個把小時處理的 ODP.NET 參照修改問題,花了幾分鐘便搞定。

奧步雖然可恥但有用~ XD


Comments

Be the first to post a comment

Post a comment