淘宝新版UA文件混淆函数清晰化处理(C#实现)
淘宝UA文件已更新为63.js,上一篇文章讲述的去数组下标的方法依然适用,但是提取数组元素时的正则表达式需要略作修改。在新版UA文件的起始有n(n),t(n),o(n),a(n)四个函数,这四个函数作用就是混淆,本文记录这4个混淆函数清晰化处理,该方法适用于62和63.
混淆函数清晰化处理仍然用C#来实现。新版UA文件中函数n,t,o,a的参数都是有一个,反混淆方法基本一致,可以用一个函数来反混淆。基本原理是在C#中调用这四个js函数,用它们的执行结果来替代它们在代码中的形式。实现步骤如下:
1. 在当前C#工程中添加MSScriptControl组件
添加方法大家参考httpwatch抓包分析登录淘宝领取淘金币的过程(五)的说明。
2. 修改MSScriptControl属性
手动进行如下操作:解决方案资源管理器–>项目目录–>引用–>MSScriptControl–>属性–>嵌入互操作类型–>改为false,如下图所示:
3. 在当前C#工程中添加 ScriptEngine类
该类支持JScript,VBscript,JavaScript,ScriptEngine类代码可以参考在C#中调用微博密码加密文件ssologin.js。
4.新建一个js文件,将UA文件中的n,t,o,a四个函数拷贝到该文件中。
我给函数命名比较简单粗暴,这个js文件命名为ntoa.js,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
function t(n) { if (!n) return ""; for (var t = "", o = "V587", a = 2333, e = 0; e < n.length; e++) { var u = n.charCodeAt(e); a = (a + 1) % o.length, u ^= o.charCodeAt(a), t += String.fromCharCode(u) } return t } function o(n) { if (!n) return ""; for (var t = "", o = 9527, a = 0; a < n.length; a++) { var e = n.charCodeAt(a), u = e^o; o = e, t += String.fromCharCode(u) } return t } function a(n) { if (!n) return ""; for (var t = "", o = 9527, a = 0; a < n.length; a++) { var e = n.charCodeAt(a), u = e^o; o = o * a % 256 + 2333, t += String.fromCharCode(u) } return t } |
4.用正则表达式找出所有的调用函数n(t,o,a)的地方。
在使用以下正则表达式中,我用NotePad++正则表达式查询的方法大致浏览了函数n,t,o,a的调用方式,基本上都是n{“参数”)的方式(不排除有漏网之鱼,另外误杀的状况也会发生),因此正则表达式就是以该原则为准写的。但是在以下代码中,”\bn\n(\””(.*?)\””\)”),这种方式有一个致命的缺点,就是它会join(“”)也替换掉,这个该怎么解?!我还没有想到合适的方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
static private string replaceFunction(string codeStr) { string contentOut = codeStr; //获取调用函数a("")并用执行结果替代 Regex reg1 = new Regex(@"\ba\(\""(.*?)\""\)"); MatchCollection colMatch = reg1.Matches(contentOut); int arrIndex = colMatch.Count; contentOut = getJsFunResultForOne(colMatch, arrIndex, contentOut, "a"); //获取调用函数n("")并用执行结果替代 reg1 = new Regex(@"\bn\(\""(.*?)\""\)"); colMatch = reg1.Matches(contentOut); arrIndex = colMatch.Count; contentOut = getJsFunResultForOne(colMatch, arrIndex, contentOut, "n"); //获取调用函数n("")并用执行结果替代 reg1 = new Regex(@"\bt\(\""(.*?)\""\)"); colMatch = reg1.Matches(contentOut); arrIndex = colMatch.Count; contentOut = getJsFunResultForOne(colMatch, arrIndex, contentOut, "t"); //获取调用函数n("")并用执行结果替代 reg1 = new Regex(@"\bo\(\""(.*?)\""\)"); colMatch = reg1.Matches(contentOut); arrIndex = colMatch.Count; contentOut = getJsFunResultForOne(colMatch, arrIndex, contentOut, "o"); return contentOut; } |
5.用第4步找到的结果循环调用相应函数并用执行结果替换原函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
static private string getJsFunResultForOne(MatchCollection match, int arrIndex, string strIn, string funName) { string contentOut = strIn; GroupCollection tmpColl = match[0].Groups; string jsFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "ntoa.js"; StreamReader reader = new StreamReader(jsFilePath); string strScript = reader.ReadToEnd(); ScriptEngine.ScriptEngine se = new ScriptEngine.ScriptEngine(ScriptEngine.ScriptLanguage.JavaScript); object[] para = new object[1]; string tmpStr1 = ""; for (int i = 0; i < arrIndex; i++) { tmpColl = match[i].Groups; para[0] = Regex.Unescape(tmpColl[1].Value); tmpStr1 = se.Run(funName, para, strScript).ToString(); contentOut = contentOut.Replace(tmpColl[0].Value, "\"" + tmpStr1 + "\""); } return contentOut; } |
注意点:用正则提取出来的参数是包含转义字符的,若直接将这些转义字符输入到函数,函数会将转义字符也当成字符进行处理,这样是得不到正确结果的。因此提取出来的字符需要调用Regex.Unescape来去除转义部分再作为参数传递给js文件。
除了这四个函数之外,淘宝UA文件还涉及大量的ParseInt函数用来表示一个固定数值。理论上而言,C#中应该有类似的函数来实现该功能,可以用正则表达式提取参数后用C#相应函数得到结果并实现替换。不过我比较懒,直接将ParseInt也写在nota.js文件中,用处理n, t, o, a函数的方法来处理ParseInt,反混淆的方法与上述4个函数大致相同,差异是它有两个参数,对上述函数稍作处理即可。另外文件中部分ParseInt函数调用时,参数由变量组成,而新版UA中变量错综复杂,故ParseInt的混淆作用不能完全清除。
近距离膜拜大神
我也是只正在学习的菜鸟